From a475e693dc0ac9d37afa908981a3f76bf7aea600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 10:11:55 +0800 Subject: [PATCH 01/40] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=83=A8=E9=97=A8=E6=98=BE=E7=A4=BA=E6=95=B0?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-department/index.tsx | 61 ++++++++++++++++++++++-- src/pages/course/index.tsx | 1 + src/pages/member/index.tsx | 1 + 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 573105a..8d96ab1 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -11,6 +11,7 @@ interface Option { interface PropInterface { type: string; text: string; + showNum: boolean; onUpdate: (keys: any, title: any) => void; } @@ -18,14 +19,26 @@ export const TreeDepartment = (props: PropInterface) => { const [treeData, setTreeData] = useState([]); const [loading, setLoading] = useState(true); const [selectKey, setSelectKey] = useState([]); + const [total, setTotal] = useState(0); + useEffect(() => { setLoading(true); department.departmentList().then((res: any) => { const departments = res.data.departments; - + const departCount = res.data.dep_user_count; if (JSON.stringify(departments) !== "{}") { - const new_arr: Option[] = checkArr(departments, 0); - setTreeData(new_arr); + if (props.showNum) { + const new_arr: any = checkNewArr(departments, 0, departCount); + setTreeData(new_arr); + let num = 0; + for (let item in departCount) { + num = num + Number(item); + } + setTotal(num); + } else { + const new_arr: Option[] = checkArr(departments, 0); + setTreeData(new_arr); + } } else { const new_arr: Option[] = [ { @@ -40,6 +53,38 @@ export const TreeDepartment = (props: PropInterface) => { }); }, []); + const checkNewArr = (departments: any[], id: number, counts: any) => { + const arr = []; + for (let i = 0; i < departments[id].length; i++) { + if (!departments[departments[id][i].id]) { + arr.push({ + title: getNewTitle( + departments[id][i].name, + departments[id][i].id, + counts + ), + key: departments[id][i].id, + }); + } else { + const new_arr: any = checkNewArr( + departments, + departments[id][i].id, + counts + ); + arr.push({ + title: getNewTitle( + departments[id][i].name, + departments[id][i].id, + counts + ), + key: departments[id][i].id, + children: new_arr, + }); + } + } + return arr; + }; + const checkArr = (departments: any[], id: number) => { const arr = []; for (let i = 0; i < departments[id].length; i++) { @@ -60,6 +105,15 @@ export const TreeDepartment = (props: PropInterface) => { return arr; }; + const getNewTitle = (title: any, id: number, counts: any) => { + if (counts) { + let value = counts[id] || 0; + return title + "(" + value + ")"; + } else { + return title; + } + }; + const onSelect = (selectedKeys: any, info: any) => { let label = "全部" + props.text; if (info) { @@ -89,6 +143,7 @@ export const TreeDepartment = (props: PropInterface) => { onClick={() => onSelect([], "")} > 全部{props.text} + {props.showNum && total ? "(" + total + ")" : ""} {treeData.length > 0 && ( { children: (
{ diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index 34b5641..9e60c1b 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -200,6 +200,7 @@ const MemberPage = () => {
{ From 9dadb9818ddb72ad5bc6e97aef8ded10c13cd555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 11:03:11 +0800 Subject: [PATCH 02/40] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AD=A6=E5=91=98=E9=BB=98=E8=AE=A4=E5=A4=B4=E5=83=8F=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/system/config/index.tsx | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/pages/system/config/index.tsx b/src/pages/system/config/index.tsx index 3c4447d..69d4568 100644 --- a/src/pages/system/config/index.tsx +++ b/src/pages/system/config/index.tsx @@ -23,6 +23,7 @@ const SystemConfigPage = () => { const [loading, setLoading] = useState(false); const [logo, setLogo] = useState(""); const [thumb, setThumb] = useState(""); + const [avatar, setAvatar] = useState(""); const [tabKey, setTabKey] = useState(1); const [nameChecked, setNameChecked] = useState(false); const [emailChecked, setEmailChecked] = useState(false); @@ -103,6 +104,11 @@ const SystemConfigPage = () => { form.setFieldsValue({ "system.pc_index_footer_msg": configData[i].key_value, }); + } else if (configData[i].key_name === "member.default_avatar") { + setAvatar(configData[i].key_value); + form.setFieldsValue({ + "member.default_avatar": configData[i].key_value, + }); } } }); @@ -411,6 +417,79 @@ const SystemConfigPage = () => { ), }, + { + key: "3", + label: `学员设置`, + children: ( +
+ {avatar && ( + +
+ +
+ { + setAvatar(url); + form.setFieldsValue({ "member.default_avatar": url }); + }} + > +
(新学员的默认头像)
+
+
+
+ )} + {!avatar && ( + +
+
+ { + setAvatar(url); + form.setFieldsValue({ "member.default_avatar": url }); + }} + > +
(新学员的默认头像)
+
+
+
+ )} + + + +
+ ), + }, ]; const onChange = (key: string) => { From 23d16b52dd863d0caadb34f0d83fd25cc8e79d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 11:12:45 +0800 Subject: [PATCH 03/40] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=83=A8=E9=97=A8=E6=98=BE=E7=A4=BA=E6=95=B0?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-department/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 8d96ab1..4ea497d 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -32,7 +32,8 @@ export const TreeDepartment = (props: PropInterface) => { setTreeData(new_arr); let num = 0; for (let item in departCount) { - num = num + Number(item); + num = num + Number(departCount[item]); + } setTotal(num); } else { From 36a24ae87fb02a09305179369ffd1d9cbfe68404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 11:19:15 +0800 Subject: [PATCH 04/40] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=BB=9A=E5=88=B0?= =?UTF-8?q?=E5=88=B0=E9=A1=B6=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AutoTop.ts | 12 ++++++++++++ src/main.tsx | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/AutoTop.ts diff --git a/src/AutoTop.ts b/src/AutoTop.ts new file mode 100644 index 0000000..f3a29ea --- /dev/null +++ b/src/AutoTop.ts @@ -0,0 +1,12 @@ +import { useLayoutEffect } from "react"; +import { useLocation } from "react-router-dom"; + +const AutoScorllTop = ({ children }) => { + const location = useLocation(); + useLayoutEffect(() => { + document.documentElement.scrollTo(0, 0); + }, [location.pathname]); + return children; +}; + +export default AutoScorllTop; diff --git a/src/main.tsx b/src/main.tsx index 16f96ee..98bf043 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,6 +7,7 @@ import { Provider } from "react-redux"; import store from "./store"; import { ConfigProvider } from "antd"; import zhCN from "antd/locale/zh_CN"; +import AutoScorllTop from "./AutoTop"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( @@ -15,7 +16,9 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( theme={{ token: { colorPrimary: "#ff4d4f" } }} > - + + + From e57ef9ce46f831a364a22c6f5bfce23d1f906c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 14:27:45 +0800 Subject: [PATCH 05/40] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=BB=9A=E5=88=B0?= =?UTF-8?q?=E5=88=B0=E9=A1=B6=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AutoTop.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AutoTop.ts b/src/AutoTop.ts index f3a29ea..fc8efa6 100644 --- a/src/AutoTop.ts +++ b/src/AutoTop.ts @@ -1,7 +1,8 @@ +import React from "react"; import { useLayoutEffect } from "react"; import { useLocation } from "react-router-dom"; -const AutoScorllTop = ({ children }) => { +const AutoScorllTop: React.FC<{ children: any }> = ({ children }) => { const location = useLocation(); useLayoutEffect(() => { document.documentElement.scrollTo(0, 0); From 016f5b4a7097e987a4bb8f306c73d463b75b1e03 Mon Sep 17 00:00:00 2001 From: none Date: Mon, 17 Apr 2023 15:55:51 +0800 Subject: [PATCH 06/40] =?UTF-8?q?=E4=BC=98=E5=8C=96docker=E7=BC=96?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6336b7b..c7ea6b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,13 @@ +FROM node:lts-slim as builder + +WORKDIR /app + +COPY . /app + +RUN yarn config set registry https://registry.npm.taobao.org && yarn && yarn build + FROM nginx:1.23.4-alpine-slim -COPY dist /usr/share/nginx/html +COPY --from=builder /app/dist /usr/share/nginx/html -COPY docker/nginx.conf /etc/nginx/nginx.conf +COPY --from=builder /app/docker/nginx.conf /etc/nginx/nginx.conf \ No newline at end of file From c0e9e5bd5cb6b4896cf05cad76ccd4a9d34d4892 Mon Sep 17 00:00:00 2001 From: none Date: Mon, 17 Apr 2023 16:05:23 +0800 Subject: [PATCH 07/40] docker --- .dockerignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..57d3105 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +/node_modules +/build +/dist \ No newline at end of file From c01de5b51b83a9285b2aadd47076c87515061747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Mon, 17 Apr 2023 17:25:57 +0800 Subject: [PATCH 08/40] =?UTF-8?q?=E9=80=80=E5=87=BA=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/header/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compenents/header/index.tsx b/src/compenents/header/index.tsx index 8953bd2..9295311 100644 --- a/src/compenents/header/index.tsx +++ b/src/compenents/header/index.tsx @@ -5,6 +5,7 @@ import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import avatar from "../../assets/images/commen/avatar.png"; import { logoutAction } from "../../store/user/loginUserSlice"; +import { clearToken } from "../../utils/index"; export const Header: React.FC = () => { const dispatch = useDispatch(); @@ -13,6 +14,7 @@ export const Header: React.FC = () => { const onClick: MenuProps["onClick"] = ({ key }) => { if (key === "login_out") { + clearToken(); dispatch(logoutAction()); navigate("/login"); } else if (key === "change_password") { From f5ad3a4eb2bbcc70039295898e0796b3f7869cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Wed, 19 Apr 2023 11:17:19 +0800 Subject: [PATCH 09/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/user.ts | 30 +++ src/pages/member/index.tsx | 17 +- src/pages/member/learn.module.less | 15 ++ src/pages/member/learn.tsx | 320 +++++++++++++++++++++++++++++ src/routes/index.tsx | 7 +- 5 files changed, 387 insertions(+), 2 deletions(-) create mode 100644 src/pages/member/learn.module.less create mode 100644 src/pages/member/learn.tsx diff --git a/src/api/user.ts b/src/api/user.ts index 169dd87..27682c9 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -78,3 +78,33 @@ export function storeBatch(startLine: number, users: string[][]) { users: users, }); } + +export function learnStats(id: number) { + return client.get(`/backend/v1/user/${id}/learn-stats`, {}); +} + +export function learnHours( + id: number, + page: number, + size: number, + params: object +) { + return client.get(`/backend/v1/user/${id}/learn-hours`, { + page, + size, + ...params, + }); +} + +export function learnCourses( + id: number, + page: number, + size: number, + params: object +) { + return client.get(`/backend/v1/user/${id}/learn-courses`, { + page, + size, + ...params, + }); +} diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index 9e60c1b..be3b66e 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -14,7 +14,7 @@ import type { ColumnsType } from "antd/es/table"; import { PlusOutlined, ExclamationCircleFilled } from "@ant-design/icons"; import { user } from "../../api/index"; import { dateFormat } from "../../utils/index"; -import { Link } from "react-router-dom"; +import { Link, Navigate } from "react-router-dom"; import { TreeDepartment, PerButton } from "../../compenents"; import { MemberCreate } from "./compenents/create"; import { MemberUpdate } from "./compenents/update"; @@ -99,6 +99,21 @@ const MemberPage = () => { width: 160, render: (_, record: any) => ( + + null} + disabled={null} + /> + +
{ + let chartRef = useRef(null); + const result = new URLSearchParams(useLocation().search); + const [loading, setLoading] = useState(false); + const [page, setPage] = useState(1); + const [size, setSize] = useState(10); + const [list, setList] = useState([]); + const [hours, setHours] = useState({}); + const [total, setTotal] = useState(0); + const [refresh, setRefresh] = useState(false); + const [loading2, setLoading2] = useState(false); + const [page2, setPage2] = useState(1); + const [size2, setSize2] = useState(10); + const [list2, setList2] = useState([]); + const [courses, setCourses] = useState({}); + const [total2, setTotal2] = useState(0); + const [refresh2, setRefresh2] = useState(false); + const [uid, setUid] = useState(Number(result.get("id"))); + + useEffect(() => { + getZxtData(); + return () => { + window.onresize = null; + }; + }, [uid]); + + useEffect(() => { + getLearnHours(); + }, [refresh, page, size]); + + useEffect(() => { + getLearnCourses(); + }, [refresh2, page2, size2]); + + const getZxtData = () => { + member.learnStats(uid).then((res: any) => { + renderView(res.data); + }); + }; + + const renderView = (params: any) => { + const timeData: any = []; + const valueData: any = []; + params.map((item: any) => { + timeData.push(item.key); + valueData.push(item.value / 1000); + }); + let dom: any = chartRef.current; + let myChart = echarts.init(dom); + myChart.setOption({ + tooltip: { + trigger: "axis", + }, + legend: { + data: ["每日学习时长"], + x: "right", + }, + grid: { + left: "3%", + right: "4%", + bottom: "3%", + containLabel: true, + }, + xAxis: { + type: "category", + boundaryGap: false, + data: timeData, + }, + yAxis: { + type: "value", + }, + series: [ + { + name: "每日学习时长(秒)", + type: "line", + data: valueData, + }, + ], + }); + window.onresize = () => { + myChart.resize(); + }; + }; + + const getLearnHours = () => { + if (loading) { + return; + } + setLoading(true); + member + .learnHours(uid, page, size, { + sort_field: "", + sort_algo: "", + is_finished: "", + }) + .then((res: any) => { + setList(res.data.data); + setHours(res.data.hours); + setTotal(res.data.total); + setLoading(false); + }); + }; + + const getLearnCourses = () => { + if (loading2) { + return; + } + setLoading2(true); + member + .learnCourses(uid, page2, size2, { + sort_field: "", + sort_algo: "", + is_finished: "", + }) + .then((res: any) => { + setList2(res.data.data); + setCourses(res.data.courses); + setTotal2(res.data.total); + setLoading2(false); + }); + }; + + const paginationProps = { + current: page, //当前页码 + pageSize: size, + total: total, // 总条数 + onChange: (page: number, pageSize: number) => + handlePageChange(page, pageSize), //改变页码的函数 + showSizeChanger: true, + }; + + const handlePageChange = (page: number, pageSize: number) => { + setPage(page); + setSize(pageSize); + }; + + const paginationProps2 = { + current: page2, //当前页码 + pageSize: size2, + total: total2, // 总条数 + onChange: (page: number, pageSize: number) => + handlePageChange2(page, pageSize), //改变页码的函数 + showSizeChanger: true, + }; + + const handlePageChange2 = (page: number, pageSize: number) => { + setPage2(page); + setSize2(pageSize); + }; + + const columns: ColumnsType = [ + { + title: "课时标题", + dataIndex: "title", + render: (_, record: any) => ( + <> + {hours[record.hour_id].title} + + ), + }, + { + title: "课时类型", + dataIndex: "type", + render: (_, record: any) => ( + <> + {hours[record.hour_id].type} + + ), + }, + { + title: "总时长", + dataIndex: "total_duration", + render: (_, record: any) => ( + <> + + + ), + }, + { + title: "已学习时长", + dataIndex: "finished_duration", + render: (_, record: any) => ( + <> + + + ), + }, + { + title: "状态", + dataIndex: "is_finished", + render: (_, record: any) => ( + <> + {record.is_finished === 1 ? 已学完 : 未学完} + + ), + }, + { + title: "时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, + }, + ]; + + const column2: ColumnsType = [ + { + title: "课程", + dataIndex: "title", + render: (_, record: any) => ( +
+ + {courses[record.course_id].title} +
+ ), + }, + { + title: "总课时", + dataIndex: "total_duration", + render: (_, record: any) => ( + <> + {record.hour_count} + + ), + }, + { + title: "已学习课时", + dataIndex: "finished_duration", + render: (_, record: any) => ( + <> + {record.finished_count} + + ), + }, + { + title: "状态", + dataIndex: "is_finished", + render: (_, record: any) => ( + <> + {record.is_finished === 1 ? 已学完 : 未学完} + + ), + }, + { + title: "时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, + }, + ]; + + return ( + <> + +
+ +
+
学习时长统计
+
+
+
+
+
+
课时学习记录
+
+ record.id} + /> + + +
+
线上课学习记录
+
+
record.id} + /> + + + + ); +}; +export default MemberLearnPage; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 42e9f92..620cbe6 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -16,6 +16,7 @@ import CoursePage from "../pages/course/index"; import CourseUserPage from "../pages/course/user"; import MemberPage from "../pages/member"; import MemberImportPage from "../pages/member/import"; +import MemberLearnPage from "../pages/member/learn"; import SystemConfigPage from "../pages/system/config"; import SystemAdministratorPage from "../pages/system/administrator"; import SystemAdminrolesPage from "../pages/system/adminroles"; @@ -32,7 +33,7 @@ if (getToken()) { try { let configRes: any = await system.getSystemConfig(); let userRes: any = await login.getUser(); - + resolve({ default: ( @@ -98,6 +99,10 @@ const routes: RouteObject[] = [ path: "/member/import", element: , }, + { + path: "/member/learn", + element: , + }, { path: "/system/config/index", element: , From 2a2a091144b45615371d60bcd9d7c669bd80eda2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Wed, 19 Apr 2023 12:08:11 +0800 Subject: [PATCH 10/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/user.ts | 13 + src/pages/member/departmentUser.module.less | 0 src/pages/member/departmentUser.tsx | 254 ++++++++++++++++++++ src/pages/member/index.tsx | 16 ++ src/pages/member/learn.tsx | 4 +- src/routes/index.tsx | 5 + 6 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/pages/member/departmentUser.module.less create mode 100644 src/pages/member/departmentUser.tsx diff --git a/src/api/user.ts b/src/api/user.ts index 27682c9..c1165e1 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -108,3 +108,16 @@ export function learnCourses( ...params, }); } + +export function departmentProgress( + id: number, + page: number, + size: number, + params: object +) { + return client.get(`/backend/v1/department/${id}/users`, { + page, + size, + ...params, + }); +} diff --git a/src/pages/member/departmentUser.module.less b/src/pages/member/departmentUser.module.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx new file mode 100644 index 0000000..9550f5e --- /dev/null +++ b/src/pages/member/departmentUser.tsx @@ -0,0 +1,254 @@ +import { useState, useEffect, useRef } from "react"; +import styles from "./learn.module.less"; +import { + Typography, + Input, + Modal, + Image, + Button, + Space, + message, + Table, +} from "antd"; +import { useNavigate, useLocation } from "react-router-dom"; +import { BackBartment, DurationText } from "../../compenents"; +import { dateFormat } from "../../utils/index"; +import { user as member } from "../../api/index"; +const { Column, ColumnGroup } = Table; + +interface DataType { + id: React.Key; + title: string; + type: string; + created_at: string; + total_duration: number; + finished_duration: number; + is_finished: boolean; +} + +const MemberDepartmentProgressPage = () => { + const result = new URLSearchParams(useLocation().search); + const [loading, setLoading] = useState(false); + const [page, setPage] = useState(1); + const [size, setSize] = useState(10); + const [list, setList] = useState([]); + const [total, setTotal] = useState(0); + const [refresh, setRefresh] = useState(false); + const [courses, setCourses] = useState([]); + const [records, setRecords] = useState({}); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [id_card, setIdCard] = useState(""); + const [did, setDid] = useState(Number(result.get("id"))); + + useEffect(() => { + getData(); + }, [refresh, page, size, name, email, id_card]); + + const getData = () => { + if (loading) { + return; + } + setLoading(true); + member + .departmentProgress(did, page, size, { + sort_field: "", + sort_algo: "", + name: name, + email: email, + id_card: id_card, + }) + .then((res: any) => { + setList(res.data.data); + setTotal(res.data.total); + let data = res.data.courses; + let arr = []; + for (let key in data) { + arr.push(data[key]); + } + setCourses(arr); + setRecords(res.data.user_course_records); + setLoading(false); + }); + }; + + const resetData = () => { + setName(""); + setEmail(""); + setIdCard(""); + setPage(1); + setSize(10); + setList([]); + setRefresh(!refresh); + }; + + const paginationProps = { + current: page, //当前页码 + pageSize: size, + total: total, // 总条数 + onChange: (page: number, pageSize: number) => + handlePageChange(page, pageSize), //改变页码的函数 + showSizeChanger: true, + }; + + const handlePageChange = (page: number, pageSize: number) => { + setPage(page); + setSize(pageSize); + }; + + const getTotalHours = (params: any) => { + if (params) { + let value = 0; + for (let key in params) { + value += params[key].hour_count; + } + return value; + } else { + return 0; + } + }; + + const getFinishedHours = (params: any) => { + if (params) { + let value = 0; + for (let key in params) { + value += params[key].finished_count; + } + return value; + } else { + return 0; + } + }; + + return ( +
+
+ +
+
+
+
+ 姓名: + { + setName(e.target.value); + }} + style={{ width: 160 }} + placeholder="请输入姓名关键字" + /> +
+
+ 邮箱: + { + setEmail(e.target.value); + }} + style={{ width: 160 }} + placeholder="请输入邮箱" + /> +
+
+ 身份证号: + { + setIdCard(e.target.value); + }} + style={{ width: 160 }} + placeholder="请输入身份证号" + /> +
+
+ + +
+
+
+
+
record.id} + > + ( + <> + + {record.name} + + )} + /> + {courses.map((item: any) => ( + + ( + <> + {records[record.id] && records[record.id][item.id] ? ( + {records[record.id][item.id].finished_count} + ) : ( + 0 + )} + + )} + /> + ( + <> + {item.class_hour} + + )} + /> + + ))} + + ( + <>{getFinishedHours(records[record.id])} + )} + /> + ( + <>{getTotalHours(records[record.id])} + )} + /> + +
+
+
+ ); +}; +export default MemberDepartmentProgressPage; diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index be3b66e..7623792 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -250,6 +250,22 @@ const MemberPage = () => { disabled={null} /> + {dep_ids.length > 0 && ( + + null} + disabled={null} + /> + + )}
diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index 3b36d49..cac04e0 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useRef } from "react"; import styles from "./learn.module.less"; -import { Row, Col, Image, message, Table } from "antd"; -import { useNavigate, useLocation } from "react-router-dom"; +import { Row, Image, Table } from "antd"; +import { useLocation } from "react-router-dom"; import { BackBartment, DurationText } from "../../compenents"; import { dateFormat } from "../../utils/index"; import { user as member } from "../../api/index"; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 620cbe6..2f1ee5d 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -17,6 +17,7 @@ import CourseUserPage from "../pages/course/user"; import MemberPage from "../pages/member"; import MemberImportPage from "../pages/member/import"; import MemberLearnPage from "../pages/member/learn"; +import MemberDepartmentProgressPage from "../pages/member/departmentUser"; import SystemConfigPage from "../pages/system/config"; import SystemAdministratorPage from "../pages/system/administrator"; import SystemAdminrolesPage from "../pages/system/adminroles"; @@ -103,6 +104,10 @@ const routes: RouteObject[] = [ path: "/member/learn", element: , }, + { + path: "/member/departmentUser", + element: , + }, { path: "/system/config/index", element: , From 30785497d3170942c7616270bedb1dc36a873277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Wed, 19 Apr 2023 13:40:12 +0800 Subject: [PATCH 11/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index 9550f5e..a939d52 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -36,6 +36,7 @@ const MemberDepartmentProgressPage = () => { const [refresh, setRefresh] = useState(false); const [courses, setCourses] = useState([]); const [records, setRecords] = useState({}); + const [totalHour, setTotalHour] = useState(0); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [id_card, setIdCard] = useState(""); @@ -63,10 +64,13 @@ const MemberDepartmentProgressPage = () => { setTotal(res.data.total); let data = res.data.courses; let arr = []; + let value = 0; for (let key in data) { arr.push(data[key]); + value += data[key].class_hour; } setCourses(arr); + setTotalHour(value); setRecords(res.data.user_course_records); setLoading(false); }); @@ -241,9 +245,7 @@ const MemberDepartmentProgressPage = () => { title="总课时" dataIndex="class_hour" key="class_hour" - render={(_, record: any) => ( - <>{getTotalHours(records[record.id])} - )} + render={(_, record: any) => {totalHour}} /> From b616335d1897e00ab1d754468a2e05ced530b7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Wed, 19 Apr 2023 13:43:05 +0800 Subject: [PATCH 12/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index a939d52..1f4d695 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -1,5 +1,5 @@ -import { useState, useEffect, useRef } from "react"; -import styles from "./learn.module.less"; +import { useState, useEffect } from "react"; +import styles from "./departmentUser.module.less"; import { Typography, Input, From 6c923e17569528afbd34b8318b7b8961fa81e970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Wed, 19 Apr 2023 16:12:37 +0800 Subject: [PATCH 13/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=85=A8=E9=83=A8=E4=BA=BA=E6=95=B0=E6=B8=B2?= =?UTF-8?q?=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-department/index.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 4ea497d..000d665 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -19,23 +19,18 @@ export const TreeDepartment = (props: PropInterface) => { const [treeData, setTreeData] = useState([]); const [loading, setLoading] = useState(true); const [selectKey, setSelectKey] = useState([]); - const [total, setTotal] = useState(0); + const [userTotal, setUserTotal] = useState(0); useEffect(() => { setLoading(true); department.departmentList().then((res: any) => { const departments = res.data.departments; const departCount = res.data.dep_user_count; + setUserTotal(res.data.user_total); if (JSON.stringify(departments) !== "{}") { if (props.showNum) { const new_arr: any = checkNewArr(departments, 0, departCount); setTreeData(new_arr); - let num = 0; - for (let item in departCount) { - num = num + Number(departCount[item]); - - } - setTotal(num); } else { const new_arr: Option[] = checkArr(departments, 0); setTreeData(new_arr); @@ -144,7 +139,7 @@ export const TreeDepartment = (props: PropInterface) => { onClick={() => onSelect([], "")} > 全部{props.text} - {props.showNum && total ? "(" + total + ")" : ""} + {props.showNum && userTotal ? "(" + userTotal + ")" : ""}
{treeData.length > 0 && ( Date: Wed, 19 Apr 2023 16:50:43 +0800 Subject: [PATCH 14/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E5=88=97=E8=A1=A8=E7=AD=9B=E9=80=89=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index 1f4d695..b3a4ead 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -44,7 +44,7 @@ const MemberDepartmentProgressPage = () => { useEffect(() => { getData(); - }, [refresh, page, size, name, email, id_card]); + }, [refresh, page, size]); const getData = () => { if (loading) { From a71be154d844b5400d1c17484ae64d90e5a0a56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 09:36:05 +0800 Subject: [PATCH 15/40] =?UTF-8?q?=E7=99=BB=E5=BD=95=E8=B7=B3=E8=BD=AC?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=BB=84=E4=BB=B6=E7=BC=93=E5=AD=98=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/error/index.tsx | 2 +- src/pages/login/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/error/index.tsx b/src/pages/error/index.tsx index 18fc278..9a1a37d 100644 --- a/src/pages/error/index.tsx +++ b/src/pages/error/index.tsx @@ -15,7 +15,7 @@ const ErrorPage = () => { + + + ); + }, }, ]; From 2afada157decdcc64e75c82c6f943e56c7d78104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 10:32:08 +0800 Subject: [PATCH 24/40] =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E6=97=B6=E6=98=BE=E7=A4=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 42aaba3..816b890 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -13,10 +13,16 @@ export function clearToken() { } export function dateFormat(dateStr: string) { + if (!dateStr) { + return "-"; + } return moment(dateStr).format("YYYY-MM-DD HH:mm"); } export function timeFormat(dateStr: number) { + if (!dateStr) { + return "-"; + } var d = moment.duration(dateStr, "seconds"); let value = Math.floor(d.asDays()) + @@ -117,4 +123,4 @@ export function ValidataCredentials(value: any) { return true; } } -} \ No newline at end of file +} From 795609f5be46f07c49cd740c8e849afac8acffab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 10:44:05 +0800 Subject: [PATCH 25/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index b3a4ead..ec138f0 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -232,7 +232,7 @@ const MemberDepartmentProgressPage = () => { /> ))} - + Date: Thu, 20 Apr 2023 10:48:51 +0800 Subject: [PATCH 26/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index ec138f0..940ad96 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -232,7 +232,7 @@ const MemberDepartmentProgressPage = () => { /> ))} - + Date: Thu, 20 Apr 2023 11:03:16 +0800 Subject: [PATCH 27/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E6=8A=98=E7=BA=BF=E5=9B=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/learn.module.less | 1 - src/pages/member/learn.tsx | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/pages/member/learn.module.less b/src/pages/member/learn.module.less index 725f821..c1354f0 100644 --- a/src/pages/member/learn.module.less +++ b/src/pages/member/learn.module.less @@ -11,5 +11,4 @@ width: 100%; height: 320px; box-sizing: border-box; - padding-top: 24px; } diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index cac04e0..8550c52 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -7,6 +7,7 @@ import { dateFormat } from "../../utils/index"; import { user as member } from "../../api/index"; import * as echarts from "echarts"; import type { ColumnsType } from "antd/es/table"; +import { duration } from "moment"; interface DataType { id: React.Key; @@ -58,10 +59,21 @@ const MemberLearnPage = () => { }); }; + const minuteFormat = (duration: number) => { + if (duration === 0) { + return 0; + } + let h = Math.trunc(duration / 3600); + let m = Math.trunc((duration % 3600) / 60); + let s = Math.trunc((duration % 3600) % 60); + return h + "小时" + m + "分"; + }; + const renderView = (params: any) => { const timeData: any = []; const valueData: any = []; params.map((item: any) => { + let time = minuteFormat(item.value / 1000); timeData.push(item.key); valueData.push(item.value / 1000); }); @@ -91,9 +103,10 @@ const MemberLearnPage = () => { }, series: [ { - name: "每日学习时长(秒)", + name: "每日学习时长", type: "line", data: valueData, + color: "#ff4d4f", }, ], }); @@ -278,7 +291,6 @@ const MemberLearnPage = () => {
-
学习时长统计
Date: Thu, 20 Apr 2023 11:09:59 +0800 Subject: [PATCH 28/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E6=8A=98=E7=BA=BF=E5=9B=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/learn.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index 8550c52..b1c8a39 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -61,12 +61,12 @@ const MemberLearnPage = () => { const minuteFormat = (duration: number) => { if (duration === 0) { - return 0; + return "0小时0分0秒"; } let h = Math.trunc(duration / 3600); let m = Math.trunc((duration % 3600) / 60); let s = Math.trunc((duration % 3600) % 60); - return h + "小时" + m + "分"; + return h + "小时" + m + "分" + s + "秒"; }; const renderView = (params: any) => { @@ -75,7 +75,7 @@ const MemberLearnPage = () => { params.map((item: any) => { let time = minuteFormat(item.value / 1000); timeData.push(item.key); - valueData.push(item.value / 1000); + valueData.push(time); }); let dom: any = chartRef.current; let myChart = echarts.init(dom); @@ -99,7 +99,8 @@ const MemberLearnPage = () => { data: timeData, }, yAxis: { - type: "value", + type: "category", + boundaryGap: false, }, series: [ { From a18d7319130be8819d9a8ca8eb2f55fdf4a8caac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:18:22 +0800 Subject: [PATCH 29/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E8=AF=BE=E8=BF=9B=E5=BA=A6=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=96=87=E6=A1=88=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/learn.tsx | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index b1c8a39..4bb43c8 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -237,7 +237,7 @@ const MemberLearnPage = () => { const column2: ColumnsType = [ { - title: "课程", + title: "课程名称", dataIndex: "title", render: (_, record: any) => (
@@ -253,37 +253,39 @@ const MemberLearnPage = () => { ), }, { - title: "总课时", + title: "课程进度", dataIndex: "total_duration", render: (_, record: any) => ( <> - {record.hour_count} + + 已完成课时: {record.finished_count}/{record.hour_count} + ), }, { - title: "已学习课时", - dataIndex: "finished_duration", - render: (_, record: any) => ( - <> - {record.finished_count} - - ), + title: "第一次学习时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, }, { - title: "状态", + title: "学习进度", dataIndex: "is_finished", render: (_, record: any) => ( <> - {record.is_finished === 1 ? 已学完 : 未学完} + = + 100 + ? "c-green" + : "c-red" + } + > + {Math.floor((record.finished_count / record.hour_count) * 100)}% + ), }, - { - title: "时间", - dataIndex: "created_at", - render: (text: string) => {dateFormat(text)}, - }, ]; return ( @@ -303,7 +305,7 @@ const MemberLearnPage = () => { >
-
+ {/*
课时学习记录
{ rowKey={(record) => record.id} /> - + */}
线上课学习记录
From d4df2fd07fdb3981067737091448b1e56b1f8c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:36:41 +0800 Subject: [PATCH 30/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E6=8A=98=E7=BA=BF=E5=9B=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.less | 11 +++++++++++ src/pages/member/learn.tsx | 26 ++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/index.less b/src/index.less index 987b30f..019888e 100644 --- a/src/index.less +++ b/src/index.less @@ -257,6 +257,17 @@ code { position: relative; } +.playedu-main-sp-top { + width: 100%; + height: auto; + float: left; + background-color: white; + box-sizing: border-box; + padding: 24px 0px; + border-radius: 12px; + position: relative; +} + .playedu-main-body { width: 100%; height: auto; diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index 4bb43c8..6d9b387 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -73,15 +73,27 @@ const MemberLearnPage = () => { const timeData: any = []; const valueData: any = []; params.map((item: any) => { - let time = minuteFormat(item.value / 1000); timeData.push(item.key); - valueData.push(time); + valueData.push(item.value / 1000); }); let dom: any = chartRef.current; let myChart = echarts.init(dom); myChart.setOption({ tooltip: { trigger: "axis", + formatter: function (params: any) { + // 只粘贴formatter了 + let relVal = params[0].axisValueLabel; + for (let i = 0; i < params.length; i++) { + relVal += + "
" + + params[i].marker + + params[i].seriesName + + ": " + + minuteFormat(params[i].value); + } + return relVal; + }, }, legend: { data: ["每日学习时长"], @@ -99,8 +111,7 @@ const MemberLearnPage = () => { data: timeData, }, yAxis: { - type: "category", - boundaryGap: false, + type: "value", }, series: [ { @@ -290,8 +301,11 @@ const MemberLearnPage = () => { return ( <> - -
+ +
From b197da34c86b2079d9bc421c63edc30dbb7ba96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:37:22 +0800 Subject: [PATCH 31/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E6=8A=98=E7=BA=BF=E5=9B=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/learn.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index 6d9b387..2fe26e5 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -301,11 +301,8 @@ const MemberLearnPage = () => { return ( <> - -
+ +
From 1782f6aceff59a53bc562b0d32c81330c5128c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:46:19 +0800 Subject: [PATCH 32/40] =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E8=AF=BE=E5=AD=A6?= =?UTF-8?q?=E5=91=98=E6=90=BA=E5=B8=A6=E8=AF=BE=E7=A8=8B=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course/index.tsx | 4 +++- src/pages/course/user.tsx | 8 +++++--- src/pages/member/learn.tsx | 38 ++++++++++++++++++++------------------ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/pages/course/index.tsx b/src/pages/course/index.tsx index cfd66e7..f5b89b6 100644 --- a/src/pages/course/index.tsx +++ b/src/pages/course/index.tsx @@ -232,7 +232,9 @@ const CoursePage = () => { p="course" onClick={() => { setCid(Number(record.id)); - navigate("/course/user/" + Number(record.id)); + navigate( + "/course/user/" + Number(record.id) + "?title=" + record.title + ); }} disabled={null} /> diff --git a/src/pages/course/user.tsx b/src/pages/course/user.tsx index 68b46db..dad37df 100644 --- a/src/pages/course/user.tsx +++ b/src/pages/course/user.tsx @@ -11,7 +11,7 @@ import { Image, } from "antd"; import { course } from "../../api"; -import { useParams } from "react-router-dom"; +import { useParams, useLocation } from "react-router-dom"; import type { ColumnsType } from "antd/es/table"; import { BackBartment } from "../../compenents"; import { ExclamationCircleFilled } from "@ant-design/icons"; @@ -31,6 +31,7 @@ interface DataType { const CourseUserPage = () => { const params = useParams(); + const result = new URLSearchParams(useLocation().search); const [list, setList] = useState([]); const [users, setUsers] = useState([]); const [refresh, setRefresh] = useState(false); @@ -42,10 +43,11 @@ const CourseUserPage = () => { const [email, setEmail] = useState(""); const [idCard, setIdCard] = useState(""); const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [title, setTitle] = useState(String(result.get("title"))); const columns: ColumnsType = [ { - title: "学员名称", + title: "学员", render: (_, record: any) => (
{
- +
diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index 2fe26e5..db0d435 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -269,16 +269,11 @@ const MemberLearnPage = () => { render: (_, record: any) => ( <> - 已完成课时: {record.finished_count}/{record.hour_count} + 已完成课时:{record.finished_count} / {record.hour_count} ), }, - { - title: "第一次学习时间", - dataIndex: "created_at", - render: (text: string) => {dateFormat(text)}, - }, { title: "学习进度", dataIndex: "is_finished", @@ -297,6 +292,16 @@ const MemberLearnPage = () => { ), }, + { + title: "第一次学习时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, + }, + { + title: "学习完成时间", + dataIndex: "finished_at", + render: (text: string) => {dateFormat(text)}, + }, ]; return ( @@ -315,6 +320,15 @@ const MemberLearnPage = () => { }} >
+
+
record.id} + /> + {/*
课时学习记录
@@ -328,18 +342,6 @@ const MemberLearnPage = () => { />
*/} -
-
线上课学习记录
-
-
record.id} - /> - - ); }; From b8bb5234cabecc36ad27807268b48872b427c02a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:52:35 +0800 Subject: [PATCH 33/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course/user.tsx | 4 ++-- src/pages/member/index.tsx | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/pages/course/user.tsx b/src/pages/course/user.tsx index dad37df..9c9278b 100644 --- a/src/pages/course/user.tsx +++ b/src/pages/course/user.tsx @@ -217,7 +217,7 @@ const CourseUserPage = () => { placeholder="请输入学员邮箱" /> -
+ {/*
身份证号: { style={{ width: 160 }} placeholder="请输入身份证号" /> -
+
*/}
From 746a48d4d6f1ffed1fa4a6762c124bc06d20b150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 11:55:48 +0800 Subject: [PATCH 34/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=8F=98=E5=8C=96=E5=85=B3=E8=81=94=E9=83=A8=E9=97=A8=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-department/index.tsx | 3 ++- src/pages/course/index.tsx | 1 + src/pages/member/index.tsx | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 000d665..3da48c5 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -11,6 +11,7 @@ interface Option { interface PropInterface { type: string; text: string; + refresh: boolean; showNum: boolean; onUpdate: (keys: any, title: any) => void; } @@ -47,7 +48,7 @@ export const TreeDepartment = (props: PropInterface) => { } setLoading(false); }); - }, []); + }, [props.refresh]); const checkNewArr = (departments: any[], id: number, counts: any) => { const arr = []; diff --git a/src/pages/course/index.tsx b/src/pages/course/index.tsx index f5b89b6..ad94cbb 100644 --- a/src/pages/course/index.tsx +++ b/src/pages/course/index.tsx @@ -89,6 +89,7 @@ const CoursePage = () => { children: (
{
Date: Thu, 20 Apr 2023 11:58:09 +0800 Subject: [PATCH 35/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/index.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index 679bafb..e36519b 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -278,17 +278,19 @@ const MemberPage = () => { onClick={() => setCreateVisible(true)} disabled={null} /> - - null} - disabled={null} - /> - + {dep_ids.length === 0 && ( + + null} + disabled={null} + /> + + )} {dep_ids.length > 0 && ( { > Date: Thu, 20 Apr 2023 12:02:28 +0800 Subject: [PATCH 36/40] =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E8=AF=BE=E5=AD=A6?= =?UTF-8?q?=E5=91=98=E5=88=97=E8=A1=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course/user.tsx | 14 +++++++++----- src/pages/member/learn.tsx | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/pages/course/user.tsx b/src/pages/course/user.tsx index 9c9278b..fb74011 100644 --- a/src/pages/course/user.tsx +++ b/src/pages/course/user.tsx @@ -72,11 +72,6 @@ const CourseUserPage = () => { ), }, - { - title: "学习进度", - dataIndex: "progress", - render: (progress: number) => {progress / 100}%, - }, { title: "第一次学习时间", dataIndex: "created_at", @@ -87,6 +82,15 @@ const CourseUserPage = () => { dataIndex: "finished_at", render: (text: string) => {dateFormat(text)}, }, + { + title: "学习进度", + dataIndex: "progress", + render: (progress: number) => ( + = 10000 ? "c-green" : "c-red"}> + {progress / 100}% + + ), + }, ]; useEffect(() => { diff --git a/src/pages/member/learn.tsx b/src/pages/member/learn.tsx index db0d435..ec3d42a 100644 --- a/src/pages/member/learn.tsx +++ b/src/pages/member/learn.tsx @@ -274,6 +274,16 @@ const MemberLearnPage = () => { ), }, + { + title: "第一次学习时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, + }, + { + title: "学习完成时间", + dataIndex: "finished_at", + render: (text: string) => {dateFormat(text)}, + }, { title: "学习进度", dataIndex: "is_finished", @@ -292,16 +302,6 @@ const MemberLearnPage = () => { ), }, - { - title: "第一次学习时间", - dataIndex: "created_at", - render: (text: string) => {dateFormat(text)}, - }, - { - title: "学习完成时间", - dataIndex: "finished_at", - render: (text: string) => {dateFormat(text)}, - }, ]; return ( From b5e2d351e576a7fc26a494b0f627ffc53be53788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 12:03:11 +0800 Subject: [PATCH 37/40] =?UTF-8?q?=E5=AD=A6=E5=91=98=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index e36519b..5441664 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -297,7 +297,7 @@ const MemberPage = () => { to={`/member/departmentUser?id=${dep_ids.join(",")}`} > Date: Thu, 20 Apr 2023 16:55:52 +0800 Subject: [PATCH 38/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 92 +++++++++++++++-------------- src/pages/member/index.tsx | 4 +- 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index 940ad96..1da58c7 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -41,6 +41,7 @@ const MemberDepartmentProgressPage = () => { const [email, setEmail] = useState(""); const [id_card, setIdCard] = useState(""); const [did, setDid] = useState(Number(result.get("id"))); + const [title, setTitle] = useState(String(result.get("title"))); useEffect(() => { getData(); @@ -127,10 +128,13 @@ const MemberDepartmentProgressPage = () => { return (
- +
-
-
+
+
+ 以下表格内数字对应的是表头课程的“已学完课时数/总课时数”) +
+
姓名: { placeholder="请输入邮箱" />
-
+ {/*
身份证号: { style={{ width: 160 }} placeholder="请输入身份证号" /> -
+
*/}
record.id} + scroll={{ x: 1600 }} > ( <> { )} /> {courses.map((item: any) => ( - - ( - <> - {records[record.id] && records[record.id][item.id] ? ( - {records[record.id][item.id].finished_count} - ) : ( - 0 - )} - - )} - /> - ( - <> - {item.class_hour} - - )} - /> - - ))} - ( - <>{getFinishedHours(records[record.id])} + <> + {records[record.id] && records[record.id][item.id] ? ( + records[record.id][item.id].is_finished === 1 ? ( + 已完成 + ) : ( + <> + + {records[record.id][item.id].finished_count} + {" "} + / {item.class_hour} + + ) + ) : ( + <> + 0 / {item.class_hour} + + )} + )} /> - {totalHour}} - /> - + ))} + ( + <> + {getFinishedHours(records[record.id])} /{" "} + {totalHour} + + )} + />
diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index 5441664..e08267c 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -294,7 +294,9 @@ const MemberPage = () => { {dep_ids.length > 0 && ( Date: Thu, 20 Apr 2023 16:57:07 +0800 Subject: [PATCH 39/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index 1da58c7..847f07e 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -218,7 +218,7 @@ const MemberDepartmentProgressPage = () => { ellipsis={true} dataIndex="id" key={item.id} - width={100} + width={60} render={(_, record: any) => ( <> {records[record.id] && records[record.id][item.id] ? ( @@ -246,7 +246,7 @@ const MemberDepartmentProgressPage = () => { title="所有课程总课时" dataIndex="id" key="id" - width={100} + width={60} render={(_, record: any) => ( <> {getFinishedHours(records[record.id])} /{" "} From 492270bfc31f776fb7ef3567c44e81dbfbbb7464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BA=E7=8B=A8?= <18119604035@163.com> Date: Thu, 20 Apr 2023 17:04:00 +0800 Subject: [PATCH 40/40] =?UTF-8?q?=E9=83=A8=E9=97=A8=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/member/departmentUser.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/member/departmentUser.tsx b/src/pages/member/departmentUser.tsx index 847f07e..de96f52 100644 --- a/src/pages/member/departmentUser.tsx +++ b/src/pages/member/departmentUser.tsx @@ -132,7 +132,7 @@ const MemberDepartmentProgressPage = () => {
- 以下表格内数字对应的是表头课程的“已学完课时数/总课时数”) + (以下表格内数字对应的是表头课程的“已学完课时数/总课时数”)
@@ -191,14 +191,14 @@ const MemberDepartmentProgressPage = () => { loading={loading} pagination={paginationProps} rowKey={(record) => record.id} - scroll={{ x: 1600 }} + scroll={{ x: 1200 }} > ( <> { ellipsis={true} dataIndex="id" key={item.id} - width={60} + width={100} render={(_, record: any) => ( <> {records[record.id] && records[record.id][item.id] ? ( @@ -246,7 +246,7 @@ const MemberDepartmentProgressPage = () => { title="所有课程总课时" dataIndex="id" key="id" - width={60} + width={100} render={(_, record: any) => ( <> {getFinishedHours(records[record.id])} /{" "}