diff --git a/public/favicon.ico b/public/favicon.ico index a11777c..37da455 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/api/course.ts b/src/api/course.ts index 503f89a..595a360 100644 --- a/src/api/course.ts +++ b/src/api/course.ts @@ -36,7 +36,7 @@ export function storeCourse( return client.post("/backend/v1/course/create", { title: title, thumb: thumb, - isShow: isShow, + is_show: isShow, dep_ids: depIds, category_ids: categoryIds, }); @@ -54,10 +54,10 @@ export function updateCourse( depIds: number[], categoryIds: number[] ) { - return client.post(`/backend/v1/course/${id}`, { + return client.put(`/backend/v1/course/${id}`, { title: title, thumb: thumb, - isShow: isShow, + is_show: isShow, dep_ids: depIds, category_ids: categoryIds, }); diff --git a/src/assets/logo.png b/src/assets/logo.png index b99676b..6906040 100644 Binary files a/src/assets/logo.png and b/src/assets/logo.png differ diff --git a/src/compenents/left-menu/index.tsx b/src/compenents/left-menu/index.tsx index a983b89..a03493e 100644 --- a/src/compenents/left-menu/index.tsx +++ b/src/compenents/left-menu/index.tsx @@ -21,6 +21,13 @@ function getItem(label: any, key: any, icon: any, children: any, type: any) { } const items = [ getItem("首页概览", "/", , null, null), + getItem( + "课程内容", + "8", + , + [getItem("课程", "/course", null, null, null)], + null + ), getItem( "资源管理", "3", @@ -55,7 +62,7 @@ const items = [ ), ]; -const rootSubmenuKeys = ["3", "4", "5", "6", "7"]; +const rootSubmenuKeys = ["3", "4", "5", "6", "7", "8"]; export const LeftMenu: React.FC = () => { //展开的subMenu diff --git a/src/index.less b/src/index.less index 82a7b3d..a9476be 100644 --- a/src/index.less +++ b/src/index.less @@ -82,6 +82,18 @@ code { color: #ff4d4f; } +.c-yellow { + color: #e1a500; +} + +.c-green { + color: #04c877; +} + +.c-gray { + color: #999999; +} + .c-red { color: #ff4d4f; } @@ -91,6 +103,11 @@ code { height: 100px; } +.form-course-thumb{ + width: 200px; + height: 150px; +} + .playedu-main-body { width: 100%; height: auto; diff --git a/src/pages/course/vod/index.module.less b/src/pages/course/create.module.less similarity index 100% rename from src/pages/course/vod/index.module.less rename to src/pages/course/create.module.less diff --git a/src/pages/course/create.tsx b/src/pages/course/create.tsx new file mode 100644 index 0000000..c350d15 --- /dev/null +++ b/src/pages/course/create.tsx @@ -0,0 +1,192 @@ +import React, { useState, useEffect } from "react"; +import { Row, Col, Form, Input, Cascader, Switch, Button, message } from "antd"; +import styles from "./create.module.less"; +import { course, department } from "../../api/index"; +import { useNavigate } from "react-router-dom"; +import { UploadImageButton, BackBartment } from "../../compenents"; +const { SHOW_CHILD } = Cascader; + +interface Option { + value: string | number; + label: string; + children?: Option[]; +} + +export const CourseCreatePage: React.FC = () => { + const navigate = useNavigate(); + const [form] = Form.useForm(); + const [loading, setLoading] = useState(true); + const [departments, setDepartments] = useState([]); + const [categories, setCategories] = useState([]); + const [thumb, setThumb] = useState(""); + + useEffect(() => { + getParams(); + getCategory(); + }, []); + + const getParams = () => { + department.departmentList().then((res: any) => { + const departments = res.data.departments; + if (JSON.stringify(departments) !== "{}") { + const new_arr: Option[] = checkArr(departments, 0); + setDepartments(new_arr); + } + }); + }; + + const getCategory = () => { + course.createCourse().then((res: any) => { + const categories = res.data.categories; + if (JSON.stringify(categories) !== "{}") { + const new_arr: Option[] = checkArr(categories, 0); + setCategories(new_arr); + } + form.setFieldsValue({ isShow: 1 }); + }); + }; + + const checkArr = (departments: any[], id: number) => { + const arr = []; + for (let i = 0; i < departments[id].length; i++) { + if (!departments[departments[id][i].id]) { + arr.push({ + label: departments[id][i].name, + value: departments[id][i].id, + }); + } else { + const new_arr: Option[] = checkArr(departments, departments[id][i].id); + arr.push({ + label: departments[id][i].name, + value: departments[id][i].id, + children: new_arr, + }); + } + } + return arr; + }; + + const onFinish = (values: any) => { + console.log("Success:", values); + course + .storeCourse( + values.title, + values.thumb, + values.isShow, + values.dep_ids, + values.category_ids + ) + .then((res: any) => { + message.success("保存成功!"); + navigate(-1); + }); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log("Failed:", errorInfo); + }; + const onChange = (checked: boolean) => { + if (checked) { + form.setFieldsValue({ isShow: 1 }); + } else { + form.setFieldsValue({ isShow: 0 }); + } + }; + + return ( + <> + + + + + + + + + + + + + + { + setThumb(url); + form.setFieldsValue({ thumb: url }); + }} + > + + {thumb && ( + + )} + + + + + + + + + + + + + + 保存 + + navigate(-1)} + > + 取消 + + + + + + + > + ); +}; diff --git a/src/pages/course/index.module.less b/src/pages/course/index.module.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/course/index.tsx b/src/pages/course/index.tsx new file mode 100644 index 0000000..0fd14de --- /dev/null +++ b/src/pages/course/index.tsx @@ -0,0 +1,253 @@ +import { useEffect, useState } from "react"; +import { + Button, + Row, + Col, + Popconfirm, + Image, + Table, + Typography, + Input, + message, + Space, +} from "antd"; +import { course } from "../../api"; +import styles from "./index.module.less"; +import { PlusOutlined, ReloadOutlined } from "@ant-design/icons"; +import type { ColumnsType } from "antd/es/table"; +import { dateFormat } from "../../utils/index"; +import { Link, useNavigate } from "react-router-dom"; +import { TreeDepartment, TreeCategory, PerButton } from "../../compenents"; + +interface DataType { + id: React.Key; + title: string; + created_at: string; + thumb: string; + charge: number; + is_show: number; +} + +export const CoursePage = () => { + 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 [loading, setLoading] = useState(true); + const [category_ids, setCategoryIds] = useState([]); + const [title, setTitle] = useState(""); + const [dep_ids, setDepIds] = useState([]); + + const columns: ColumnsType = [ + { + title: "ID", + key: "id", + dataIndex: "id", + }, + { + title: "封面", + dataIndex: "thumb", + render: (thumb: string) => ( + + ), + }, + { + title: "课程标题", + dataIndex: "title", + render: (text: string) => {text}, + }, + { + title: "时间", + dataIndex: "created_at", + render: (text: string) => {dateFormat(text)}, + }, + { + title: "是否显示", + dataIndex: "is_show", + render: (is_show: number) => ( + + {is_show === 1 ? "· 显示" : "· 隐藏"} + + ), + }, + { + title: "操作", + key: "action", + fixed: "right", + width: 100, + render: (_, record: any) => ( + + navigate(`/course/update/${record.id}`)} + /> + removeItem(record.id)} + okText="确定" + cancelText="取消" + > + null} + /> + + + ), + }, + ]; + + // 删除图片 + const removeItem = (id: number) => { + if (id === 0) { + return; + } + course.destroyCourse(id).then(() => { + message.success("删除成功"); + resetList(); + }); + }; + + // 获取视频列表 + const getList = () => { + setLoading(true); + let categoryIds = category_ids.join(","); + let depIds = dep_ids.join(","); + course + .courseList(page, size, "", "", title, depIds, categoryIds) + .then((res: any) => { + setTotal(res.data.total); + setList(res.data.data); + setLoading(false); + }) + .catch((err: any) => { + console.log("错误,", err); + }); + }; + // 重置列表 + const resetList = () => { + setPage(1); + setSize(10); + setList([]); + setRefresh(!refresh); + }; + + // 加载视频列表 + useEffect(() => { + getList(); + }, [category_ids, refresh, page, size]); + + 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); + }; + + return ( + <> + + + + + + 资源分类: + + setCategoryIds(keys)} /> + + + + 部门: + + setDepIds(keys)} /> + + + + + + + + 课程名称: + { + setTitle(e.target.value); + }} + style={{ width: 160 }} + placeholder="请输入课程名称" + /> + + + + 重 置 + + { + setPage(1); + setRefresh(!refresh); + }} + > + 查 询 + + + + + + + + + } + p="course" + onClick={() => null} + /> + + + + } + style={{ color: "#333333" }} + onClick={() => { + setRefresh(!refresh); + }} + > + + + + record.id} + /> + + + + + > + ); +}; diff --git a/src/pages/course/update.module.less b/src/pages/course/update.module.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/course/update.tsx b/src/pages/course/update.tsx new file mode 100644 index 0000000..0e6f5cb --- /dev/null +++ b/src/pages/course/update.tsx @@ -0,0 +1,227 @@ +import React, { useState, useEffect } from "react"; +import { Row, Col, Form, Input, Cascader, Switch, Button, message } from "antd"; +import styles from "./create.module.less"; +import { course, department } from "../../api/index"; +import { useParams, useNavigate } from "react-router-dom"; +import { UploadImageButton, BackBartment } from "../../compenents"; + +interface Option { + value: string | number; + label: string; + children?: Option[]; +} + +export const CourseUpdatePage: React.FC = () => { + const navigate = useNavigate(); + const params = useParams(); + const [form] = Form.useForm(); + const [loading, setLoading] = useState(true); + const [departments, setDepartments] = useState([]); + const [categories, setCategories] = useState([]); + const [thumb, setThumb] = useState(""); + + useEffect(() => { + getParams(); + getCategory(); + }, []); + + useEffect(() => { + getDetail(); + }, [params.cid]); + + const getParams = () => { + department.departmentList().then((res: any) => { + const departments = res.data.departments; + if (JSON.stringify(departments) !== "{}") { + const new_arr: Option[] = checkArr(departments, 0); + setDepartments(new_arr); + } + }); + }; + + const getCategory = () => { + course.createCourse().then((res: any) => { + const categories = res.data.categories; + if (JSON.stringify(categories) !== "{}") { + const new_arr: Option[] = checkArr(categories, 0); + setCategories(new_arr); + } + form.setFieldsValue({ isShow: 1 }); + }); + }; + + const checkArr = (departments: any[], id: number) => { + const arr = []; + for (let i = 0; i < departments[id].length; i++) { + if (!departments[departments[id][i].id]) { + arr.push({ + label: departments[id][i].name, + value: departments[id][i].id, + }); + } else { + const new_arr: Option[] = checkArr(departments, departments[id][i].id); + arr.push({ + label: departments[id][i].name, + value: departments[id][i].id, + children: new_arr, + }); + } + } + return arr; + }; + + const getDetail = () => { + course.course(Number(params.cid)).then((res: any) => { + let data = res.data.course; + // let depIds=res.data.dep_ids; + // for (let i = 0; i < depIds.length; i++) { + // dep_ids.push(depIds[i]); + // } + form.setFieldsValue({ + title: data.title, + thumb: data.thumb, + isShow: data.is_show, + dep_ids: res.data.dep_ids, + category_ids: res.data.category_ids, + }); + setThumb(data.thumb); + }); + }; + + const onFinish = (values: any) => { + console.log("Success:", values); + let id = Number(params.cid); + let dep_ids: any[] = []; + for (let i = 0; i < values.dep_ids.length; i++) { + dep_ids.push(values.dep_ids[i][values.dep_ids[i].length - 1]); + } + let category_ids: any[] = []; + for (let j = 0; j < values.category_ids.length; j++) { + category_ids.push( + values.category_ids[j][values.category_ids[j].length - 1] + ); + } + course + .updateCourse( + id, + values.title, + values.thumb, + values.isShow, + dep_ids, + category_ids + ) + .then((res: any) => { + message.success("保存成功!"); + navigate(-1); + }); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log("Failed:", errorInfo); + }; + + const onChange = (checked: boolean) => { + if (checked) { + form.setFieldsValue({ isShow: 1 }); + } else { + form.setFieldsValue({ isShow: 0 }); + } + }; + + + return ( + <> + + + + + + + + + + + + + + { + setThumb(url); + form.setFieldsValue({ thumb: url }); + }} + > + + {thumb && ( + + )} + + + + + + + + + + + + + + 保存 + + navigate(-1)} + > + 取消 + + + + + + + > + ); +}; diff --git a/src/pages/course/vod/index.tsx b/src/pages/course/vod/index.tsx deleted file mode 100644 index fc70417..0000000 --- a/src/pages/course/vod/index.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React, { useEffect } from "react"; -import { Typography, Input, Select, Button, Space, Table } from "antd"; -import type { ColumnsType } from "antd/es/table"; -import styles from "./index.module.less"; -import { PlusOutlined, ReloadOutlined } from "@ant-design/icons"; -import { login } from "../../../api/index"; - -interface DataType { - key: string; - name: string; - age: number; - address: string; -} - -const columns: ColumnsType = [ - { - title: "Name", - dataIndex: "name", - key: "name", - render: (text) => {text}, - }, - { - title: "Age", - dataIndex: "age", - key: "age", - }, - { - title: "Address", - dataIndex: "address", - key: "address", - }, - { - title: "Action", - key: "action", - render: (_, record) => ( - - Invite {record.name} - Delete - - ), - }, -]; - -const data: DataType[] = [ - { - key: "1", - name: "John Brown", - age: 32, - address: "New York No. 1 Lake Park", - }, - { - key: "2", - name: "Jim Green", - age: 42, - address: "London No. 1 Lake Park", - }, - { - key: "3", - name: "Joe Black", - age: 32, - address: "Sydney No. 1 Lake Park", - }, -]; - -export const VodListPage: React.FC = () => { - useEffect(() => {}, []); - const handleChange = (e: any) => { - console.log(e); - }; - return ( - <> - - - - 课程名称: - - - - 课程分类: - - - - 重 置 - 查 询 - - - - - - - } className="mr-16" type="primary"> - 新建 - - 删除 - - - } - style={{ color: "#333333" }} - > - - - - - - - > - ); -}; diff --git a/src/pages/department/index.tsx b/src/pages/department/index.tsx index 24222a9..930e3f3 100644 --- a/src/pages/department/index.tsx +++ b/src/pages/department/index.tsx @@ -63,7 +63,7 @@ export const DepartmentPage: React.FC = () => { text="详情" class="c-red" icon={null} - p="department-update" + p="department-cud" onClick={() => navigate(`/department/update/${record.id}`)} /> { text="删除" class="c-red" icon={null} - p="department-destroy" + p="department-cud" onClick={() => null} /> @@ -152,7 +152,7 @@ export const DepartmentPage: React.FC = () => { text="新建" class="mr-16" icon={} - p="department-store" + p="department-cud" onClick={() => null} /> diff --git a/src/pages/index.ts b/src/pages/index.ts index 703385e..acabe85 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -3,7 +3,9 @@ export * from "./login"; export * from "./dashboard"; export * from "./error"; export * from "./test"; -export * from "./course/vod"; +export * from "./course/index"; +export * from "./course/create"; +export * from "./course/update"; export * from "./member/index"; export * from "./member/create"; export * from "./member/update"; diff --git a/src/pages/login/index.module.less b/src/pages/login/index.module.less index c56b537..687fa83 100644 --- a/src/pages/login/index.module.less +++ b/src/pages/login/index.module.less @@ -63,3 +63,4 @@ } } } + diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 5fe0fcd..43ca052 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -12,6 +12,7 @@ import { import { useNavigate } from "react-router-dom"; import banner from "../../assets/images/login/banner.png"; import icon from "../../assets/images/login/icon.png"; +import "./login.less"; export const Login: React.FC = () => { const dispatch = useDispatch(); diff --git a/src/pages/login/login.less b/src/pages/login/login.less new file mode 100644 index 0000000..c018443 --- /dev/null +++ b/src/pages/login/login.less @@ -0,0 +1,8 @@ +.ant-btn { + font-size: 18px !important; + font-weight: 600 !important; +} + +.ant-input { + font-size: 18px !important; +} diff --git a/src/pages/member/create.tsx b/src/pages/member/create.tsx index 102c535..5994c3d 100644 --- a/src/pages/member/create.tsx +++ b/src/pages/member/create.tsx @@ -25,8 +25,10 @@ export const MemberCreatePage: React.FC = () => { const getParams = () => { department.departmentList().then((res: any) => { const departments = res.data.departments; - const new_arr: Option[] = checkArr(departments, 0); - setDepartments(new_arr); + if (JSON.stringify(departments) !== "{}") { + const new_arr: Option[] = checkArr(departments, 0); + setDepartments(new_arr); + } }); }; diff --git a/src/pages/member/update.tsx b/src/pages/member/update.tsx index 18a52d7..602c5ea 100644 --- a/src/pages/member/update.tsx +++ b/src/pages/member/update.tsx @@ -29,8 +29,10 @@ export const MemberUpdatePage: React.FC = () => { const getParams = () => { department.departmentList().then((res: any) => { const departments = res.data.departments; - const new_arr: Option[] = checkArr(departments, 0); - setDepartments(new_arr); + if (JSON.stringify(departments) !== "{}") { + const new_arr: Option[] = checkArr(departments, 0); + setDepartments(new_arr); + } }); }; diff --git a/src/pages/resource/resource-category/index.tsx b/src/pages/resource/resource-category/index.tsx index 2df550f..3be3a8e 100644 --- a/src/pages/resource/resource-category/index.tsx +++ b/src/pages/resource/resource-category/index.tsx @@ -63,7 +63,7 @@ export const ResourceCategoryPage: React.FC = () => { text="详情" class="c-red" icon={null} - p="department-update" + p="department-cud" onClick={() => navigate(`/resource-category/update/${record.id}`)} /> { text="删除" class="c-red" icon={null} - p="department-destroy" + p="department-cud" onClick={() => null} /> @@ -156,7 +156,7 @@ export const ResourceCategoryPage: React.FC = () => { text="新建" class="mr-16" icon={} - p="department-store" + p="department-cud" onClick={() => null} /> diff --git a/src/pages/resource/videos/index.tsx b/src/pages/resource/videos/index.tsx index 692f2d3..e6f20bd 100644 --- a/src/pages/resource/videos/index.tsx +++ b/src/pages/resource/videos/index.tsx @@ -23,7 +23,6 @@ interface DataType { id: React.Key; name: string; created_at: string; - duration: string; } export const ResourceVideosPage = () => { diff --git a/src/pages/system/administrator/index.tsx b/src/pages/system/administrator/index.tsx index 6bd6175..970f439 100644 --- a/src/pages/system/administrator/index.tsx +++ b/src/pages/system/administrator/index.tsx @@ -78,7 +78,7 @@ export const SystemAdministratorPage: React.FC = () => { text="详情" class="c-red" icon={null} - p="admin-user-update" + p="admin-user-cud" onClick={() => navigate(`/system/administrator/update/${record.id}`) } @@ -95,7 +95,7 @@ export const SystemAdministratorPage: React.FC = () => { text="删除" class="c-red" icon={null} - p="admin-user-destroy" + p="admin-user-cud" onClick={() => null} /> @@ -190,7 +190,7 @@ export const SystemAdministratorPage: React.FC = () => { text="新建" class="mr-16" icon={} - p="admin-user-store" + p="admin-user-cud" onClick={() => null} /> diff --git a/src/router/routes.tsx b/src/router/routes.tsx index 8e78822..3331d24 100644 --- a/src/router/routes.tsx +++ b/src/router/routes.tsx @@ -4,7 +4,9 @@ import { HomePage, Dashboard, ErrorPage, - VodListPage, + CoursePage, + CourseCreatePage, + CourseUpdatePage, TestPage, MemberPage, MemberCreatePage, @@ -24,7 +26,7 @@ import { ResourceCategoryPage, ResourceCategoryCreatePage, ResourceCategoryUpdatePage, - ResourceVideosPage + ResourceVideosPage, } from "../pages"; const routes: RouteObject[] = [ @@ -61,9 +63,18 @@ const routes: RouteObject[] = [ element: , }, { - path: "/vod", - element: , + path: "/course", + element: , }, + { + path: "/course/create", + element: , + }, + { + path: "/course/update/:cid", + element: , + }, + { path: "/member", element: ,