From 5d5dc4dde6c6e2e91f94f5bf54a8a74cf5cc8375 Mon Sep 17 00:00:00 2001 From: xxx Date: Thu, 21 Sep 2023 10:02:06 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E5=B7=A6=E4=BE=A7=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/left-menu/index.tsx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/compenents/left-menu/index.tsx b/src/compenents/left-menu/index.tsx index 85f7715..e514641 100644 --- a/src/compenents/left-menu/index.tsx +++ b/src/compenents/left-menu/index.tsx @@ -37,16 +37,16 @@ const items = [ , null, null, - null + "resource-category-menu" ), getItem( "资源管理", "resource", , [ - getItem("视频", "/videos", null, null, null, null), - getItem("图片", "/images", null, null, null, null), - getItem("课件", "/courseware", null, null, null, null), + getItem("视频", "/videos", null, null, null, "resource-menu"), + getItem("图片", "/images", null, null, null, "resource-menu"), + getItem("课件", "/courseware", null, null, null, "resource-menu"), ], null, null @@ -92,7 +92,6 @@ const items = [ "admin-user-index" ), getItem("管理日志", "/system/adminlog", null, null, null, "admin-log"), - // getItem("角色配置", "/system/adminroles", null, null, null, null), ], null, null @@ -120,6 +119,7 @@ export const LeftMenu: React.FC = () => { } return []; }; + const openKeyMerge = (pathname: string): string[] => { let newOpenKeys = hit(pathname); for (let i = 0; i < openKeys.length; i++) { @@ -166,8 +166,14 @@ export const LeftMenu: React.FC = () => { for (let i in items) { let menuItem = items[i]; - if (!menuItem.children) { - // 一级菜单不做权限控制 + // 一级菜单=>没有子菜单&配置了权限 + if (menuItem.children === null) { + if ( + menuItem.permission !== null && + typeof permissions[menuItem.permission] === "undefined" + ) { + continue; + } menus.push(menuItem); continue; } From 36ab0200a023da860e571c7689d6fb2a86ce82cf Mon Sep 17 00:00:00 2001 From: xxx Date: Thu, 21 Sep 2023 10:12:18 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E6=96=B0=E5=A2=9ELDAP=E7=9A=84=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E6=9E=B6=E6=9E=84=E4=B8=80=E9=94=AE=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/department.ts | 4 ++++ src/pages/department/index.tsx | 31 +++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/api/department.ts b/src/api/department.ts index 00101a6..d94a077 100644 --- a/src/api/department.ts +++ b/src/api/department.ts @@ -54,3 +54,7 @@ export function dropDiffClass(id: number, parent_id: number, ids: number[]) { export function checkDestroy(id: number) { return client.get(`/backend/v1/department/${id}/destroy`, {}); } + +export function ldapSync() { + return client.post(`/backend/v1/department/ldap-sync`, {}); +} diff --git a/src/pages/department/index.tsx b/src/pages/department/index.tsx index 7a4ad65..c6aba78 100644 --- a/src/pages/department/index.tsx +++ b/src/pages/department/index.tsx @@ -32,6 +32,8 @@ const DepartmentPage = () => { const [updateVisible, setUpdateVisible] = useState(false); const [did, setDid] = useState(0); const [modal, contextHolder] = Modal.useModal(); + + // 是否启用LDAP const ldapEnabled = useSelector( (state: any) => state.systemConfig.value["ldap-enabled"] ); @@ -389,9 +391,22 @@ const DepartmentPage = () => { } }; + const ldapSync = () => { + if (loading) { + message.warning("正在同步,请稍后..."); + return; + } + setLoading(true); + department.ldapSync().then(() => { + message.success("操作成功"); + setLoading(false); + resetData(); + }); + }; + return ( <> - {!ldapEnabled && ( + {
{contextHolder}
@@ -404,9 +419,21 @@ const DepartmentPage = () => { onClick={() => setCreateVisible(true)} disabled={null} /> + + {ldapEnabled ? ( + ldapSync()} + disabled={null} + /> + ) : null}
- )} + }
{loading && (
From c1adb96a0ae6ad568f33c3fd4b7dbd5963cc6c8c Mon Sep 17 00:00:00 2001 From: unknown <18119604035@163.com> Date: Fri, 22 Sep 2023 14:50:54 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E9=83=A8=E9=97=A8=E5=92=8C=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-category/index.tsx | 29 ++++++++++---------- src/compenents/tree-department/index.tsx | 34 +++++++++++++++++------- src/pages/init/index.tsx | 2 ++ src/pages/login/index.tsx | 2 ++ src/pages/system/config/index.tsx | 2 ++ src/store/system/systemConfigSlice.ts | 2 ++ 6 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/compenents/tree-category/index.tsx b/src/compenents/tree-category/index.tsx index bc01a50..bbaf0d3 100644 --- a/src/compenents/tree-category/index.tsx +++ b/src/compenents/tree-category/index.tsx @@ -1,6 +1,6 @@ import { Tree } from "antd"; import { useState, useEffect } from "react"; -import { resourceCategory } from "../../api/index"; +import { useSelector } from "react-redux"; interface Option { key: string | number; @@ -19,6 +19,9 @@ export const TreeCategory = (props: PropInterface) => { const [treeData, setTreeData] = useState([]); const [loading, setLoading] = useState(true); const [selectKey, setSelectKey] = useState([]); + const resourceCategories = useSelector( + (state: any) => state.systemConfig.value.resourceCategories + ); useEffect(() => { if (props.selected && props.selected.length > 0) { @@ -27,21 +30,17 @@ export const TreeCategory = (props: PropInterface) => { }, [props.selected]); useEffect(() => { - resourceCategory.resourceCategoryList().then((res: any) => { - const categories: CategoriesBoxModel = res.data.categories; - if (JSON.stringify(categories) !== "{}") { - const new_arr: Option[] = checkArr(categories, 0); - if (props.type === "no-cate") { - new_arr.unshift({ - key: 0, - title: 未分类, - }); - } - - setTreeData(new_arr); + if (JSON.stringify(resourceCategories) !== "{}") { + const new_arr: Option[] = checkArr(resourceCategories, 0); + if (props.type === "no-cate") { + new_arr.unshift({ + key: 0, + title: 未分类, + }); } - }); - }, []); + setTreeData(new_arr); + } + }, [resourceCategories]); const checkArr = (categories: CategoriesBoxModel, id: number) => { const arr = []; diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 3bba14d..098bb4f 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -1,6 +1,7 @@ import { Button, Input, message, Tree } from "antd"; import { useState, useEffect } from "react"; import { department } from "../../api/index"; +import { useSelector } from "react-redux"; interface Option { key: string | number; @@ -22,6 +23,9 @@ export const TreeDepartment = (props: PropInterface) => { const [loading, setLoading] = useState(true); const [selectKey, setSelectKey] = useState([]); const [userTotal, setUserTotal] = useState(0); + const localDepartments = useSelector( + (state: any) => state.systemConfig.value.departments + ); useEffect(() => { if (props.selected && props.selected.length > 0) { @@ -31,18 +35,30 @@ export const TreeDepartment = (props: PropInterface) => { useEffect(() => { setLoading(true); - department.departmentList().then((res: any) => { - const departments: DepartmentsBoxModel = res.data.departments; - const departCount: DepIdsModel = res.data.dep_user_count; - setUserTotal(res.data.user_total); - if (JSON.stringify(departments) !== "{}") { - if (props.showNum) { + if (props.showNum) { + department.departmentList().then((res: any) => { + const departments: DepartmentsBoxModel = res.data.departments; + const departCount: DepIdsModel = res.data.dep_user_count; + setUserTotal(res.data.user_total); + if (JSON.stringify(departments) !== "{}") { const new_arr: any[] = checkNewArr(departments, 0, departCount); setTreeData(new_arr); } else { - const new_arr: any[] = checkArr(departments, 0); + const new_arr: Option[] = [ + { + key: "", + title: "全部", + children: [], + }, + ]; setTreeData(new_arr); } + setLoading(false); + }); + } else { + if (JSON.stringify(localDepartments) !== "{}") { + const new_arr: any[] = checkArr(localDepartments, 0); + setTreeData(new_arr); } else { const new_arr: Option[] = [ { @@ -54,8 +70,8 @@ export const TreeDepartment = (props: PropInterface) => { setTreeData(new_arr); } setLoading(false); - }); - }, [props.refresh]); + } + }, [props.refresh, localDepartments]); const checkNewArr = ( departments: DepartmentsBoxModel, diff --git a/src/pages/init/index.tsx b/src/pages/init/index.tsx index b71db95..8bdbf1d 100644 --- a/src/pages/init/index.tsx +++ b/src/pages/init/index.tsx @@ -27,6 +27,8 @@ const InitPage = (props: Props) => { systemH5Url: props.configData["system.h5_url"], memberDefaultAvatar: props.configData["member.default_avatar"], courseDefaultThumbs: props.configData["default.course_thumbs"], + departments: props.configData["departments"], + resourceCategories: props.configData["resource_categories"], }; dispatch(saveConfigAction(config)); } diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index a7918bd..d687553 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -67,6 +67,8 @@ const LoginPage = () => { systemH5Url: res.data["system.h5_url"], memberDefaultAvatar: res.data["member.default_avatar"], courseDefaultThumbs: res.data["default.course_thumbs"], + departments: res.data["departments"], + resourceCategories: res.data["resource_categories"], }; dispatch(saveConfigAction(data)); }; diff --git a/src/pages/system/config/index.tsx b/src/pages/system/config/index.tsx index 6aa754a..4145c82 100644 --- a/src/pages/system/config/index.tsx +++ b/src/pages/system/config/index.tsx @@ -259,6 +259,8 @@ const SystemConfigPage = () => { systemH5Url: res.data["system.h5_url"], memberDefaultAvatar: res.data["member.default_avatar"], courseDefaultThumbs: res.data["default.course_thumbs"], + departments: res.data["departments"], + resourceCategories: res.data["resource_categories"], }; dispatch(saveConfigAction(data)); }); diff --git a/src/store/system/systemConfigSlice.ts b/src/store/system/systemConfigSlice.ts index f4a37c7..ce4facb 100644 --- a/src/store/system/systemConfigSlice.ts +++ b/src/store/system/systemConfigSlice.ts @@ -9,6 +9,8 @@ type SystemConfigStoreInterface = { systemName?: string; memberDefaultAvatar?: string; courseDefaultThumbs?: string[]; + departments: any; + resourceCategories: any; }; const systemConfigSlice = createSlice({ From 6715d8cf50650752e0b1a1b890d1adf36396aa2a Mon Sep 17 00:00:00 2001 From: unknown <18119604035@163.com> Date: Fri, 22 Sep 2023 14:51:22 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E9=83=A8=E9=97=A8=E5=92=8C=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-department/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compenents/tree-department/index.tsx b/src/compenents/tree-department/index.tsx index 098bb4f..9aed8da 100644 --- a/src/compenents/tree-department/index.tsx +++ b/src/compenents/tree-department/index.tsx @@ -1,4 +1,4 @@ -import { Button, Input, message, Tree } from "antd"; +import { Tree } from "antd"; import { useState, useEffect } from "react"; import { department } from "../../api/index"; import { useSelector } from "react-redux"; From f580bc5ac75bb971393b70a1de72d6926fb67714 Mon Sep 17 00:00:00 2001 From: unknown <18119604035@163.com> Date: Fri, 22 Sep 2023 15:04:22 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E8=AF=BE=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E3=80=81=E5=AD=A6=E5=91=98=E5=88=97=E8=A1=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=AD=98=E5=82=A8=E5=88=B0url=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course/index.tsx | 75 ++++++++++++++++++++++++++-------- src/pages/member/index.tsx | 82 ++++++++++++++++++++++++++++++-------- 2 files changed, 124 insertions(+), 33 deletions(-) diff --git a/src/pages/course/index.tsx b/src/pages/course/index.tsx index 42e103c..001aa9e 100644 --- a/src/pages/course/index.tsx +++ b/src/pages/course/index.tsx @@ -20,7 +20,7 @@ import { import type { MenuProps } from "antd"; import type { ColumnsType } from "antd/es/table"; import { dateFormat } from "../../utils/index"; -import { useNavigate, useLocation } from "react-router-dom"; +import { useNavigate, useLocation, useSearchParams } from "react-router-dom"; import { TreeDepartment, TreeCategory, PerButton } from "../../compenents"; import type { TabsProps } from "antd"; import { CourseCreate } from "./compenents/create"; @@ -42,17 +42,30 @@ interface DataType { title: string; } +interface LocalSearchParamsInterface { + page?: number; + size?: number; + title?: string; +} + const CoursePage = () => { const result = new URLSearchParams(useLocation().search); + + const [searchParams, setSearchParams] = useSearchParams({ + page: "1", + size: "10", + title: "", + }); + const page = parseInt(searchParams.get("page") || "1"); + const size = parseInt(searchParams.get("size") || "10"); + const title = searchParams.get("title"); + const navigate = useNavigate(); const [list, setList] = useState([]); - const [refresh, setRefresh] = useState(false); - const [page, setPage] = useState(1); - const [size, setSize] = useState(10); const [total, setTotal] = useState(0); + const [refresh, setRefresh] = useState(false); const [loading, setLoading] = useState(true); const [category_ids, setCategoryIds] = useState([]); - const [title, setTitle] = useState(""); const [dep_ids, setDepIds] = useState([]); const [selLabel, setLabel] = useState( result.get("label") ? String(result.get("label")) : "全部分类" @@ -105,7 +118,9 @@ const CoursePage = () => { type="" text={"分类"} onUpdate={(keys: any, title: any) => { - setPage(1); + resetLocalSearchParams({ + page: 1, + }); setCategoryIds(keys); if (typeof title === "string") { setLabel(title); @@ -129,7 +144,9 @@ const CoursePage = () => { type="no-course" text={"部门"} onUpdate={(keys: any, title: any) => { - setPage(1); + resetLocalSearchParams({ + page: 1, + }); setDepIds(keys); setDepLabel(title); }} @@ -346,7 +363,7 @@ const CoursePage = () => { depIds = dep_ids.join(","); } course - .courseList(page, size, "", "", title, depIds, categoryIds) + .courseList(page, size, "", "", title ? title : "", depIds, categoryIds) .then((res: any) => { setTotal(res.data.total); setList(res.data.data); @@ -362,10 +379,12 @@ const CoursePage = () => { }; // 重置列表 const resetList = () => { - setPage(1); - setSize(10); + resetLocalSearchParams({ + page: 1, + size: 10, + title: "", + }); setList([]); - setTitle(""); setRefresh(!refresh); }; @@ -379,8 +398,28 @@ const CoursePage = () => { }; const handlePageChange = (page: number, pageSize: number) => { - setPage(page); - setSize(pageSize); + resetLocalSearchParams({ + page: page, + size: pageSize, + }); + }; + + const resetLocalSearchParams = (params: LocalSearchParamsInterface) => { + setSearchParams( + (prev) => { + if (typeof params.title !== "undefined") { + prev.set("title", params.title); + } + if (typeof params.page !== "undefined") { + prev.set("page", params.page + ""); + } + if (typeof params.size !== "undefined") { + prev.set("size", params.size + ""); + } + return prev; + }, + { replace: true } + ); }; const onChange = (key: string) => { @@ -419,9 +458,11 @@ const CoursePage = () => {
课程名称: { - setTitle(e.target.value); + resetLocalSearchParams({ + title: e.target.value, + }); }} allowClear style={{ width: 160 }} @@ -435,7 +476,9 @@ const CoursePage = () => {
{treeData.length > 0 && ( {
{ resetLocalSearchParams({ diff --git a/src/pages/member/index.tsx b/src/pages/member/index.tsx index 6d122d3..5684213 100644 --- a/src/pages/member/index.tsx +++ b/src/pages/member/index.tsx @@ -70,7 +70,9 @@ const MemberPage = () => { const [loading, setLoading] = useState(false); const [list, setList] = useState([]); const [total, setTotal] = useState(0); + const [pureTotal, setPureTotal] = useState(0); const [refresh, setRefresh] = useState(false); + const [depUserCount, setDepUserCount] = useState(); const [dep_ids, setDepIds] = useState([]); const [selLabel, setLabel] = useState( @@ -252,6 +254,8 @@ const MemberPage = () => { setDepartments(res.data.departments); setUserDepIds(res.data.user_dep_ids); setTotal(res.data.total); + setPureTotal(res.data.pure_total); + setDepUserCount(res.data.dep_user_count); setLoading(false); }); }; @@ -333,9 +337,9 @@ const MemberPage = () => {
{ resetLocalSearchParams({ diff --git a/src/playedu.d.ts b/src/playedu.d.ts index 48babd2..80fe456 100644 --- a/src/playedu.d.ts +++ b/src/playedu.d.ts @@ -1,4 +1,8 @@ declare global { + interface KeyNumberObject { + [key: number]: number; + } + interface FileItem { id: string; //上传文件的唯一id file: File; //上传的文件资源 From 983b8c39bd1881fcaadd756202b348c39916585f Mon Sep 17 00:00:00 2001 From: xxx Date: Sun, 24 Sep 2023 08:23:43 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E9=80=89=E6=8B=A9=E7=9A=84=E5=88=86=E7=B1=BB?= =?UTF-8?q?=E6=80=BB=E6=98=AF=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compenents/tree-category/index.tsx | 1 - src/compenents/upload-video-sub/index.tsx | 10 +--------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/compenents/tree-category/index.tsx b/src/compenents/tree-category/index.tsx index bbaf0d3..cf7cecd 100644 --- a/src/compenents/tree-category/index.tsx +++ b/src/compenents/tree-category/index.tsx @@ -17,7 +17,6 @@ interface PropInterface { export const TreeCategory = (props: PropInterface) => { const [treeData, setTreeData] = useState([]); - const [loading, setLoading] = useState(true); const [selectKey, setSelectKey] = useState([]); const resourceCategories = useSelector( (state: any) => state.systemConfig.value.resourceCategories diff --git a/src/compenents/upload-video-sub/index.tsx b/src/compenents/upload-video-sub/index.tsx index a503a75..3e8857f 100644 --- a/src/compenents/upload-video-sub/index.tsx +++ b/src/compenents/upload-video-sub/index.tsx @@ -159,15 +159,7 @@ export const UploadVideoSub = (props: PropsInterface) => { <> - {init && ( -
- -
- )} -
+