!14 存储桶改为private
* 后台 使用许可页面 * 优化:移除API访问地址配置 * 后台、pc、h5 删除无用配置 * docker部署优化 * 2.0 networkMode=bridge * changelog * 学员端权限为空报错 * h5 我的页面请求优化 * 缓存查询 * 后台 学员列表报错、线上课-上架时间字段优化 * 后台、pc、h5 使用签名地址 * 学员端接口修改 * 后台、pc 使用签名地址 * 后台 使用签名地址 * 上传接口 * 上传接口 * 系统配置 * 线上课封面 * bucket由public改为private * 资源相关表实体及对象修改 * 统一数据库脚本
@@ -79,7 +79,7 @@ export function updateCourse(
|
||||
category_ids: categoryIds,
|
||||
chapters: chapters,
|
||||
hours: hours,
|
||||
published_at: publishedAt,
|
||||
sort_at: publishedAt,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
BIN
playedu-admin/src/assets/images/commen/fanghu.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
playedu-admin/src/assets/images/commen/icon5.png
Normal file
|
After Width: | Height: | Size: 706 B |
BIN
playedu-admin/src/assets/images/commen/icon6.png
Normal file
|
After Width: | Height: | Size: 716 B |
BIN
playedu-admin/src/assets/thumb/avatar.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
playedu-admin/src/assets/thumb/thumb1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
playedu-admin/src/assets/thumb/thumb2.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
playedu-admin/src/assets/thumb/thumb3.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@@ -36,7 +36,7 @@ export const Footer: React.FC<PropInterface> = ({ type }) => {
|
||||
className="ml-5"
|
||||
style={{ color: "#D7D7D7", fontSize: 12, marginTop: -5 }}
|
||||
>
|
||||
Version 1.7
|
||||
Version 2.0
|
||||
</span>
|
||||
</Link>
|
||||
</Layout.Footer>
|
||||
|
||||
@@ -96,6 +96,14 @@ const items = [
|
||||
null,
|
||||
null
|
||||
),
|
||||
getItem(
|
||||
"使用许可",
|
||||
"/licensing",
|
||||
<i className="iconfont icon-xuke" />,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
];
|
||||
|
||||
export const LeftMenu: React.FC = () => {
|
||||
|
||||
@@ -37,7 +37,7 @@ interface ImageItem {
|
||||
|
||||
interface PropsInterface {
|
||||
text: any;
|
||||
onSelected: (url: string) => void;
|
||||
onSelected: (url: string, id: number) => void;
|
||||
}
|
||||
|
||||
export const UploadImageButton = (props: PropsInterface) => {
|
||||
@@ -50,6 +50,8 @@ export const UploadImageButton = (props: PropsInterface) => {
|
||||
const [size, setSize] = useState(15);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [selected, setSelected] = useState<string>("");
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [selectedKey, setSelectedKey] = useState<number>(0);
|
||||
|
||||
// 获取图片列表
|
||||
const getImageList = () => {
|
||||
@@ -59,6 +61,7 @@ export const UploadImageButton = (props: PropsInterface) => {
|
||||
.then((res: any) => {
|
||||
setTotal(res.data.result.total);
|
||||
setImageList(res.data.result.data);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("错误,", err);
|
||||
@@ -103,7 +106,7 @@ export const UploadImageButton = (props: PropsInterface) => {
|
||||
message.error("请选择图片后确定");
|
||||
return;
|
||||
}
|
||||
props.onSelected(selected);
|
||||
props.onSelected(selected, selectedKey);
|
||||
setShowModal(false);
|
||||
}}
|
||||
>
|
||||
@@ -140,17 +143,19 @@ export const UploadImageButton = (props: PropsInterface) => {
|
||||
<div
|
||||
key={item.id}
|
||||
className="image-item"
|
||||
style={{ backgroundImage: `url(${item.url})` }}
|
||||
style={{ backgroundImage: `url(${resourceUrl[item.id]})` }}
|
||||
onClick={() => {
|
||||
setSelected(item.url);
|
||||
setSelected(resourceUrl[item.id]);
|
||||
setSelectedKey(item.id);
|
||||
}}
|
||||
>
|
||||
{selected.indexOf(item.url) !== -1 && (
|
||||
{selected.indexOf(resourceUrl[item.id]) !== -1 && (
|
||||
<i
|
||||
className={styles.checked}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelected("");
|
||||
setSelectedKey(0);
|
||||
}}
|
||||
>
|
||||
<CheckOutlined />
|
||||
|
||||
@@ -79,6 +79,10 @@ code {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mt-16 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.ml-15 {
|
||||
margin-left: 15px;
|
||||
}
|
||||
@@ -123,6 +127,10 @@ code {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.mt-30 {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.mb-28 {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
@@ -729,3 +737,7 @@ textarea.ant-input {
|
||||
.clickable-stat:hover .ant-statistic-content {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.ant-tree .ant-tree-switcher:before {
|
||||
height: 40px;
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
Tag,
|
||||
} from "antd";
|
||||
import styles from "./create.module.less";
|
||||
import { useSelector } from "react-redux";
|
||||
import { course, department } from "../../../api/index";
|
||||
import {
|
||||
UploadImageButton,
|
||||
@@ -25,6 +24,9 @@ import {
|
||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
||||
import { TreeHours } from "./hours";
|
||||
import { TreeAttachments } from "./attachments";
|
||||
import defaultThumb1 from "../../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../../assets/thumb/thumb3.png";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@@ -46,12 +48,6 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
onCancel,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
const courseDefaultThumbs = useSelector(
|
||||
(state: any) => state.systemConfig.value.courseDefaultThumbs
|
||||
);
|
||||
const defaultThumb1 = courseDefaultThumbs[0];
|
||||
const defaultThumb2 = courseDefaultThumbs[1];
|
||||
const defaultThumb3 = courseDefaultThumbs[2];
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [init, setInit] = useState(true);
|
||||
const [departments, setDepartments] = useState<Option[]>([]);
|
||||
@@ -85,7 +81,7 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({
|
||||
title: "",
|
||||
thumb: defaultThumb1,
|
||||
thumb: -1,
|
||||
isRequired: 1,
|
||||
short_desc: "",
|
||||
hasChapter: 0,
|
||||
@@ -688,7 +684,7 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb1);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb1,
|
||||
thumb: -1,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -709,7 +705,7 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb2);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb2,
|
||||
thumb: -2,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -730,7 +726,7 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb3);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb3,
|
||||
thumb: -3,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -746,9 +742,9 @@ export const CourseCreate: React.FC<PropInterface> = ({
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换封面"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setThumb(url);
|
||||
form.setFieldsValue({ thumb: url });
|
||||
form.setFieldsValue({ thumb: id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<span className="helper-text ml-8">
|
||||
|
||||
@@ -14,9 +14,11 @@ import {
|
||||
Tag,
|
||||
} from "antd";
|
||||
import styles from "./update.module.less";
|
||||
import { useSelector } from "react-redux";
|
||||
import { course, department } from "../../../api/index";
|
||||
import { UploadImageButton, SelectRange } from "../../../compenents";
|
||||
import defaultThumb1 from "../../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../../assets/thumb/thumb3.png";
|
||||
import dayjs from "dayjs";
|
||||
import moment from "moment";
|
||||
|
||||
@@ -39,15 +41,10 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
const [init, setInit] = useState(true);
|
||||
const courseDefaultThumbs = useSelector(
|
||||
(state: any) => state.systemConfig.value.courseDefaultThumbs
|
||||
);
|
||||
const defaultThumb1 = courseDefaultThumbs[0];
|
||||
const defaultThumb2 = courseDefaultThumbs[1];
|
||||
const defaultThumb3 = courseDefaultThumbs[2];
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [departments, setDepartments] = useState<Option[]>([]);
|
||||
const [categories, setCategories] = useState<Option[]>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [thumb, setThumb] = useState("");
|
||||
const [depIds, setDepIds] = useState<number[]>([]);
|
||||
const [deps, setDeps] = useState<any[]>([]);
|
||||
@@ -98,8 +95,8 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
short_desc: res.data.course.short_desc,
|
||||
hasChapter: chapterType,
|
||||
type: type,
|
||||
published_at: res.data.course.published_at
|
||||
? dayjs(res.data.course.published_at)
|
||||
published_at: res.data.course.sort_at
|
||||
? dayjs(res.data.course.sort_at)
|
||||
: "",
|
||||
});
|
||||
setType(type);
|
||||
@@ -111,6 +108,16 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
if (deps && JSON.stringify(deps) !== "{}") {
|
||||
form.setFieldsValue({ ids: [1, 2] });
|
||||
}
|
||||
setResourceUrl(res.data.resource_url);
|
||||
setThumb(
|
||||
res.data.course.thumb === -1
|
||||
? defaultThumb1
|
||||
: res.data.course.thumb === -2
|
||||
? defaultThumb2
|
||||
: res.data.course.thumb === -3
|
||||
? defaultThumb3
|
||||
: res.data.resource_url[res.data.course.thumb]
|
||||
);
|
||||
setInit(false);
|
||||
});
|
||||
};
|
||||
@@ -412,7 +419,7 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb1);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb1,
|
||||
thumb: -1,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -433,7 +440,7 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb2);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb2,
|
||||
thumb: -2,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -454,7 +461,7 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
onClick={() => {
|
||||
setThumb(defaultThumb3);
|
||||
form.setFieldsValue({
|
||||
thumb: defaultThumb3,
|
||||
thumb: -3,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -470,9 +477,9 @@ export const CourseUpdate: React.FC<PropInterface> = ({
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换封面"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setThumb(url);
|
||||
form.setFieldsValue({ thumb: url });
|
||||
form.setFieldsValue({ thumb: id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<span className="helper-text ml-8">
|
||||
|
||||
@@ -27,6 +27,9 @@ import { CourseCreate } from "./compenents/create";
|
||||
import { CourseUpdate } from "./compenents/update";
|
||||
import { CourseHourUpdate } from "./compenents/hour-update";
|
||||
import { CourseAttachmentUpdate } from "./compenents/attachment-update";
|
||||
import defaultThumb1 from "../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../assets/thumb/thumb3.png";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@@ -77,6 +80,7 @@ const CoursePage = () => {
|
||||
useState<CategoryIdsModel>({});
|
||||
const [course_dep_ids, setCourseDepIds] = useState<DepIdsModel>({});
|
||||
const [categories, setCategories] = useState<CategoriesModel>({});
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [departments, setDepartments] = useState<DepartmentsModel>({});
|
||||
const [tabKey, setTabKey] = useState(result.get("did") ? "2" : "1");
|
||||
const [adminUsers, setAdminUsers] = useState<any>({});
|
||||
@@ -166,7 +170,15 @@ const CoursePage = () => {
|
||||
width={80}
|
||||
height={60}
|
||||
style={{ borderRadius: 6 }}
|
||||
src={record.thumb}
|
||||
src={
|
||||
record.thumb === -1
|
||||
? defaultThumb1
|
||||
: record.thumb === -2
|
||||
? defaultThumb2
|
||||
: record.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[record.thumb]
|
||||
}
|
||||
></Image>
|
||||
<span className="ml-8">{record.title}</span>
|
||||
</div>
|
||||
@@ -227,7 +239,7 @@ const CoursePage = () => {
|
||||
},
|
||||
{
|
||||
title: "上架时间",
|
||||
dataIndex: "published_at",
|
||||
dataIndex: "sort_at",
|
||||
render: (text: string) => <span>{dateFormat(text)}</span>,
|
||||
},
|
||||
{
|
||||
@@ -381,6 +393,7 @@ const CoursePage = () => {
|
||||
setCategories(res.data.categories);
|
||||
setDepartments(res.data.departments);
|
||||
setAdminUsers(res.data.admin_users);
|
||||
setResourceUrl(res.data.resource_url)
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { BackBartment } from "../../compenents";
|
||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
||||
import { PerButton } from "../../compenents";
|
||||
import { dateFormat } from "../../utils/index";
|
||||
import memberDefaultAvatar from "../../assets/thumb/avatar.png";
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@@ -95,6 +96,7 @@ const CourseUserPage = () => {
|
||||
const [email, setEmail] = useState("");
|
||||
const [idCard, setIdCard] = useState("");
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [title, setTitle] = useState<string>(String(result.get("title")));
|
||||
|
||||
const columns: ColumnsType<DataType> = [
|
||||
@@ -107,7 +109,11 @@ const CourseUserPage = () => {
|
||||
preview={false}
|
||||
width={40}
|
||||
height={40}
|
||||
src={record.avatar}
|
||||
src={
|
||||
record.avatar == -1
|
||||
? memberDefaultAvatar
|
||||
: resourceUrl[record.avatar]
|
||||
}
|
||||
></Image>
|
||||
<span className="ml-8">{record.name}</span>
|
||||
</div>
|
||||
@@ -231,6 +237,7 @@ const CourseUserPage = () => {
|
||||
setHourCount(res.data.user_course_hour_user_first_at);
|
||||
setRecords(res.data.user_course_records);
|
||||
setPerRecords(res.data.per_user_earliest_records);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
setCourse(res.data.course);
|
||||
setDepartments(res.data.departments);
|
||||
setUserDepIds(res.data.user_dep_ids);
|
||||
|
||||
@@ -23,9 +23,9 @@ const InitPage = (props: Props) => {
|
||||
"ldap-enabled": props.configData["ldap-enabled"],
|
||||
systemName: props.configData["system.name"],
|
||||
systemLogo: props.configData["system.logo"],
|
||||
systemApiUrl: props.configData["system.api_url"],
|
||||
systemPcUrl: props.configData["system.pc_url"],
|
||||
systemH5Url: props.configData["system.h5_url"],
|
||||
resourceUrl: props.configData["resource_url"],
|
||||
memberDefaultAvatar: props.configData["member.default_avatar"],
|
||||
courseDefaultThumbs: props.configData["default.course_thumbs"],
|
||||
departments: props.configData["departments"],
|
||||
|
||||
194
playedu-admin/src/pages/licensing/index.module.less
Normal file
@@ -0,0 +1,194 @@
|
||||
.main-title {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
float: left;
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
color: #333333;
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.persion {
|
||||
width: 158px;
|
||||
height: 32px;
|
||||
background: rgba(255, 77, 79, 0.1);
|
||||
border-radius: 6px 6px 6px 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
float: left;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contrast-box1 {
|
||||
width: 100%;
|
||||
height: 85px;
|
||||
float: left;
|
||||
background: #fafafa;
|
||||
border-radius: 16px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
/* Firefox */
|
||||
-webkit-box-sizing: border-box;
|
||||
/* Safari */
|
||||
padding: 15px 100px 15px 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.name {
|
||||
flex: 1;
|
||||
height: 25px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
line-height: 25px;
|
||||
}
|
||||
.ex {
|
||||
width: 114px;
|
||||
height: 55px;
|
||||
background: #ff4d4f;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
line-height: 25px;
|
||||
margin-right: 307px;
|
||||
}
|
||||
.ex2 {
|
||||
width: 114px;
|
||||
height: 55px;
|
||||
background: #f1aa2e;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
line-height: 25px;
|
||||
margin-right: 47px;
|
||||
}
|
||||
}
|
||||
|
||||
.contrast-box2 {
|
||||
width: 100%;
|
||||
float: left;
|
||||
height: 65px;
|
||||
background: rgba(#f1aa2e, 0.1);
|
||||
border-radius: 16px 16px 0px 0px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
/* Firefox */
|
||||
-webkit-box-sizing: border-box;
|
||||
/* Safari */
|
||||
padding: 20px 100px 20px 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.name {
|
||||
flex: 1;
|
||||
height: 25px;
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
line-height: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.contrast-box3 {
|
||||
width: 100%;
|
||||
height: 85px;
|
||||
float: left;
|
||||
height: 76px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
/* Firefox */
|
||||
-webkit-box-sizing: border-box;
|
||||
/* Safari */
|
||||
padding: 30px 100px 30px 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-top: none;
|
||||
position: relative;
|
||||
.name {
|
||||
flex: 1;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
strong {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #f1aa2e;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
span {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
line-height: 16px;
|
||||
}
|
||||
.sp {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
.ex {
|
||||
width: 209px;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #ff4d4f;
|
||||
line-height: 16px;
|
||||
margin-right: 209px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.pic {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
.ex2 {
|
||||
width: 209px;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #ff9900;
|
||||
line-height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.pic {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
826
playedu-admin/src/pages/licensing/index.tsx
Normal file
@@ -0,0 +1,826 @@
|
||||
import styles from "./index.module.less";
|
||||
import { Button, Tooltip } from "antd";
|
||||
import fangIcon from "../../assets/images/commen/fanghu.png";
|
||||
import ex1Icon from "../../assets/images/commen/icon5.png";
|
||||
import ex2Icon from "../../assets/images/commen/icon6.png";
|
||||
|
||||
const LicensingPage = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="playedu-main-top">
|
||||
<div className={styles["main-title"]}>当前版本信息</div>
|
||||
<div className="float-left mt-24">
|
||||
<div className={styles["persion"]}>PlayEdu开源版 v2.0</div>
|
||||
</div>
|
||||
<div className="float-left mt-16">
|
||||
<div className={styles["content"]}>
|
||||
1.版权归属:PlayEdu开源版版权归杭州白书科技有限公司所有,保留全部使用权。
|
||||
</div>
|
||||
<div className={styles["content"]}>
|
||||
2.代码修改:允许在遵守开源协议的前提下修改代码,但需在修改处添加明确备注,详细说明修改内容。
|
||||
</div>
|
||||
<div className={styles["content"]}>
|
||||
3.版权保护:任何场景下均需保留
|
||||
PlayEdu开源版页面及代码中的原有版权信息(如 “Designed By PlayEdu”
|
||||
标识、官网链接、开源说明等),严禁删除、修改或篡改,违者需承担法律责任及赔偿。
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-24">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
window.open("https://www.playeduos.com/");
|
||||
}}
|
||||
>
|
||||
采购企业版本
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="playedu-main-top mt-24" style={{ position: "relative" }}>
|
||||
<div className={styles["main-title"]}>版本功能对比</div>
|
||||
<div className="float-left mt-24">
|
||||
<div className={styles["contrast-box1"]}>
|
||||
<div className={styles["name"]}>功能特性</div>
|
||||
<div className={styles["ex"]}>开源版</div>
|
||||
<div className={styles["ex2"]}>企业版</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>系统支持</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>功能支持</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>基础功能</div>
|
||||
<div className={styles["ex2"]}>全部功能</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>技术支持</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>无</div>
|
||||
<Tooltip
|
||||
className={styles["ex2"]}
|
||||
title="专属售后群以及远程排障服务"
|
||||
>
|
||||
<img src={fangIcon} className={styles["icon"]} />
|
||||
7*10h专业技术服务
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>安全认证</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>无</div>
|
||||
<div className={styles["ex2"]}>CMA国家资质安全认证</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>部署服务</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>无</div>
|
||||
<div className={styles["ex2"]}>内外网单机及集群部署</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>性能负载</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>低</div>
|
||||
<div className={styles["ex2"]}>企业级全链路高性能场景</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>资源类型</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>视频库</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>MP4(H264)</div>
|
||||
<div className={styles["ex2"]}>MP4|MOV|AVI|WMV|FLV</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>图片库</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>附件库</span>
|
||||
<span className={styles["sp"]}>(仅支持上传下载)</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>文档库</span>
|
||||
<span className={styles["sp"]}>
|
||||
(支持Word、PPT、PDF在线预览)
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>音频库</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>证书库</span>
|
||||
<span className={styles["sp"]}>(支持自定义证书设计)</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>讲师资料</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>考试中心</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>试题库</span>
|
||||
<span className={styles["sp"]}>
|
||||
(支持六大题型,支持批量导入)
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>试卷库</span>
|
||||
<span className={styles["sp"]}>(支持手动组卷,随机组卷)</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>考试中心</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>线上课</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>线下课</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学习任务</span>
|
||||
<span className={styles["sp"]}>
|
||||
(支持指派部门以及独立学员、支持多阶段学习、支持闯关模式、支持关联证书奖励)
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>考试任务</span>
|
||||
<span className={styles["sp"]}>
|
||||
(支持指派部门以及独立学员、支持试题/选项乱序、支持补考、支持关联证书奖励)
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>指派方式</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>部门</div>
|
||||
<div className={styles["ex2"]}>部门|学员|用户组</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>积分激励</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>积分规则</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>积分调整</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>积分排行</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>数据统计</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>数据概览</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学习排行</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>资源统计</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学员信息导出</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>课程学习导出</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学员学习导出</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>部门学习导出</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学习任务统计</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>考试任务统计</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>考生答卷导出</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>防作弊</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>防拖拽</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>防挂机</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>防切屏</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>系统配置</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>网站设置</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>播放设置</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>学员设置</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>单点登录</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>LDAP</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>企业微信</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>钉钉</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>飞书</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>云之家(金蝶)</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>CAS</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>泛微</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>免费支持</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>用友</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>免费支持</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>存储方案</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>MinIO(私有化)</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>阿里云oss</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>腾讯云cos</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>安全保护</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>视频跑马灯</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>HLS视频加密</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>视频防嗅探下载</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>文档水印</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>考试水印</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>试题防复制</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>多终端</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>PC独立网站</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>移动端H5</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>
|
||||
<img src={ex1Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>版权信息</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>代码协议文件</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>不可移除</div>
|
||||
<div className={styles["ex2"]}>企业授权</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>页脚版权链接</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}>不可移除</div>
|
||||
<div className={styles["ex2"]}>企业授权</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="float-left mt-30">
|
||||
<div className={styles["contrast-box2"]}>
|
||||
<div className={styles["name"]}>售后服务</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>安装部署</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>使用手册</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["contrast-box3"]}>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>系统升级</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["contrast-box3"]}
|
||||
style={{ borderRadius: "0px 0px 16px 16px" }}
|
||||
>
|
||||
<div className={styles["name"]}>
|
||||
<strong></strong>
|
||||
<span>专属服务群</span>
|
||||
</div>
|
||||
<div className={styles["ex"]}></div>
|
||||
<div className={styles["ex2"]}>
|
||||
<img src={ex2Icon} className={styles["pic"]} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LicensingPage;
|
||||
@@ -63,9 +63,9 @@ const LoginPage = () => {
|
||||
"ldap-enabled": res.data["ldap-enabled"],
|
||||
systemName: res.data["system.name"],
|
||||
systemLogo: res.data["system.logo"],
|
||||
systemApiUrl: res.data["system.api_url"],
|
||||
systemPcUrl: res.data["system.pc_url"],
|
||||
systemH5Url: res.data["system.h5_url"],
|
||||
resourceUrl: res.data["resource_url"],
|
||||
memberDefaultAvatar: res.data["member.default_avatar"],
|
||||
courseDefaultThumbs: res.data["default.course_thumbs"],
|
||||
departments: res.data["departments"],
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useSelector } from "react-redux";
|
||||
import { user, department } from "../../../api/index";
|
||||
import { UploadImageButton } from "../../../compenents";
|
||||
import { ValidataCredentials } from "../../../utils/index";
|
||||
import memberDefaultAvatar from "../../../assets/thumb/avatar.png";
|
||||
|
||||
interface PropInterface {
|
||||
open: boolean;
|
||||
@@ -27,9 +28,12 @@ export const MemberCreate: React.FC<PropInterface> = ({
|
||||
const [init, setInit] = useState(true);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [departments, setDepartments] = useState<any>([]);
|
||||
const memberDefaultAvatar = useSelector(
|
||||
const systemMemberDefaultAvatar = useSelector(
|
||||
(state: any) => state.systemConfig.value.memberDefaultAvatar
|
||||
);
|
||||
const systemResourceUrl = useSelector(
|
||||
(state: any) => state.systemConfig.value.resourceUrl
|
||||
);
|
||||
const [avatar, setAvatar] = useState<string>(memberDefaultAvatar);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -44,11 +48,20 @@ export const MemberCreate: React.FC<PropInterface> = ({
|
||||
email: "",
|
||||
name: "",
|
||||
password: "",
|
||||
avatar: memberDefaultAvatar,
|
||||
avatar: systemMemberDefaultAvatar
|
||||
? Number(systemMemberDefaultAvatar)
|
||||
: -1,
|
||||
idCard: "",
|
||||
dep_ids: depIds,
|
||||
|
||||
});
|
||||
setAvatar(memberDefaultAvatar);
|
||||
if (systemMemberDefaultAvatar === -1) {
|
||||
setAvatar(memberDefaultAvatar);
|
||||
} else if (systemMemberDefaultAvatar >= 0) {
|
||||
setAvatar(systemResourceUrl[Number(systemMemberDefaultAvatar)]);
|
||||
} else {
|
||||
setAvatar(memberDefaultAvatar);
|
||||
}
|
||||
}, [form, open, depIds]);
|
||||
|
||||
const getParams = () => {
|
||||
@@ -160,9 +173,9 @@ export const MemberCreate: React.FC<PropInterface> = ({
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换头像"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setAvatar(url);
|
||||
form.setFieldsValue({ avatar: url });
|
||||
form.setFieldsValue({ avatar: id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Modal, Form, TreeSelect, Input, message, Spin } from "antd";
|
||||
import styles from "./update.module.less";
|
||||
import { useSelector } from "react-redux";
|
||||
import { user, department } from "../../../api/index";
|
||||
import { UploadImageButton } from "../../../compenents";
|
||||
import { ValidataCredentials } from "../../../utils/index";
|
||||
import memberDefaultAvatar from "../../../assets/thumb/avatar.png";
|
||||
|
||||
interface PropInterface {
|
||||
id: number;
|
||||
@@ -27,9 +27,7 @@ export const MemberUpdate: React.FC<PropInterface> = ({
|
||||
const [init, setInit] = useState(true);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [departments, setDepartments] = useState<any>([]);
|
||||
const memberDefaultAvatar = useSelector(
|
||||
(state: any) => state.systemConfig.value.memberDefaultAvatar
|
||||
);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [avatar, setAvatar] = useState<string>(memberDefaultAvatar);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -62,7 +60,7 @@ export const MemberUpdate: React.FC<PropInterface> = ({
|
||||
const getDetail = () => {
|
||||
user.user(id).then((res: any) => {
|
||||
let user = res.data.user;
|
||||
setAvatar(user.avatar);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
form.setFieldsValue({
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
@@ -70,6 +68,11 @@ export const MemberUpdate: React.FC<PropInterface> = ({
|
||||
idCard: user.id_card,
|
||||
dep_ids: res.data.dep_ids,
|
||||
});
|
||||
if (user.avatar === -1) {
|
||||
setAvatar(memberDefaultAvatar);
|
||||
} else {
|
||||
setAvatar(res.data.resource_url[user.avatar]);
|
||||
}
|
||||
setInit(false);
|
||||
});
|
||||
};
|
||||
@@ -185,9 +188,9 @@ export const MemberUpdate: React.FC<PropInterface> = ({
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换头像"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setAvatar(url);
|
||||
form.setFieldsValue({ avatar: url });
|
||||
form.setFieldsValue({ avatar: id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,7 @@ import { useSelector } from "react-redux";
|
||||
import { TreeDepartment, PerButton } from "../../compenents";
|
||||
import { MemberCreate } from "./compenents/create";
|
||||
import { MemberUpdate } from "./compenents/update";
|
||||
import memberDefaultAvatar from "../../assets/thumb/avatar.png";
|
||||
const { confirm } = Modal;
|
||||
|
||||
interface DataType {
|
||||
@@ -69,6 +70,7 @@ const MemberPage = () => {
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [list, setList] = useState<DataType[]>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [total, setTotal] = useState(0);
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [dep_ids, setDepIds] = useState<number[]>([]);
|
||||
@@ -103,7 +105,11 @@ const MemberPage = () => {
|
||||
<>
|
||||
<Image
|
||||
style={{ borderRadius: "50%" }}
|
||||
src={record.avatar}
|
||||
src={
|
||||
record.avatar == -1
|
||||
? memberDefaultAvatar
|
||||
: resourceUrl[record.avatar]
|
||||
}
|
||||
preview={false}
|
||||
width={40}
|
||||
height={40}
|
||||
@@ -250,6 +256,7 @@ const MemberPage = () => {
|
||||
setList(res.data.data);
|
||||
setDepartments(res.data.departments);
|
||||
setUserDepIds(res.data.user_dep_ids);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
setTotal(res.data.total);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
@@ -8,6 +8,9 @@ import { user as member } from "../../api/index";
|
||||
import * as echarts from "echarts";
|
||||
import type { ColumnsType } from "antd/es/table";
|
||||
import { MemberLearnProgressDialog } from "./compenents/progress";
|
||||
import defaultThumb1 from "../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../assets/thumb/thumb3.png";
|
||||
|
||||
interface DataType {
|
||||
id: React.Key;
|
||||
@@ -87,6 +90,7 @@ const MemberLearnPage = () => {
|
||||
const [records, setRecords] = useState<UserCourseRecordsModel>({});
|
||||
const [perRecords, setPerRecords] = useState<PerCourseRecordsModel>({});
|
||||
const [hourCount, setHourCount] = useState<HourCountModel>({});
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [total2, setTotal2] = useState(0);
|
||||
const [refresh2, setRefresh2] = useState(false);
|
||||
const [uid, setUid] = useState(Number(result.get("id")));
|
||||
@@ -212,6 +216,7 @@ const MemberLearnPage = () => {
|
||||
setHourCount(res.data.user_course_hour_count);
|
||||
setRecords(res.data.user_course_records);
|
||||
setPerRecords(res.data.per_course_earliest_records);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
if (res.data.departments.length > 0) {
|
||||
let box: OptionModel[] = [];
|
||||
res.data.departments.map((item: any) => {
|
||||
@@ -236,13 +241,31 @@ const MemberLearnPage = () => {
|
||||
dataIndex: "title",
|
||||
render: (_, record: any) => (
|
||||
<div className="d-flex">
|
||||
<Image
|
||||
src={record.thumb}
|
||||
preview={false}
|
||||
width={80}
|
||||
height={60}
|
||||
style={{ borderRadius: 6 }}
|
||||
/>
|
||||
{loading2 ? (
|
||||
<Image
|
||||
src={defaultThumb1}
|
||||
preview={false}
|
||||
width={80}
|
||||
height={60}
|
||||
style={{ borderRadius: 6 }}
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
src={
|
||||
record.thumb === -1
|
||||
? defaultThumb1
|
||||
: record.thumb === -2
|
||||
? defaultThumb2
|
||||
: record.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[record.thumb]
|
||||
}
|
||||
preview={false}
|
||||
width={80}
|
||||
height={60}
|
||||
style={{ borderRadius: 6 }}
|
||||
/>
|
||||
)}
|
||||
<span className="ml-8">{record.title}</span>
|
||||
</div>
|
||||
),
|
||||
|
||||
@@ -43,6 +43,7 @@ const ResourceCoursewarePage = () => {
|
||||
const [list, setList] = useState<DataType[]>([]);
|
||||
const [adminUsers, setAdminUsers] = useState<AdminUsersModel>({});
|
||||
const [existingTypes, setExistingTypes] = useState<string[]>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [size, setSize] = useState(10);
|
||||
@@ -94,6 +95,7 @@ const ResourceCoursewarePage = () => {
|
||||
setList(res.data.result.data);
|
||||
setExistingTypes(res.data.existing_types);
|
||||
setAdminUsers(res.data.admin_users);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
@@ -153,7 +155,11 @@ const ResourceCoursewarePage = () => {
|
||||
size="small"
|
||||
className="b-n-link c-red"
|
||||
onClick={() => {
|
||||
downLoadFile(record.url);
|
||||
downLoadFile(
|
||||
resourceUrl[record.id],
|
||||
record.name,
|
||||
record.extension
|
||||
);
|
||||
}}
|
||||
>
|
||||
下载
|
||||
@@ -262,9 +268,17 @@ const ResourceCoursewarePage = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const downLoadFile = (url: string) => {
|
||||
console.log(url);
|
||||
const downLoadFile = (url: string, name: string, extension: string) => {
|
||||
window.open(url);
|
||||
const a = document.createElement("a");
|
||||
a.style.display = "none";
|
||||
a.href = url;
|
||||
a.download = `${name}.${extension}`; // 设置下载的文件名
|
||||
document.body.appendChild(a);
|
||||
a.click(); // 触发点击事件
|
||||
// 释放 URL 对象
|
||||
URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,6 +35,7 @@ interface ImageItem {
|
||||
const ResourceImagesPage = () => {
|
||||
const result = new URLSearchParams(useLocation().search);
|
||||
const [imageList, setImageList] = useState<ImageItem[]>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [size, setSize] = useState(32);
|
||||
@@ -96,6 +97,7 @@ const ResourceImagesPage = () => {
|
||||
.then((res: any) => {
|
||||
setTotal(res.data.result.total);
|
||||
setImageList(res.data.result.data);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
let data: ImageItem[] = res.data.result.data;
|
||||
let arr = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
@@ -232,7 +234,7 @@ const ResourceImagesPage = () => {
|
||||
<div
|
||||
key={item.id}
|
||||
className={`${styles.imageItem} ref-image-item`}
|
||||
style={{ backgroundImage: `url(${item.url})` }}
|
||||
style={{ backgroundImage: `url(${resourceUrl[item.id]})` }}
|
||||
onClick={() => showImage(index, true)}
|
||||
onMouseOver={() => showHover(index, true)}
|
||||
onMouseOut={() => showHover(index, false)}
|
||||
@@ -254,10 +256,10 @@ const ResourceImagesPage = () => {
|
||||
<Image
|
||||
width={200}
|
||||
style={{ display: "none" }}
|
||||
src={item.url}
|
||||
src={resourceUrl[item.id]}
|
||||
preview={{
|
||||
visible: visibleArr[index],
|
||||
src: item.url,
|
||||
src: resourceUrl[item.id],
|
||||
onVisibleChange: (value) => {
|
||||
showImage(index, value);
|
||||
},
|
||||
|
||||
@@ -56,6 +56,7 @@ const ResourceVideosPage = () => {
|
||||
const [videoList, setVideoList] = useState<DataType[]>([]);
|
||||
const [videosExtra, setVideoExtra] = useState<VideosExtraModel>({});
|
||||
const [adminUsers, setAdminUsers] = useState<AdminUsersModel>({});
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [size, setSize] = useState(10);
|
||||
@@ -164,7 +165,7 @@ const ResourceVideosPage = () => {
|
||||
className="b-n-link c-red"
|
||||
onClick={() => {
|
||||
setUpdateId(record.id);
|
||||
setPlayUrl(record.url);
|
||||
setPlayUrl(resourceUrl[record.id]);
|
||||
setPlayeVisible(true);
|
||||
}}
|
||||
>
|
||||
@@ -247,6 +248,7 @@ const ResourceVideosPage = () => {
|
||||
setVideoList(res.data.result.data);
|
||||
setVideoExtra(res.data.videos_extra);
|
||||
setAdminUsers(res.data.admin_users);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
} from "antd";
|
||||
import { appConfig, system } from "../../../api/index";
|
||||
import { UploadImageButton } from "../../../compenents";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useDispatch } from "react-redux";
|
||||
import type { TabsProps } from "antd";
|
||||
import type { CheckboxChangeEvent } from "antd/es/checkbox";
|
||||
import {
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
saveConfigAction,
|
||||
} from "../../../store/system/systemConfigSlice";
|
||||
import logoIcon from "../../../assets/logo.png";
|
||||
import memberDefaultAvatar from "../../../assets/thumb/avatar.png";
|
||||
|
||||
const SystemConfigPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -32,13 +33,10 @@ const SystemConfigPage = () => {
|
||||
const [thumb, setThumb] = useState("");
|
||||
const [avatar, setAvatar] = useState("");
|
||||
const [tabKey, setTabKey] = useState(1);
|
||||
const [s3Service, setS3Service] = useState("");
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const [nameChecked, setNameChecked] = useState(false);
|
||||
const [emailChecked, setEmailChecked] = useState(false);
|
||||
const [idCardchecked, setIdCardChecked] = useState(false);
|
||||
const memberDefaultAvatar = useSelector(
|
||||
(state: any) => state.systemConfig.value.memberDefaultAvatar
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getDetail();
|
||||
@@ -46,7 +44,8 @@ const SystemConfigPage = () => {
|
||||
|
||||
const getDetail = () => {
|
||||
appConfig.appConfig().then((res: any) => {
|
||||
let configData = res.data;
|
||||
setResourceUrl(res.data.resource_url);
|
||||
let configData = res.data.app_config;
|
||||
for (let i = 0; i < configData.length; i++) {
|
||||
if (configData[i].key_name === "system.name") {
|
||||
form.setFieldsValue({
|
||||
@@ -56,19 +55,12 @@ const SystemConfigPage = () => {
|
||||
form.setFieldsValue({
|
||||
"system.logo": configData[i].key_value,
|
||||
});
|
||||
console.log(configData[i].key_value);
|
||||
if (configData[i].key_value !== "") {
|
||||
setLogo(configData[i].key_value);
|
||||
setLogo(res.data.resource_url[Number(configData[i].key_value)]);
|
||||
} else {
|
||||
setLogo(logoIcon);
|
||||
}
|
||||
} 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.api_url") {
|
||||
form.setFieldsValue({
|
||||
"system.api_url": configData[i].key_value,
|
||||
});
|
||||
} else if (configData[i].key_name === "system.pc_url") {
|
||||
form.setFieldsValue({
|
||||
"system.pc_url": configData[i].key_value,
|
||||
@@ -78,7 +70,9 @@ const SystemConfigPage = () => {
|
||||
"system.h5_url": configData[i].key_value,
|
||||
});
|
||||
} else if (configData[i].key_name === "player.poster") {
|
||||
setThumb(configData[i].key_value);
|
||||
if (configData[i].key_value !== "") {
|
||||
setThumb(res.data.resource_url[Number(configData[i].key_value)]);
|
||||
}
|
||||
form.setFieldsValue({
|
||||
"player.poster": configData[i].key_value,
|
||||
});
|
||||
@@ -131,18 +125,13 @@ const SystemConfigPage = () => {
|
||||
});
|
||||
} else if (configData[i].key_name === "member.default_avatar") {
|
||||
if (configData[i].key_value !== "") {
|
||||
setAvatar(configData[i].key_value);
|
||||
setAvatar(res.data.resource_url[Number(configData[i].key_value)]);
|
||||
} else {
|
||||
setAvatar(memberDefaultAvatar);
|
||||
}
|
||||
form.setFieldsValue({
|
||||
"member.default_avatar": configData[i].key_value,
|
||||
});
|
||||
} else if (configData[i].key_name === "s3.service") {
|
||||
form.setFieldsValue({
|
||||
"s3.service": configData[i].key_value,
|
||||
});
|
||||
setS3Service(configData[i].key_value);
|
||||
} else if (configData[i].key_name === "s3.access_key") {
|
||||
form.setFieldsValue({
|
||||
"s3.access_key": configData[i].key_value,
|
||||
@@ -163,10 +152,6 @@ const SystemConfigPage = () => {
|
||||
form.setFieldsValue({
|
||||
"s3.endpoint": configData[i].key_value,
|
||||
});
|
||||
} else if (configData[i].key_name === "s3.domain") {
|
||||
form.setFieldsValue({
|
||||
"s3.domain": configData[i].key_value,
|
||||
});
|
||||
} else if (configData[i].key_name === "ldap.enabled") {
|
||||
let value = 0;
|
||||
if (configData[i].key_value === "1") {
|
||||
@@ -271,7 +256,6 @@ const SystemConfigPage = () => {
|
||||
"ldap-enabled": res.data["ldap-enabled"],
|
||||
systemName: res.data["system.name"],
|
||||
systemLogo: res.data["system.logo"],
|
||||
systemApiUrl: res.data["system.api_url"],
|
||||
systemPcUrl: res.data["system.pc_url"],
|
||||
systemH5Url: res.data["system.h5_url"],
|
||||
memberDefaultAvatar: res.data["member.default_avatar"],
|
||||
@@ -322,9 +306,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex ml-24">
|
||||
<UploadImageButton
|
||||
text="更换Logo"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setLogo(url);
|
||||
form.setFieldsValue({ "system.logo": url });
|
||||
form.setFieldsValue({ "system.logo": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
</div>
|
||||
@@ -344,9 +328,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex ml-24">
|
||||
<UploadImageButton
|
||||
text="更换Logo"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setLogo(url);
|
||||
form.setFieldsValue({ "system.logo": url });
|
||||
form.setFieldsValue({ "system.logo": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
</div>
|
||||
@@ -356,13 +340,6 @@ const SystemConfigPage = () => {
|
||||
</div>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
label="API访问地址"
|
||||
name="system.api_url"
|
||||
>
|
||||
<Input style={{ width: 274 }} placeholder="请填写API访问地址" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
label="PC学员端地址"
|
||||
@@ -511,9 +488,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex ml-24">
|
||||
<UploadImageButton
|
||||
text="更换封面"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setThumb(url);
|
||||
form.setFieldsValue({ "player.poster": url });
|
||||
form.setFieldsValue({ "player.poster": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<div className="helper-text ml-8">
|
||||
@@ -533,9 +510,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换封面"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setThumb(url);
|
||||
form.setFieldsValue({ "player.poster": url });
|
||||
form.setFieldsValue({ "player.poster": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<div className="helper-text ml-8">
|
||||
@@ -588,9 +565,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex ml-24">
|
||||
<UploadImageButton
|
||||
text="更换头像"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setAvatar(url);
|
||||
form.setFieldsValue({ "member.default_avatar": url });
|
||||
form.setFieldsValue({ "member.default_avatar": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<div className="helper-text ml-8">(新学员的默认头像)</div>
|
||||
@@ -608,9 +585,9 @@ const SystemConfigPage = () => {
|
||||
<div className="d-flex">
|
||||
<UploadImageButton
|
||||
text="更换头像"
|
||||
onSelected={(url) => {
|
||||
onSelected={(url, id) => {
|
||||
setAvatar(url);
|
||||
form.setFieldsValue({ "member.default_avatar": url });
|
||||
form.setFieldsValue({ "member.default_avatar": id });
|
||||
}}
|
||||
></UploadImageButton>
|
||||
<div className="helper-text ml-8">(新学员的默认头像)</div>
|
||||
@@ -643,24 +620,6 @@ const SystemConfigPage = () => {
|
||||
onFinishFailed={onFinishFailed}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
label="服务商"
|
||||
name="s3.service"
|
||||
>
|
||||
<Select
|
||||
defaultValue={null}
|
||||
style={{ width: 200 }}
|
||||
placeholder="请选择服务商"
|
||||
options={[
|
||||
{ value: "oss", label: "阿里云OSS" },
|
||||
{ value: "cos", label: "腾讯云COS" },
|
||||
]}
|
||||
onChange={(e: any) => {
|
||||
setS3Service(e);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
label="AccessKey"
|
||||
@@ -716,17 +675,6 @@ const SystemConfigPage = () => {
|
||||
placeholder="请填写Endpoint"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
label="Domain"
|
||||
name="s3.domain"
|
||||
>
|
||||
<Input
|
||||
style={{ width: 274 }}
|
||||
allowClear
|
||||
placeholder="请填写Domain"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 30 }}
|
||||
wrapperCol={{ offset: 3, span: 21 }}
|
||||
|
||||
4
playedu-admin/src/playedu.d.ts
vendored
@@ -141,6 +141,10 @@ declare global {
|
||||
rid: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface ResourceUrlModel {
|
||||
[key: number]: string;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
@@ -46,6 +46,8 @@ const DepartmentPage = lazy(() => import("../pages/department"));
|
||||
const TestPage = lazy(() => import("../pages/test"));
|
||||
//错误页面
|
||||
const ErrorPage = lazy(() => import("../pages/error"));
|
||||
//使用许可页面
|
||||
const LicensingPage = lazy(() => import("../pages/licensing/index"));
|
||||
|
||||
import PrivateRoute from "../compenents/private-route";
|
||||
|
||||
@@ -161,6 +163,10 @@ const routes: RouteObject[] = [
|
||||
path: "/department",
|
||||
element: <PrivateRoute Component={<DepartmentPage />} />,
|
||||
},
|
||||
{
|
||||
path: "/licensing",
|
||||
element: <PrivateRoute Component={<LicensingPage />} />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@ import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
type SystemConfigStoreInterface = {
|
||||
"ldap-enabled"?: boolean;
|
||||
systemApiUrl?: string;
|
||||
systemPcUrl?: string;
|
||||
systemH5Url?: string;
|
||||
systemLogo?: string;
|
||||
@@ -11,6 +10,7 @@ type SystemConfigStoreInterface = {
|
||||
courseDefaultThumbs?: string[];
|
||||
departments?: any;
|
||||
resourceCategories?: any;
|
||||
resourceUrl?: ResourceUrlModel;
|
||||
};
|
||||
|
||||
let defaultValue: SystemConfigStoreInterface = {};
|
||||
|
||||