mirror of
https://github.com/PlayEdu/backend
synced 2025-07-19 00:09:40 +08:00
commit
7dc58e2fde
@ -8,9 +8,15 @@
|
|||||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
||||||
/>
|
/>
|
||||||
<title>管理后台</title>
|
<title>管理后台</title>
|
||||||
|
<script src="/js/DPlayer.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
<script
|
||||||
|
crossorigin="anonymous"
|
||||||
|
integrity="sha512-oHrfR/z2wkuRuaHrdZ9NhoT/o/1kteub+QvmQgVzOKK7NTvIKQMvnY9+/RR0+eW311o4lAE/YzzLXXmP2XUvig=="
|
||||||
|
src="https://lib.baomitu.com/hls.js/1.1.4/hls.min.js"
|
||||||
|
></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
1
public/js/DPlayer.min.js
vendored
Normal file
1
public/js/DPlayer.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/js/xg/hls.min.js
vendored
Normal file
1
public/js/xg/hls.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
21
public/js/xg/index.js
Normal file
21
public/js/xg/index.js
Normal file
File diff suppressed because one or more lines are too long
@ -61,3 +61,11 @@ export function destroyResourceMulti(ids: number[]) {
|
|||||||
ids: ids,
|
ids: ids,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function videoDetail(id: number) {
|
||||||
|
return client.get(`/backend/v1/resource/${id}`, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function videoUpdate(id: number, params: any) {
|
||||||
|
return client.put(`/backend/v1/resource/${id}`, params);
|
||||||
|
}
|
||||||
|
BIN
src/assets/images/commen/close.png
Normal file
BIN
src/assets/images/commen/close.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 736 B |
@ -1,16 +1,25 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Menu } from "antd";
|
import { Menu } from "antd";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
import styles from "./index.module.less";
|
import styles from "./index.module.less";
|
||||||
import logo from "../../assets/logo.png";
|
import logo from "../../assets/logo.png";
|
||||||
|
|
||||||
function getItem(label: any, key: any, icon: any, children: any, type: any) {
|
function getItem(
|
||||||
|
label: any,
|
||||||
|
key: any,
|
||||||
|
icon: any,
|
||||||
|
children: any,
|
||||||
|
type: any,
|
||||||
|
permission: any
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
icon,
|
icon,
|
||||||
children,
|
children,
|
||||||
label,
|
label,
|
||||||
type,
|
type,
|
||||||
|
permission,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const items = [
|
const items = [
|
||||||
@ -19,6 +28,7 @@ const items = [
|
|||||||
"/",
|
"/",
|
||||||
<i className={`iconfont icon-icon-home`} />,
|
<i className={`iconfont icon-icon-home`} />,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
getItem(
|
getItem(
|
||||||
@ -26,6 +36,7 @@ const items = [
|
|||||||
"/resource-category",
|
"/resource-category",
|
||||||
<i className="iconfont icon-icon-category" />,
|
<i className="iconfont icon-icon-category" />,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
getItem(
|
getItem(
|
||||||
@ -33,16 +44,18 @@ const items = [
|
|||||||
"resource",
|
"resource",
|
||||||
<i className="iconfont icon-icon-file" />,
|
<i className="iconfont icon-icon-file" />,
|
||||||
[
|
[
|
||||||
getItem("视频", "/videos", null, null, null),
|
getItem("视频", "/videos", null, null, null, null),
|
||||||
getItem("图片", "/images", null, null, null),
|
getItem("图片", "/images", null, null, null, null),
|
||||||
],
|
],
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
getItem(
|
getItem(
|
||||||
"课程中心",
|
"课程中心",
|
||||||
"courses",
|
"courses",
|
||||||
<i className="iconfont icon-icon-study" />,
|
<i className="iconfont icon-icon-study" />,
|
||||||
[getItem("线上课", "/course", null, null, null)],
|
[getItem("线上课", "/course", null, null, null, "course")],
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
getItem(
|
getItem(
|
||||||
@ -50,9 +63,10 @@ const items = [
|
|||||||
"user",
|
"user",
|
||||||
<i className="iconfont icon-icon-user" />,
|
<i className="iconfont icon-icon-user" />,
|
||||||
[
|
[
|
||||||
getItem("学员", "/member/index", null, null, null),
|
getItem("学员", "/member/index", null, null, null, "user-index"),
|
||||||
getItem("部门", "/department", null, null, null),
|
getItem("部门", "/department", null, null, null, "department-cud"),
|
||||||
],
|
],
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
getItem(
|
getItem(
|
||||||
@ -60,26 +74,40 @@ const items = [
|
|||||||
"system",
|
"system",
|
||||||
<i className="iconfont icon-icon-setting" />,
|
<i className="iconfont icon-icon-setting" />,
|
||||||
[
|
[
|
||||||
getItem("系统配置", "/system/config/index", null, null, null),
|
getItem(
|
||||||
getItem("管理人员", "/system/administrator", null, null, null),
|
"系统配置",
|
||||||
// getItem("角色配置", "/system/adminroles", null, null, null),
|
"/system/config/index",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"system-config"
|
||||||
|
),
|
||||||
|
getItem(
|
||||||
|
"管理人员",
|
||||||
|
"/system/administrator",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"admin-user-index"
|
||||||
|
),
|
||||||
|
// getItem("角色配置", "/system/adminroles", null, null, null, null),
|
||||||
],
|
],
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
const children2Parent: any = {
|
export const LeftMenu: React.FC = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const children2Parent: any = {
|
||||||
"^/video": ["resource"],
|
"^/video": ["resource"],
|
||||||
"^/image": ["resource"],
|
"^/image": ["resource"],
|
||||||
"^/member": ["user"],
|
"^/member": ["user"],
|
||||||
"^/department": ["user"],
|
"^/department": ["user"],
|
||||||
"^/course": ["courses"],
|
"^/course": ["courses"],
|
||||||
"^/system": ["system"],
|
"^/system": ["system"],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LeftMenu: React.FC = () => {
|
|
||||||
const location = useLocation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const hit = (pathname: string): string[] => {
|
const hit = (pathname: string): string[] => {
|
||||||
for (let p in children2Parent) {
|
for (let p in children2Parent) {
|
||||||
@ -104,7 +132,6 @@ export const LeftMenu: React.FC = () => {
|
|||||||
}
|
}
|
||||||
newOpenKeys.push(openKeys[i]);
|
newOpenKeys.push(openKeys[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newOpenKeys;
|
return newOpenKeys;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,11 +141,54 @@ export const LeftMenu: React.FC = () => {
|
|||||||
]);
|
]);
|
||||||
// 展开菜单
|
// 展开菜单
|
||||||
const [openKeys, setOpenKeys] = useState<string[]>(hit(location.pathname));
|
const [openKeys, setOpenKeys] = useState<string[]>(hit(location.pathname));
|
||||||
|
const permissions = useSelector(
|
||||||
|
(state: any) => state.loginUser.value.permissions
|
||||||
|
);
|
||||||
|
const [activeMenus, setActiveMenus] = useState<any>([]);
|
||||||
|
|
||||||
const onClick = (e: any) => {
|
const onClick = (e: any) => {
|
||||||
navigate(e.key);
|
navigate(e.key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkMenuPermissions(items, permissions);
|
||||||
|
}, [items, permissions]);
|
||||||
|
|
||||||
|
const checkMenuPermissions = (items: any, permissions: any) => {
|
||||||
|
let menus: any = [];
|
||||||
|
if (permissions.length === 0) {
|
||||||
|
setActiveMenus(menus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in items) {
|
||||||
|
let menuItem = items[i];
|
||||||
|
if (!menuItem.children) {
|
||||||
|
// 一级菜单不做权限控制
|
||||||
|
menus.push(menuItem);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let children = [];
|
||||||
|
|
||||||
|
for (let j in menuItem.children) {
|
||||||
|
let childrenItem = menuItem.children[j];
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof permissions[childrenItem.permission] !== "undefined" ||
|
||||||
|
!childrenItem.permission
|
||||||
|
) {
|
||||||
|
// 存在权限
|
||||||
|
children.push(childrenItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children.length > 0) {
|
||||||
|
menus.push(Object.assign({}, menuItem, { children: children }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setActiveMenus(menus);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (location.pathname.indexOf("/course/user") !== -1) {
|
if (location.pathname.indexOf("/course/user") !== -1) {
|
||||||
setSelectedKeys(["/course"]);
|
setSelectedKeys(["/course"]);
|
||||||
@ -159,7 +229,7 @@ export const LeftMenu: React.FC = () => {
|
|||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
openKeys={openKeys}
|
openKeys={openKeys}
|
||||||
mode="inline"
|
mode="inline"
|
||||||
items={items}
|
items={activeMenus}
|
||||||
onSelect={(data: any) => {
|
onSelect={(data: any) => {
|
||||||
setSelectedKeys(data.selectedKeys);
|
setSelectedKeys(data.selectedKeys);
|
||||||
}}
|
}}
|
||||||
|
@ -13,13 +13,14 @@ interface PropInterface {
|
|||||||
roleDelSuccess: boolean;
|
roleDelSuccess: boolean;
|
||||||
type: string;
|
type: string;
|
||||||
text: string;
|
text: string;
|
||||||
onUpdate: (keys: any, title: any) => void;
|
onUpdate: (keys: any, title: any, isSuper: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TreeAdminroles = (props: PropInterface) => {
|
export const TreeAdminroles = (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<any>([]);
|
||||||
|
const [superId, setSuperId] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onSelect([], "");
|
onSelect([], "");
|
||||||
@ -28,6 +29,7 @@ export const TreeAdminroles = (props: PropInterface) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
adminRole.adminRoleList().then((res: any) => {
|
adminRole.adminRoleList().then((res: any) => {
|
||||||
let adminrole = res.data;
|
let adminrole = res.data;
|
||||||
|
let superId = 0;
|
||||||
if (adminrole.length > 0) {
|
if (adminrole.length > 0) {
|
||||||
const new_arr: Option[] = [];
|
const new_arr: Option[] = [];
|
||||||
for (let i = 0; i < adminrole.length; i++) {
|
for (let i = 0; i < adminrole.length; i++) {
|
||||||
@ -36,9 +38,13 @@ export const TreeAdminroles = (props: PropInterface) => {
|
|||||||
key: adminrole[i].id,
|
key: adminrole[i].id,
|
||||||
children: [],
|
children: [],
|
||||||
});
|
});
|
||||||
|
if (adminrole[i].slug === "super-role") {
|
||||||
|
superId = adminrole[i].id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setTreeData(new_arr);
|
setTreeData(new_arr);
|
||||||
}
|
}
|
||||||
|
setSuperId(superId);
|
||||||
});
|
});
|
||||||
}, [props.refresh]);
|
}, [props.refresh]);
|
||||||
|
|
||||||
@ -47,7 +53,11 @@ export const TreeAdminroles = (props: PropInterface) => {
|
|||||||
if (info) {
|
if (info) {
|
||||||
label = info.node.title;
|
label = info.node.title;
|
||||||
}
|
}
|
||||||
props.onUpdate(selectedKeys, label);
|
let isSuper = false;
|
||||||
|
if (selectedKeys[0] === superId && superId !== 0) {
|
||||||
|
isSuper = true;
|
||||||
|
}
|
||||||
|
props.onUpdate(selectedKeys, label, isSuper);
|
||||||
setSelectKey(selectedKeys);
|
setSelectKey(selectedKeys);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,13 +5,13 @@ import { resourceCategory } from "../../api/index";
|
|||||||
interface Option {
|
interface Option {
|
||||||
key: string | number;
|
key: string | number;
|
||||||
title: any;
|
title: any;
|
||||||
|
|
||||||
children?: Option[];
|
children?: Option[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PropInterface {
|
interface PropInterface {
|
||||||
type: string;
|
type: string;
|
||||||
text: string;
|
text: string;
|
||||||
|
selected: any;
|
||||||
onUpdate: (keys: any, title: any) => void;
|
onUpdate: (keys: any, title: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +20,12 @@ export const TreeCategory = (props: PropInterface) => {
|
|||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const [selectKey, setSelectKey] = useState<any>([]);
|
const [selectKey, setSelectKey] = useState<any>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.selected && props.selected.length > 0) {
|
||||||
|
setSelectKey(props.selected);
|
||||||
|
}
|
||||||
|
}, [props.selected]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
resourceCategory.resourceCategoryList().then((res: any) => {
|
resourceCategory.resourceCategoryList().then((res: any) => {
|
||||||
const categories = res.data.categories;
|
const categories = res.data.categories;
|
||||||
|
@ -13,6 +13,7 @@ interface PropInterface {
|
|||||||
text: string;
|
text: string;
|
||||||
refresh: boolean;
|
refresh: boolean;
|
||||||
showNum: boolean;
|
showNum: boolean;
|
||||||
|
selected: any;
|
||||||
onUpdate: (keys: any, title: any) => void;
|
onUpdate: (keys: any, title: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,6 +23,12 @@ export const TreeDepartment = (props: PropInterface) => {
|
|||||||
const [selectKey, setSelectKey] = useState<any>([]);
|
const [selectKey, setSelectKey] = useState<any>([]);
|
||||||
const [userTotal, setUserTotal] = useState(0);
|
const [userTotal, setUserTotal] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.selected && props.selected.length > 0) {
|
||||||
|
setSelectKey(props.selected);
|
||||||
|
}
|
||||||
|
}, [props.selected]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
department.departmentList().then((res: any) => {
|
department.departmentList().then((res: any) => {
|
||||||
|
@ -110,6 +110,7 @@ export const UploadImageButton = (props: PropsInterface) => {
|
|||||||
<Row style={{ width: 752, minHeight: 520, marginTop: 24 }}>
|
<Row style={{ width: 752, minHeight: 520, marginTop: 24 }}>
|
||||||
<Col span={7}>
|
<Col span={7}>
|
||||||
<TreeCategory
|
<TreeCategory
|
||||||
|
selected={category_ids}
|
||||||
type="no-cate"
|
type="no-cate"
|
||||||
text={"图片"}
|
text={"图片"}
|
||||||
onUpdate={(keys: any) => {
|
onUpdate={(keys: any) => {
|
||||||
|
@ -2,7 +2,7 @@ import { Button, message, Modal } from "antd";
|
|||||||
import Dragger from "antd/es/upload/Dragger";
|
import Dragger from "antd/es/upload/Dragger";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import config from "../../../js/config";
|
import config from "../../../js/config";
|
||||||
import { getToken } from "../../../utils";
|
import { getToken, checkUrl } from "../../../utils";
|
||||||
import { InboxOutlined } from "@ant-design/icons";
|
import { InboxOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
interface PropsInterface {
|
interface PropsInterface {
|
||||||
@ -17,8 +17,8 @@ export const UploadImageSub = (props: PropsInterface) => {
|
|||||||
name: "file",
|
name: "file",
|
||||||
multiple: true,
|
multiple: true,
|
||||||
action:
|
action:
|
||||||
config.app_url +
|
checkUrl(config.app_url) +
|
||||||
"/backend/v1/upload/minio?category_ids=" +
|
"backend/v1/upload/minio?category_ids=" +
|
||||||
props.categoryIds.join(","),
|
props.categoryIds.join(","),
|
||||||
headers: {
|
headers: {
|
||||||
authorization: "Bearer " + getToken(),
|
authorization: "Bearer " + getToken(),
|
||||||
|
@ -173,6 +173,7 @@ export const UploadVideoSub = (props: PropsInterface) => {
|
|||||||
<Row style={{ width: 752, minHeight: 520 }}>
|
<Row style={{ width: 752, minHeight: 520 }}>
|
||||||
<Col span={7}>
|
<Col span={7}>
|
||||||
<TreeCategory
|
<TreeCategory
|
||||||
|
selected={[]}
|
||||||
type="no-cate"
|
type="no-cate"
|
||||||
text={props.label}
|
text={props.label}
|
||||||
onUpdate={(keys: any) => setCategoryIds(keys)}
|
onUpdate={(keys: any) => setCategoryIds(keys)}
|
||||||
|
@ -519,16 +519,27 @@ textarea.ant-input {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-modal-confirm-btns > .ant-btn-default:hover {
|
.ant-modal-confirm-btns > .ant-btn-default {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none !important;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: none !important;
|
||||||
color: #ff4d4f !important;
|
color: #ff4d4f !important;
|
||||||
border-color: #ff4d4f;
|
border-color: #ff4d4f;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-modal-confirm-btns > .ant-btn-primary {
|
.ant-modal-confirm-btns > .ant-btn-primary {
|
||||||
|
border: none;
|
||||||
|
box-shadow: none !important;
|
||||||
background-color: #ff4d4f !important;
|
background-color: #ff4d4f !important;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
outline: none;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
box-shadow: none !important;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-tree-treenode {
|
.ant-tree-treenode {
|
||||||
|
@ -482,9 +482,9 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="必修选修"
|
label="课程属性"
|
||||||
name="isRequired"
|
name="isRequired"
|
||||||
rules={[{ required: true, message: "请选择必修选修!" }]}
|
rules={[{ required: true, message: "请选择课程属性!" }]}
|
||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Radio value={1}>必修课</Radio>
|
<Radio value={1}>必修课</Radio>
|
||||||
|
@ -230,9 +230,9 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="必修选修"
|
label="课程属性"
|
||||||
name="isRequired"
|
name="isRequired"
|
||||||
rules={[{ required: true, message: "请选择必修选修!" }]}
|
rules={[{ required: true, message: "请选择课程属性!" }]}
|
||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Radio value={1}>必修课</Radio>
|
<Radio value={1}>必修课</Radio>
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
import type { MenuProps } from "antd";
|
import type { MenuProps } from "antd";
|
||||||
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 { useNavigate } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
import { TreeDepartment, TreeCategory, PerButton } from "../../compenents";
|
import { TreeDepartment, TreeCategory, PerButton } from "../../compenents";
|
||||||
import type { TabsProps } from "antd";
|
import type { TabsProps } from "antd";
|
||||||
import { CourseCreate } from "./compenents/create";
|
import { CourseCreate } from "./compenents/create";
|
||||||
@ -40,6 +40,7 @@ interface DataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CoursePage = () => {
|
const CoursePage = () => {
|
||||||
|
const result = new URLSearchParams(useLocation().search);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [list, setList] = useState<any>([]);
|
const [list, setList] = useState<any>([]);
|
||||||
const [refresh, setRefresh] = useState(false);
|
const [refresh, setRefresh] = useState(false);
|
||||||
@ -50,18 +51,43 @@ const CoursePage = () => {
|
|||||||
const [category_ids, setCategoryIds] = useState<any>([]);
|
const [category_ids, setCategoryIds] = useState<any>([]);
|
||||||
const [title, setTitle] = useState<string>("");
|
const [title, setTitle] = useState<string>("");
|
||||||
const [dep_ids, setDepIds] = useState<any>([]);
|
const [dep_ids, setDepIds] = useState<any>([]);
|
||||||
const [selLabel, setLabel] = useState<string>("全部分类");
|
const [selLabel, setLabel] = useState<string>(
|
||||||
const [selDepLabel, setDepLabel] = useState<string>("全部部门");
|
result.get("label") ? String(result.get("label")) : "全部分类"
|
||||||
|
);
|
||||||
|
const [selDepLabel, setDepLabel] = useState<string>(
|
||||||
|
result.get("label") ? String(result.get("label")) : "全部部门"
|
||||||
|
);
|
||||||
const [course_category_ids, setCourseCategoryIds] = useState<any>({});
|
const [course_category_ids, setCourseCategoryIds] = useState<any>({});
|
||||||
const [course_dep_ids, setCourseDepIds] = useState<any>({});
|
const [course_dep_ids, setCourseDepIds] = useState<any>({});
|
||||||
const [categories, setCategories] = useState<any>({});
|
const [categories, setCategories] = useState<any>({});
|
||||||
const [departments, setDepartments] = useState<any>({});
|
const [departments, setDepartments] = useState<any>({});
|
||||||
const [tabKey, setTabKey] = useState(1);
|
const [tabKey, setTabKey] = useState(result.get("did") ? "2" : "1");
|
||||||
|
|
||||||
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 [updateHourVisible, setHourUpdateVisible] = useState<boolean>(false);
|
const [updateHourVisible, setHourUpdateVisible] = useState<boolean>(false);
|
||||||
const [cid, setCid] = useState<number>(0);
|
const [cid, setCid] = useState<number>(0);
|
||||||
|
const [cateId, setCateId] = useState(Number(result.get("cid")));
|
||||||
|
const [did, setDid] = useState(Number(result.get("did")));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getList();
|
||||||
|
}, [category_ids, dep_ids, refresh, page, size, tabKey]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCateId(Number(result.get("cid")));
|
||||||
|
if (Number(result.get("cid"))) {
|
||||||
|
let arr = [];
|
||||||
|
arr.push(Number(result.get("cid")));
|
||||||
|
setCategoryIds(arr);
|
||||||
|
}
|
||||||
|
setDid(Number(result.get("did")));
|
||||||
|
if (Number(result.get("did"))) {
|
||||||
|
let arr = [];
|
||||||
|
arr.push(Number(result.get("did")));
|
||||||
|
setDepIds(arr);
|
||||||
|
}
|
||||||
|
}, [result.get("cid"), result.get("did")]);
|
||||||
|
|
||||||
const items: TabsProps["items"] = [
|
const items: TabsProps["items"] = [
|
||||||
{
|
{
|
||||||
@ -70,9 +96,11 @@ const CoursePage = () => {
|
|||||||
children: (
|
children: (
|
||||||
<div className="float-left">
|
<div className="float-left">
|
||||||
<TreeCategory
|
<TreeCategory
|
||||||
|
selected={category_ids}
|
||||||
type=""
|
type=""
|
||||||
text={"分类"}
|
text={"分类"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any) => {
|
||||||
|
setPage(1);
|
||||||
setCategoryIds(keys);
|
setCategoryIds(keys);
|
||||||
if (typeof title === "string") {
|
if (typeof title === "string") {
|
||||||
setLabel(title);
|
setLabel(title);
|
||||||
@ -90,11 +118,13 @@ const CoursePage = () => {
|
|||||||
children: (
|
children: (
|
||||||
<div className="float-left">
|
<div className="float-left">
|
||||||
<TreeDepartment
|
<TreeDepartment
|
||||||
|
selected={dep_ids}
|
||||||
refresh={refresh}
|
refresh={refresh}
|
||||||
showNum={false}
|
showNum={false}
|
||||||
type="no-course"
|
type="no-course"
|
||||||
text={"部门"}
|
text={"部门"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any) => {
|
||||||
|
setPage(1);
|
||||||
setDepIds(keys);
|
setDepIds(keys);
|
||||||
setDepLabel(title);
|
setDepLabel(title);
|
||||||
}}
|
}}
|
||||||
@ -288,7 +318,7 @@ const CoursePage = () => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
let categoryIds = "";
|
let categoryIds = "";
|
||||||
let depIds = "";
|
let depIds = "";
|
||||||
if (tabKey === 1) {
|
if (tabKey === "1") {
|
||||||
categoryIds = category_ids.join(",");
|
categoryIds = category_ids.join(",");
|
||||||
} else {
|
} else {
|
||||||
depIds = dep_ids.join(",");
|
depIds = dep_ids.join(",");
|
||||||
@ -317,11 +347,6 @@ const CoursePage = () => {
|
|||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载列表
|
|
||||||
useEffect(() => {
|
|
||||||
getList();
|
|
||||||
}, [category_ids, dep_ids, refresh, page, size, tabKey]);
|
|
||||||
|
|
||||||
const paginationProps = {
|
const paginationProps = {
|
||||||
current: page, //当前页码
|
current: page, //当前页码
|
||||||
pageSize: size,
|
pageSize: size,
|
||||||
@ -337,7 +362,7 @@ const CoursePage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onChange = (key: string) => {
|
const onChange = (key: string) => {
|
||||||
setTabKey(Number(key));
|
setTabKey(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -345,7 +370,7 @@ const CoursePage = () => {
|
|||||||
<div className="tree-main-body">
|
<div className="tree-main-body">
|
||||||
<div className="left-box">
|
<div className="left-box">
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultActiveKey="1"
|
defaultActiveKey={tabKey}
|
||||||
centered
|
centered
|
||||||
tabBarGutter={55}
|
tabBarGutter={55}
|
||||||
items={items}
|
items={items}
|
||||||
@ -354,7 +379,7 @@ const CoursePage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="right-box">
|
<div className="right-box">
|
||||||
<div className="playedu-main-title float-left mb-24">
|
<div className="playedu-main-title float-left mb-24">
|
||||||
线上课 | {tabKey === 1 ? selLabel : selDepLabel}
|
线上课 | {tabKey === "1" ? selLabel : selDepLabel}
|
||||||
</div>
|
</div>
|
||||||
<div className="float-left j-b-flex mb-24">
|
<div className="float-left j-b-flex mb-24">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
@ -406,8 +431,8 @@ const CoursePage = () => {
|
|||||||
rowKey={(record) => record.id}
|
rowKey={(record) => record.id}
|
||||||
/>
|
/>
|
||||||
<CourseCreate
|
<CourseCreate
|
||||||
cateIds={tabKey === 1 ? category_ids : []}
|
cateIds={tabKey === "1" ? category_ids : []}
|
||||||
depIds={tabKey === 2 ? dep_ids : []}
|
depIds={tabKey === "2" ? dep_ids : []}
|
||||||
open={createVisible}
|
open={createVisible}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setCreateVisible(false);
|
setCreateVisible(false);
|
||||||
|
@ -89,7 +89,12 @@ const DepartmentPage = () => {
|
|||||||
<i
|
<i
|
||||||
className="iconfont icon-icon-delete"
|
className="iconfont icon-icon-delete"
|
||||||
style={{ fontSize: 24 }}
|
style={{ fontSize: 24 }}
|
||||||
onClick={() => removeItem(departments[id][i].id)}
|
onClick={() =>
|
||||||
|
removeItem(
|
||||||
|
departments[id][i].id,
|
||||||
|
departments[id][i].name
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -124,7 +129,12 @@ const DepartmentPage = () => {
|
|||||||
<i
|
<i
|
||||||
className="iconfont icon-icon-delete"
|
className="iconfont icon-icon-delete"
|
||||||
style={{ fontSize: 24 }}
|
style={{ fontSize: 24 }}
|
||||||
onClick={() => removeItem(departments[id][i].id)}
|
onClick={() =>
|
||||||
|
removeItem(
|
||||||
|
departments[id][i].id,
|
||||||
|
departments[id][i].name
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -144,19 +154,22 @@ const DepartmentPage = () => {
|
|||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeItem = (id: number) => {
|
const removeItem = (id: number, label: string) => {
|
||||||
if (id === 0) {
|
if (id === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
department.checkDestroy(id).then((res: any) => {
|
department.checkDestroy(id).then((res: any) => {
|
||||||
if (
|
if (
|
||||||
|
res.data.children &&
|
||||||
res.data.children.length === 0 &&
|
res.data.children.length === 0 &&
|
||||||
|
res.data.courses &&
|
||||||
res.data.courses.length === 0 &&
|
res.data.courses.length === 0 &&
|
||||||
|
res.data.users &&
|
||||||
res.data.users.length === 0
|
res.data.users.length === 0
|
||||||
) {
|
) {
|
||||||
delUser(id);
|
delUser(id);
|
||||||
} else {
|
} else {
|
||||||
if (res.data.children.length > 0) {
|
if (res.data.children && res.data.children.length > 0) {
|
||||||
modal.warning({
|
modal.warning({
|
||||||
title: "操作确认",
|
title: "操作确认",
|
||||||
centered: true,
|
centered: true,
|
||||||
@ -179,22 +192,26 @@ const DepartmentPage = () => {
|
|||||||
content: (
|
content: (
|
||||||
<p>
|
<p>
|
||||||
此部门已关联
|
此部门已关联
|
||||||
{res.data.courses.length > 0 && (
|
{res.data.courses && res.data.courses.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
style={{ paddingLeft: 4, paddingRight: 4 }}
|
style={{ paddingLeft: 4, paddingRight: 4 }}
|
||||||
type="link"
|
type="link"
|
||||||
danger
|
danger
|
||||||
onClick={() => navigate("/course")}
|
onClick={() =>
|
||||||
|
navigate("/course?did=" + id + "&label=" + label)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
({res.data.courses.length}个线上课程),
|
({res.data.courses.length}个线上课程),
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{res.data.users.length > 0 && (
|
{res.data.users && res.data.users.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
style={{ paddingLeft: 4, paddingRight: 4 }}
|
style={{ paddingLeft: 4, paddingRight: 4 }}
|
||||||
danger
|
danger
|
||||||
onClick={() => navigate("/member/index")}
|
onClick={() =>
|
||||||
|
navigate("/member/index?did=" + id + "&label=" + label)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
({res.data.users.length}个学员),
|
({res.data.users.length}个学员),
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { user } from "../../api/index";
|
import { user } from "../../api/index";
|
||||||
import { dateFormat } from "../../utils/index";
|
import { dateFormat } from "../../utils/index";
|
||||||
import { Link, Navigate } from "react-router-dom";
|
import { Link, Navigate, useLocation } from "react-router-dom";
|
||||||
import { TreeDepartment, PerButton } from "../../compenents";
|
import { TreeDepartment, PerButton } from "../../compenents";
|
||||||
import { MemberCreate } from "./compenents/create";
|
import { MemberCreate } from "./compenents/create";
|
||||||
import { MemberUpdate } from "./compenents/update";
|
import { MemberUpdate } from "./compenents/update";
|
||||||
@ -37,6 +37,7 @@ interface DataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MemberPage = () => {
|
const MemberPage = () => {
|
||||||
|
const result = new URLSearchParams(useLocation().search);
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [size, setSize] = useState(10);
|
const [size, setSize] = useState(10);
|
||||||
@ -47,12 +48,24 @@ const MemberPage = () => {
|
|||||||
const [nickname, setNickname] = useState<string>("");
|
const [nickname, setNickname] = useState<string>("");
|
||||||
const [email, setEmail] = useState<string>("");
|
const [email, setEmail] = useState<string>("");
|
||||||
const [dep_ids, setDepIds] = useState<any>([]);
|
const [dep_ids, setDepIds] = useState<any>([]);
|
||||||
const [selLabel, setLabel] = useState<string>("全部部门");
|
const [selLabel, setLabel] = useState<string>(
|
||||||
|
result.get("label") ? String(result.get("label")) : "全部部门"
|
||||||
|
);
|
||||||
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 [mid, setMid] = useState<number>(0);
|
const [mid, setMid] = useState<number>(0);
|
||||||
const [user_dep_ids, setUserDepIds] = useState<any>({});
|
const [user_dep_ids, setUserDepIds] = useState<any>({});
|
||||||
const [departments, setDepartments] = useState<any>({});
|
const [departments, setDepartments] = useState<any>({});
|
||||||
|
const [did, setDid] = useState(Number(result.get("did")));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDid(Number(result.get("did")));
|
||||||
|
if (Number(result.get("did"))) {
|
||||||
|
let arr = [];
|
||||||
|
arr.push(Number(result.get("did")));
|
||||||
|
setDepIds(arr);
|
||||||
|
}
|
||||||
|
}, [result.get("did")]);
|
||||||
|
|
||||||
const columns: ColumnsType<DataType> = [
|
const columns: ColumnsType<DataType> = [
|
||||||
{
|
{
|
||||||
@ -247,11 +260,13 @@ const MemberPage = () => {
|
|||||||
<div className="tree-main-body">
|
<div className="tree-main-body">
|
||||||
<div className="left-box">
|
<div className="left-box">
|
||||||
<TreeDepartment
|
<TreeDepartment
|
||||||
|
selected={dep_ids}
|
||||||
refresh={refresh}
|
refresh={refresh}
|
||||||
showNum={true}
|
showNum={true}
|
||||||
type=""
|
type=""
|
||||||
text={"部门"}
|
text={"部门"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any) => {
|
||||||
|
setPage(1);
|
||||||
setDepIds(keys);
|
setDepIds(keys);
|
||||||
var index = title.indexOf("(");
|
var index = title.indexOf("(");
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
Pagination,
|
Pagination,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { resource } from "../../../api";
|
import { resource } from "../../../api";
|
||||||
|
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, PerButton } from "../../../compenents";
|
||||||
@ -32,6 +33,7 @@ interface ImageItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ResourceImagesPage = () => {
|
const ResourceImagesPage = () => {
|
||||||
|
const result = new URLSearchParams(useLocation().search);
|
||||||
const [imageList, setImageList] = useState<ImageItem[]>([]);
|
const [imageList, setImageList] = useState<ImageItem[]>([]);
|
||||||
const [refresh, setRefresh] = useState(false);
|
const [refresh, setRefresh] = useState(false);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
@ -41,8 +43,25 @@ const ResourceImagesPage = () => {
|
|||||||
const [selectKey, setSelectKey] = useState<any>([]);
|
const [selectKey, setSelectKey] = useState<any>([]);
|
||||||
const [visibleArr, setVisibleArr] = useState<any>([]);
|
const [visibleArr, setVisibleArr] = useState<any>([]);
|
||||||
const [hoverArr, setHoverArr] = useState<any>([]);
|
const [hoverArr, setHoverArr] = useState<any>([]);
|
||||||
const [selLabel, setLabel] = useState<string>("全部图片");
|
const [selLabel, setLabel] = useState<string>(
|
||||||
|
result.get("label") ? String(result.get("label")) : "全部图片"
|
||||||
|
);
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [cateId, setCateId] = useState(Number(result.get("cid")));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCateId(Number(result.get("cid")));
|
||||||
|
if (Number(result.get("cid"))) {
|
||||||
|
let arr = [];
|
||||||
|
arr.push(Number(result.get("cid")));
|
||||||
|
setCategoryIds(arr);
|
||||||
|
}
|
||||||
|
}, [result.get("cid")]);
|
||||||
|
|
||||||
|
// 加载图片列表
|
||||||
|
useEffect(() => {
|
||||||
|
getImageList();
|
||||||
|
}, [category_ids, refresh, page, size]);
|
||||||
|
|
||||||
// 删除图片
|
// 删除图片
|
||||||
const removeResource = () => {
|
const removeResource = () => {
|
||||||
@ -70,9 +89,6 @@ const ResourceImagesPage = () => {
|
|||||||
|
|
||||||
// 获取图片列表
|
// 获取图片列表
|
||||||
const getImageList = () => {
|
const getImageList = () => {
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
let categoryIds = category_ids.join(",");
|
let categoryIds = category_ids.join(",");
|
||||||
resource
|
resource
|
||||||
@ -102,11 +118,6 @@ const ResourceImagesPage = () => {
|
|||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载图片列表
|
|
||||||
useEffect(() => {
|
|
||||||
getImageList();
|
|
||||||
}, [category_ids, refresh, page, size]);
|
|
||||||
|
|
||||||
const onChange = (e: any, id: number) => {
|
const onChange = (e: any, id: number) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -151,9 +162,11 @@ const ResourceImagesPage = () => {
|
|||||||
<div className="tree-main-body">
|
<div className="tree-main-body">
|
||||||
<div className="left-box">
|
<div className="left-box">
|
||||||
<TreeCategory
|
<TreeCategory
|
||||||
|
selected={category_ids}
|
||||||
type="no-cate"
|
type="no-cate"
|
||||||
text={"图片"}
|
text={"图片"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any) => {
|
||||||
|
setPage(1);
|
||||||
setCategoryIds(keys);
|
setCategoryIds(keys);
|
||||||
if (typeof title === "string") {
|
if (typeof title === "string") {
|
||||||
setLabel(title);
|
setLabel(title);
|
||||||
@ -187,15 +200,13 @@ const ResourceImagesPage = () => {
|
|||||||
<Button className="mr-16" onClick={() => selectAll()}>
|
<Button className="mr-16" onClick={() => selectAll()}>
|
||||||
全选
|
全选
|
||||||
</Button>
|
</Button>
|
||||||
<PerButton
|
<Button
|
||||||
disabled={selectKey.length === 0}
|
disabled={selectKey.length === 0}
|
||||||
type="primary"
|
type="primary"
|
||||||
text="删除"
|
|
||||||
class=""
|
|
||||||
icon={null}
|
|
||||||
p="resource-destroy"
|
|
||||||
onClick={() => removeResource()}
|
onClick={() => removeResource()}
|
||||||
/>
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,13 +84,13 @@ const ResourceCategoryPage = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{through("resource-destroy") && (
|
|
||||||
<i
|
<i
|
||||||
className="iconfont icon-icon-delete"
|
className="iconfont icon-icon-delete"
|
||||||
style={{ fontSize: 24 }}
|
style={{ fontSize: 24 }}
|
||||||
onClick={() => removeItem(categories[id][i].id)}
|
onClick={() =>
|
||||||
|
removeItem(categories[id][i].id, categories[id][i].name)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@ -119,13 +119,13 @@ const ResourceCategoryPage = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{through("resource-destroy") && (
|
|
||||||
<i
|
<i
|
||||||
className="iconfont icon-icon-delete"
|
className="iconfont icon-icon-delete"
|
||||||
style={{ fontSize: 24 }}
|
style={{ fontSize: 24 }}
|
||||||
onClick={() => removeItem(categories[id][i].id)}
|
onClick={() =>
|
||||||
|
removeItem(categories[id][i].id, categories[id][i].name)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@ -142,20 +142,24 @@ const ResourceCategoryPage = () => {
|
|||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeItem = (id: number) => {
|
const removeItem = (id: number, label: string) => {
|
||||||
if (id === 0) {
|
if (id === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resourceCategory.checkDestroy(id).then((res: any) => {
|
resourceCategory.checkDestroy(id).then((res: any) => {
|
||||||
if (
|
if (
|
||||||
|
res.data.children &&
|
||||||
res.data.children.length === 0 &&
|
res.data.children.length === 0 &&
|
||||||
|
res.data.courses &&
|
||||||
res.data.courses.length === 0 &&
|
res.data.courses.length === 0 &&
|
||||||
|
res.data.images &&
|
||||||
res.data.images.length === 0 &&
|
res.data.images.length === 0 &&
|
||||||
|
res.data.videos &&
|
||||||
res.data.videos.length === 0
|
res.data.videos.length === 0
|
||||||
) {
|
) {
|
||||||
delUser(id);
|
delUser(id);
|
||||||
} else {
|
} else {
|
||||||
if (res.data.children.length > 0) {
|
if (res.data.children && res.data.children.length > 0) {
|
||||||
modal.warning({
|
modal.warning({
|
||||||
title: "操作确认",
|
title: "操作确认",
|
||||||
centered: true,
|
centered: true,
|
||||||
@ -178,32 +182,38 @@ const ResourceCategoryPage = () => {
|
|||||||
content: (
|
content: (
|
||||||
<p>
|
<p>
|
||||||
此分类已关联
|
此分类已关联
|
||||||
{res.data.courses.length > 0 && (
|
{res.data.courses && res.data.courses.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
style={{ paddingLeft: 4, paddingRight: 4 }}
|
style={{ paddingLeft: 4, paddingRight: 4 }}
|
||||||
type="link"
|
type="link"
|
||||||
danger
|
danger
|
||||||
onClick={() => navigate("/course")}
|
onClick={() =>
|
||||||
|
navigate("/course?cid=" + id + "&label=" + label)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
({res.data.courses.length}个线上课程),
|
({res.data.courses.length}个线上课程),
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{res.data.videos.length > 0 && (
|
{res.data.videos && res.data.videos.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
style={{ paddingLeft: 4, paddingRight: 4 }}
|
style={{ paddingLeft: 4, paddingRight: 4 }}
|
||||||
danger
|
danger
|
||||||
onClick={() => navigate("/videos")}
|
onClick={() =>
|
||||||
|
navigate("/videos?cid=" + id + "&label=" + label)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
({res.data.videos.length}个视频文件),
|
({res.data.videos.length}个视频文件),
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{res.data.images.length > 0 && (
|
{res.data.images && res.data.images.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
style={{ paddingLeft: 4, paddingRight: 4 }}
|
style={{ paddingLeft: 4, paddingRight: 4 }}
|
||||||
danger
|
danger
|
||||||
onClick={() => navigate("/images")}
|
onClick={() =>
|
||||||
|
navigate("/images?cid=" + id + "&label=" + label)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
({res.data.images.length}个图片文件),
|
({res.data.images.length}个图片文件),
|
||||||
</Button>
|
</Button>
|
||||||
|
143
src/pages/resource/videos/compenents/update-dialog/index.tsx
Normal file
143
src/pages/resource/videos/compenents/update-dialog/index.tsx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Modal, Form, Input, message, TreeSelect } from "antd";
|
||||||
|
import { resource, resourceCategory } from "../../../../../api/index";
|
||||||
|
|
||||||
|
interface PropInterface {
|
||||||
|
id: number;
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
onSuccess: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VideosUpdateDialog: React.FC<PropInterface> = ({
|
||||||
|
id,
|
||||||
|
open,
|
||||||
|
onCancel,
|
||||||
|
onSuccess,
|
||||||
|
}) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
const [categories, setCategories] = useState<any>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (id === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (open) {
|
||||||
|
getCategory();
|
||||||
|
getDetail();
|
||||||
|
}
|
||||||
|
}, [id, open]);
|
||||||
|
|
||||||
|
const getCategory = () => {
|
||||||
|
resourceCategory.resourceCategoryList().then((res: any) => {
|
||||||
|
const categories = res.data.categories;
|
||||||
|
if (JSON.stringify(categories) !== "{}") {
|
||||||
|
const new_arr: any = checkArr(categories, 0, null);
|
||||||
|
setCategories(new_arr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDetail = () => {
|
||||||
|
resource.videoDetail(id).then((res: any) => {
|
||||||
|
let data = res.data.resources;
|
||||||
|
form.setFieldsValue({
|
||||||
|
name: data.name,
|
||||||
|
category_id: res.data.category_ids,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkArr = (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: departments[id][i].name,
|
||||||
|
value: departments[id][i].id,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const new_arr: any = checkArr(
|
||||||
|
departments,
|
||||||
|
departments[id][i].id,
|
||||||
|
counts
|
||||||
|
);
|
||||||
|
arr.push({
|
||||||
|
title: departments[id][i].name,
|
||||||
|
value: departments[id][i].id,
|
||||||
|
children: new_arr,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinish = (values: any) => {
|
||||||
|
if (Array.isArray(values.category_id)) {
|
||||||
|
values.category_id = values.category_id[0];
|
||||||
|
}
|
||||||
|
resource.videoUpdate(id, values).then((res: any) => {
|
||||||
|
message.success("保存成功!");
|
||||||
|
onSuccess();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinishFailed = (errorInfo: any) => {
|
||||||
|
console.log("Failed:", errorInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal
|
||||||
|
title="编辑视频"
|
||||||
|
centered
|
||||||
|
forceRender
|
||||||
|
open={open}
|
||||||
|
width={416}
|
||||||
|
onOk={() => form.submit()}
|
||||||
|
onCancel={() => onCancel()}
|
||||||
|
maskClosable={false}
|
||||||
|
>
|
||||||
|
<div className="float-left mt-24">
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
name="videos-update"
|
||||||
|
labelCol={{ span: 8 }}
|
||||||
|
wrapperCol={{ span: 16 }}
|
||||||
|
initialValues={{ remember: true }}
|
||||||
|
onFinish={onFinish}
|
||||||
|
onFinishFailed={onFinishFailed}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="视频分类"
|
||||||
|
name="category_id"
|
||||||
|
rules={[{ required: true, message: "请选择视频分类!" }]}
|
||||||
|
>
|
||||||
|
<TreeSelect
|
||||||
|
showCheckedStrategy={TreeSelect.SHOW_ALL}
|
||||||
|
allowClear
|
||||||
|
style={{ width: 200 }}
|
||||||
|
treeData={categories}
|
||||||
|
placeholder="视频分类"
|
||||||
|
treeDefaultExpandAll
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="视频名称"
|
||||||
|
name="name"
|
||||||
|
rules={[{ required: true, message: "请输入视频名称!" }]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
allowClear
|
||||||
|
style={{ width: 200 }}
|
||||||
|
placeholder="请输入视频名称"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
.play-mask {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
position: fixed;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 200;
|
||||||
|
.play-dialog {
|
||||||
|
width: 800px;
|
||||||
|
height: 450px;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
.close-button {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
position: absolute;
|
||||||
|
top: 24px;
|
||||||
|
right: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1000;
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.play-box {
|
||||||
|
width: 800px;
|
||||||
|
height: 450px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import styles from "./index.module.less";
|
||||||
|
import closeIcon from "../../../../../assets/images/commen/close.png";
|
||||||
|
|
||||||
|
interface PropInterface {
|
||||||
|
id: number;
|
||||||
|
url: string;
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const window: any;
|
||||||
|
|
||||||
|
export const VideoPlayDialog: React.FC<PropInterface> = ({
|
||||||
|
id,
|
||||||
|
url,
|
||||||
|
open,
|
||||||
|
onCancel,
|
||||||
|
}) => {
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open && url) {
|
||||||
|
initDPlayer(url);
|
||||||
|
}
|
||||||
|
}, [id, open, url]);
|
||||||
|
|
||||||
|
const initDPlayer = (playUrl: string) => {
|
||||||
|
window.player = new window.DPlayer({
|
||||||
|
container: document.getElementById("meedu-player-container"),
|
||||||
|
autoplay: false,
|
||||||
|
video: {
|
||||||
|
url: playUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
window.player.on("ended", () => {
|
||||||
|
window.player && window.player.destroy();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{open && (
|
||||||
|
<div className={styles["play-mask"]}>
|
||||||
|
<div className={styles["play-dialog"]}>
|
||||||
|
<div
|
||||||
|
className={styles["close-button"]}
|
||||||
|
onClick={() => {
|
||||||
|
window.player && window.player.destroy();
|
||||||
|
onCancel();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src={closeIcon} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={styles["play-box"]}
|
||||||
|
id="meedu-player-container"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -1,12 +1,16 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Modal, Table, message, Space } from "antd";
|
import { Modal, Table, message, Space, Dropdown, Button } from "antd";
|
||||||
|
import type { MenuProps } from "antd";
|
||||||
import { resource } from "../../../api";
|
import { resource } from "../../../api";
|
||||||
// import styles from "./index.module.less";
|
// import styles from "./index.module.less";
|
||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
import { useLocation } from "react-router-dom";
|
||||||
|
import { DownOutlined, 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, DurationText, PerButton } from "../../../compenents";
|
import { TreeCategory, DurationText, PerButton } from "../../../compenents";
|
||||||
import { UploadVideoButton } from "../../../compenents/upload-video-button";
|
import { UploadVideoButton } from "../../../compenents/upload-video-button";
|
||||||
|
import { VideoPlayDialog } from "./compenents/video-play-dialog";
|
||||||
|
import { VideosUpdateDialog } from "./compenents/update-dialog";
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@ -18,6 +22,7 @@ interface DataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ResourceVideosPage = () => {
|
const ResourceVideosPage = () => {
|
||||||
|
const result = new URLSearchParams(useLocation().search);
|
||||||
const [videoList, setVideoList] = useState<any>([]);
|
const [videoList, setVideoList] = useState<any>([]);
|
||||||
const [videosExtra, setVideoExtra] = useState<any>([]);
|
const [videosExtra, setVideoExtra] = useState<any>([]);
|
||||||
const [adminUsers, setAdminUsers] = useState<any>({});
|
const [adminUsers, setAdminUsers] = useState<any>({});
|
||||||
@ -27,21 +32,27 @@ const ResourceVideosPage = () => {
|
|||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const [category_ids, setCategoryIds] = useState<any>([]);
|
const [category_ids, setCategoryIds] = useState<any>([]);
|
||||||
const [selLabel, setLabel] = useState<string>("全部视频");
|
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
||||||
|
const [selLabel, setLabel] = useState<string>(
|
||||||
|
result.get("label") ? String(result.get("label")) : "全部视频"
|
||||||
|
);
|
||||||
|
const [cateId, setCateId] = useState(Number(result.get("cid")));
|
||||||
|
const [updateVisible, setUpdateVisible] = useState<boolean>(false);
|
||||||
|
const [playVisible, setPlayeVisible] = useState<boolean>(false);
|
||||||
|
const [multiConfig, setMultiConfig] = useState<boolean>(false);
|
||||||
|
const [updateId, setUpdateId] = useState(0);
|
||||||
|
const [playUrl, setPlayUrl] = useState<string>("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCateId(Number(result.get("cid")));
|
||||||
|
if (Number(result.get("cid"))) {
|
||||||
|
let arr = [];
|
||||||
|
arr.push(Number(result.get("cid")));
|
||||||
|
setCategoryIds(arr);
|
||||||
|
}
|
||||||
|
}, [result.get("cid")]);
|
||||||
|
|
||||||
const columns: ColumnsType<DataType> = [
|
const columns: ColumnsType<DataType> = [
|
||||||
// {
|
|
||||||
// title: "封面",
|
|
||||||
// dataIndex: "id",
|
|
||||||
// render: (id: string) => (
|
|
||||||
// <Image
|
|
||||||
// preview={false}
|
|
||||||
// width={120}
|
|
||||||
// height={80}
|
|
||||||
// src={videosExtra[id].poster}
|
|
||||||
// ></Image>
|
|
||||||
// ),
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
title: "视频名称",
|
title: "视频名称",
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
@ -80,21 +91,69 @@ const ResourceVideosPage = () => {
|
|||||||
title: "操作",
|
title: "操作",
|
||||||
key: "action",
|
key: "action",
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
width: 100,
|
width: 160,
|
||||||
render: (_, record: any) => (
|
render: (_, record: any) => {
|
||||||
<Space size="small">
|
const items: MenuProps["items"] = [
|
||||||
<PerButton
|
{
|
||||||
|
key: "1",
|
||||||
|
label: (
|
||||||
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
text="删除"
|
className="b-link c-red"
|
||||||
class="b-link c-red"
|
onClick={() => {
|
||||||
icon={null}
|
setUpdateId(record.id);
|
||||||
p="resource-destroy"
|
setUpdateVisible(true);
|
||||||
onClick={() => removeResource(record.id)}
|
}}
|
||||||
disabled={null}
|
>
|
||||||
/>
|
编辑
|
||||||
</Space>
|
</Button>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "2",
|
||||||
|
label: (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
className="b-link c-red"
|
||||||
|
onClick={() => removeResource(record.id)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space size="small">
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
className="b-n-link c-red"
|
||||||
|
onClick={() => {
|
||||||
|
setUpdateId(record.id);
|
||||||
|
setPlayUrl(record.url);
|
||||||
|
setPlayeVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
预览
|
||||||
|
</Button>
|
||||||
|
<div className="form-column"></div>
|
||||||
|
<Dropdown menu={{ items }}>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
className="b-link c-red"
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
<Space size="small" align="center">
|
||||||
|
更多
|
||||||
|
<DownOutlined />
|
||||||
|
</Space>
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// 删除图片
|
// 删除图片
|
||||||
@ -105,7 +164,7 @@ const ResourceVideosPage = () => {
|
|||||||
confirm({
|
confirm({
|
||||||
title: "操作确认",
|
title: "操作确认",
|
||||||
icon: <ExclamationCircleFilled />,
|
icon: <ExclamationCircleFilled />,
|
||||||
content: "确认删除此视频?",
|
content: "删除前请检查选中视频文件无关联课程,确认删除?",
|
||||||
centered: true,
|
centered: true,
|
||||||
okText: "确认",
|
okText: "确认",
|
||||||
cancelText: "取消",
|
cancelText: "取消",
|
||||||
@ -121,6 +180,29 @@ const ResourceVideosPage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeResourceMulti = () => {
|
||||||
|
if (selectedRowKeys.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirm({
|
||||||
|
title: "操作确认",
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
content: "删除前请检查选中视频文件无关联课程,确认删除?",
|
||||||
|
centered: true,
|
||||||
|
okText: "确认",
|
||||||
|
cancelText: "取消",
|
||||||
|
onOk() {
|
||||||
|
resource.destroyResourceMulti(selectedRowKeys).then(() => {
|
||||||
|
message.success("删除成功");
|
||||||
|
resetVideoList();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
console.log("Cancel");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 获取视频列表
|
// 获取视频列表
|
||||||
const getVideoList = () => {
|
const getVideoList = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -138,11 +220,13 @@ const ResourceVideosPage = () => {
|
|||||||
console.log("错误,", err);
|
console.log("错误,", err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重置列表
|
// 重置列表
|
||||||
const resetVideoList = () => {
|
const resetVideoList = () => {
|
||||||
setPage(1);
|
setPage(1);
|
||||||
setSize(10);
|
setSize(10);
|
||||||
setVideoList([]);
|
setVideoList([]);
|
||||||
|
setSelectedRowKeys([]);
|
||||||
setRefresh(!refresh);
|
setRefresh(!refresh);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -165,14 +249,22 @@ const ResourceVideosPage = () => {
|
|||||||
setSize(pageSize);
|
setSize(pageSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rowSelection = {
|
||||||
|
onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
|
||||||
|
setSelectedRowKeys(selectedRowKeys);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="tree-main-body">
|
<div className="tree-main-body">
|
||||||
<div className="left-box">
|
<div className="left-box">
|
||||||
<TreeCategory
|
<TreeCategory
|
||||||
|
selected={category_ids}
|
||||||
type="no-cate"
|
type="no-cate"
|
||||||
text={"视频"}
|
text={"视频"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any) => {
|
||||||
|
setPage(1);
|
||||||
setCategoryIds(keys);
|
setCategoryIds(keys);
|
||||||
if (typeof title === "string") {
|
if (typeof title === "string") {
|
||||||
setLabel(title);
|
setLabel(title);
|
||||||
@ -186,7 +278,8 @@ const ResourceVideosPage = () => {
|
|||||||
<div className="d-flex playedu-main-title float-left mb-24">
|
<div className="d-flex playedu-main-title float-left mb-24">
|
||||||
视频 | {selLabel}
|
视频 | {selLabel}
|
||||||
</div>
|
</div>
|
||||||
<div className="float-left mb-24">
|
<div className="float-left j-b-flex mb-24">
|
||||||
|
<div>
|
||||||
<UploadVideoButton
|
<UploadVideoButton
|
||||||
categoryIds={category_ids}
|
categoryIds={category_ids}
|
||||||
onUpdate={() => {
|
onUpdate={() => {
|
||||||
@ -194,7 +287,40 @@ const ResourceVideosPage = () => {
|
|||||||
}}
|
}}
|
||||||
></UploadVideoButton>
|
></UploadVideoButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="d-flex">
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
className="mr-16"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedRowKeys([]);
|
||||||
|
setMultiConfig(!multiConfig);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{multiConfig ? "取消操作" : "批量操作"}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
onClick={() => removeResourceMulti()}
|
||||||
|
disabled={selectedRowKeys.length === 0}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="float-left">
|
<div className="float-left">
|
||||||
|
{multiConfig ? (
|
||||||
|
<Table
|
||||||
|
rowSelection={{
|
||||||
|
type: "checkbox",
|
||||||
|
...rowSelection,
|
||||||
|
}}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={videoList}
|
||||||
|
loading={loading}
|
||||||
|
pagination={paginationProps}
|
||||||
|
rowKey={(record) => record.id}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={videoList}
|
dataSource={videoList}
|
||||||
@ -202,8 +328,24 @@ const ResourceVideosPage = () => {
|
|||||||
pagination={paginationProps}
|
pagination={paginationProps}
|
||||||
rowKey={(record) => record.id}
|
rowKey={(record) => record.id}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<VideoPlayDialog
|
||||||
|
id={Number(updateId)}
|
||||||
|
open={playVisible}
|
||||||
|
url={playUrl}
|
||||||
|
onCancel={() => setPlayeVisible(false)}
|
||||||
|
></VideoPlayDialog>
|
||||||
|
<VideosUpdateDialog
|
||||||
|
id={Number(updateId)}
|
||||||
|
open={updateVisible}
|
||||||
|
onCancel={() => setUpdateVisible(false)}
|
||||||
|
onSuccess={() => {
|
||||||
|
setUpdateVisible(false);
|
||||||
|
setRefresh(!refresh);
|
||||||
|
}}
|
||||||
|
></VideosUpdateDialog>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -40,6 +40,7 @@ const SystemAdministratorPage = () => {
|
|||||||
const [role_ids, setRoleIds] = useState<any>([]);
|
const [role_ids, setRoleIds] = useState<any>([]);
|
||||||
const [selLabel, setLabel] = useState<string>("全部管理员");
|
const [selLabel, setLabel] = useState<string>("全部管理员");
|
||||||
const [roleDelSuccess, setRoleDelSuccess] = useState(false);
|
const [roleDelSuccess, setRoleDelSuccess] = useState(false);
|
||||||
|
const [isSuper, setIsSuper] = useState(false);
|
||||||
|
|
||||||
const [name, setName] = useState<string>("");
|
const [name, setName] = useState<string>("");
|
||||||
|
|
||||||
@ -216,9 +217,10 @@ const SystemAdministratorPage = () => {
|
|||||||
refresh={refresh}
|
refresh={refresh}
|
||||||
type=""
|
type=""
|
||||||
text={"管理员"}
|
text={"管理员"}
|
||||||
onUpdate={(keys: any, title: any) => {
|
onUpdate={(keys: any, title: any, isSuper: boolean) => {
|
||||||
setRoleIds(keys);
|
setRoleIds(keys);
|
||||||
setLabel(title);
|
setLabel(title);
|
||||||
|
setIsSuper(isSuper);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -248,7 +250,7 @@ const SystemAdministratorPage = () => {
|
|||||||
disabled={null}
|
disabled={null}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{role_ids.length > 0 && (
|
{!isSuper && role_ids.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<PerButton
|
<PerButton
|
||||||
text="角色权限"
|
text="角色权限"
|
||||||
|
@ -72,11 +72,6 @@ export const SystemAdminrolesCreate: React.FC<PropInterface> = ({
|
|||||||
value: "线上课-n",
|
value: "线上课-n",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "资源",
|
|
||||||
value: "资源-n",
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "资源分类",
|
title: "资源分类",
|
||||||
value: "资源分类-n",
|
value: "资源分类-n",
|
||||||
@ -87,6 +82,11 @@ export const SystemAdminrolesCreate: React.FC<PropInterface> = ({
|
|||||||
value: "部门-n",
|
value: "部门-n",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "系统配置",
|
||||||
|
value: "系统配置-n",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "其它",
|
title: "其它",
|
||||||
value: "其它-n",
|
value: "其它-n",
|
||||||
|
@ -75,11 +75,6 @@ export const SystemAdminrolesUpdate: React.FC<PropInterface> = ({
|
|||||||
value: "线上课-n",
|
value: "线上课-n",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "资源",
|
|
||||||
value: "资源-n",
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "资源分类",
|
title: "资源分类",
|
||||||
value: "资源分类-n",
|
value: "资源分类-n",
|
||||||
@ -90,6 +85,11 @@ export const SystemAdminrolesUpdate: React.FC<PropInterface> = ({
|
|||||||
value: "部门-n",
|
value: "部门-n",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "系统配置",
|
||||||
|
value: "系统配置-n",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "其它",
|
title: "其它",
|
||||||
value: "其它-n",
|
value: "其它-n",
|
||||||
|
@ -52,6 +52,10 @@ const SystemConfigPage = () => {
|
|||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
"system.api_url": configData[i].key_value,
|
"system.api_url": configData[i].key_value,
|
||||||
});
|
});
|
||||||
|
} else if (configData[i].key_name === "system.api_url") {
|
||||||
|
form.setFieldsValue({
|
||||||
|
"system.api_url": configData[i].key_value,
|
||||||
|
});
|
||||||
} else if (configData[i].key_name === "system.pc_url") {
|
} else if (configData[i].key_name === "system.pc_url") {
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
"system.pc_url": configData[i].key_value,
|
"system.pc_url": configData[i].key_value,
|
||||||
@ -275,6 +279,13 @@ const SystemConfigPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
|
<Form.Item
|
||||||
|
style={{ marginBottom: 30 }}
|
||||||
|
label="API访问地址"
|
||||||
|
name="system.api_url"
|
||||||
|
>
|
||||||
|
<Input style={{ width: 274 }} placeholder="请填写API访问地址" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
style={{ marginBottom: 30 }}
|
style={{ marginBottom: 30 }}
|
||||||
label="网站标题"
|
label="网站标题"
|
||||||
@ -297,13 +308,7 @@ const SystemConfigPage = () => {
|
|||||||
placeholder="请填写网站页脚"
|
placeholder="请填写网站页脚"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{/* <Form.Item
|
{/*
|
||||||
style={{ marginBottom: 30 }}
|
|
||||||
label="API访问地址"
|
|
||||||
name="system.api_url"
|
|
||||||
>
|
|
||||||
<Input style={{ width: 274 }} placeholder="请填写API访问地址" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
style={{ marginBottom: 30 }}
|
style={{ marginBottom: 30 }}
|
||||||
label="PC端访问地址"
|
label="PC端访问地址"
|
||||||
@ -373,6 +378,14 @@ const SystemConfigPage = () => {
|
|||||||
style={{ width: 274 }}
|
style={{ width: 274 }}
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="自定义跑马灯内容"
|
placeholder="自定义跑马灯内容"
|
||||||
|
onChange={(e) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
if (!value && e.type !== "change") {
|
||||||
|
setNameChecked(false);
|
||||||
|
setEmailChecked(false);
|
||||||
|
setIdCardChecked(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
@ -124,3 +124,12 @@ export function ValidataCredentials(value: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function checkUrl(value: any) {
|
||||||
|
let url = value;
|
||||||
|
let str = url.substr(url.length - 1, 1);
|
||||||
|
if (str !== "/") {
|
||||||
|
url = url + "/";
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user