mirror of
https://github.com/PlayEdu/PlayEdu
synced 2025-10-26 22:51:36 +08:00
!14 存储桶改为private
* 后台 使用许可页面 * 优化:移除API访问地址配置 * 后台、pc、h5 删除无用配置 * docker部署优化 * 2.0 networkMode=bridge * changelog * 学员端权限为空报错 * h5 我的页面请求优化 * 缓存查询 * 后台 学员列表报错、线上课-上架时间字段优化 * 后台、pc、h5 使用签名地址 * 学员端接口修改 * 后台、pc 使用签名地址 * 后台 使用签名地址 * 上传接口 * 上传接口 * 系统配置 * 线上课封面 * bucket由public改为private * 资源相关表实体及对象修改 * 统一数据库脚本
This commit is contained in:
3062
playedu-h5/pnpm-lock.yaml
generated
Normal file
3062
playedu-h5/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
playedu-h5/src/assets/thumb/avatar.png
Normal file
BIN
playedu-h5/src/assets/thumb/avatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
playedu-h5/src/assets/thumb/thumb1.png
Normal file
BIN
playedu-h5/src/assets/thumb/thumb1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
playedu-h5/src/assets/thumb/thumb2.png
Normal file
BIN
playedu-h5/src/assets/thumb/thumb2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
playedu-h5/src/assets/thumb/thumb3.png
Normal file
BIN
playedu-h5/src/assets/thumb/thumb3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -106,28 +106,29 @@ const CoursePage = () => {
|
||||
navigate(`/course/${cid}/hour/${id}`);
|
||||
};
|
||||
|
||||
const downLoadFile = (cid: number, id: number) => {
|
||||
const downLoadFile = (cid: number, id: number, rid: number) => {
|
||||
vod.downloadAttachment(cid, id).then((res: any) => {
|
||||
let url = res.data.resource_url[rid];
|
||||
if (isWechat()) {
|
||||
if (isIOS()) {
|
||||
Toast.show("请点击右上角···浏览器打开下载");
|
||||
}
|
||||
var input = document.createElement("input");
|
||||
input.value = res.data.download_url;
|
||||
input.value = url;
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
document.execCommand("Copy");
|
||||
document.body.removeChild(input);
|
||||
window.open(res.data.download_url);
|
||||
window.open(url);
|
||||
} else {
|
||||
if (isIOS()) {
|
||||
setDownLoadTemplateURL(res.data.download_url);
|
||||
setDownLoadTemplateURL(url);
|
||||
setTimeout(() => {
|
||||
let $do: any = document.querySelector("#downLoadExcel");
|
||||
$do.click();
|
||||
}, 500);
|
||||
} else {
|
||||
window.open(res.data.download_url);
|
||||
window.open(url);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -287,7 +288,9 @@ const CoursePage = () => {
|
||||
</div>
|
||||
<div
|
||||
className={styles["download"]}
|
||||
onClick={() => downLoadFile(item.course_id, item.id)}
|
||||
onClick={() =>
|
||||
downLoadFile(item.course_id, item.id, item.rid)
|
||||
}
|
||||
>
|
||||
下载
|
||||
</div>
|
||||
|
||||
@@ -120,7 +120,7 @@ const CoursePlayPage = () => {
|
||||
} else if (record && record.is_finished === 1) {
|
||||
setWatchedSeconds(res.data.hour.duration);
|
||||
}
|
||||
getVideoUrl(params);
|
||||
getVideoUrl(res.data.hour.rid, params);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
@@ -128,12 +128,12 @@ const CoursePlayPage = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const getVideoUrl = (data: any) => {
|
||||
const getVideoUrl = (rid: number, data: any) => {
|
||||
Course.playUrl(Number(params.courseId), Number(params.hourId)).then(
|
||||
(res: any) => {
|
||||
window.player && window.player.destroy();
|
||||
setPlayUrl(res.data.url);
|
||||
initDPlayer(res.data.url, 0, data);
|
||||
setPlayUrl(res.data.resource_url[rid]);
|
||||
initDPlayer(res.data.resource_url[rid], 0, data);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,6 +9,9 @@ import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { Footer, Empty } from "../../components";
|
||||
import { CoursesModel } from "./compenents/courses-model";
|
||||
import { isEmptyObject } from "../../utils/index";
|
||||
import defaultThumb1 from "../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../assets/thumb/thumb3.png";
|
||||
|
||||
type LocalUserLearnHourRecordModel = {
|
||||
[key: number]: UserLearnHourRecordModel;
|
||||
@@ -36,6 +39,7 @@ const IndexPage = () => {
|
||||
useState<LocalUserLearnHourRecordModel>({});
|
||||
const [learnCourseHourCount, setLearnCourseHourCount] =
|
||||
useState<LocalUserLearnHourCountModel>({});
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
const systemConfig = useSelector((state: any) => state.systemConfig.value);
|
||||
const currentDepId = useSelector(
|
||||
(state: any) => state.loginUser.value.currentDepId
|
||||
@@ -85,6 +89,7 @@ const IndexPage = () => {
|
||||
const records = res.data.learn_course_records;
|
||||
setLearnCourseRecords(records);
|
||||
setLearnCourseHourCount(res.data.user_course_hour_count);
|
||||
setResourceUrl(res.data.resource_url);
|
||||
if (Number(tabKey) === 0) {
|
||||
setCoursesList(res.data.courses);
|
||||
} else if (Number(tabKey) === 1) {
|
||||
@@ -323,7 +328,15 @@ const IndexPage = () => {
|
||||
<CoursesModel
|
||||
id={item.id}
|
||||
title={item.title}
|
||||
thumb={item.thumb}
|
||||
thumb={
|
||||
item.thumb === -1
|
||||
? defaultThumb1
|
||||
: item.thumb === -2
|
||||
? defaultThumb2
|
||||
: item.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[item.thumb]
|
||||
}
|
||||
isRequired={item.is_required}
|
||||
record={learnCourseRecords[item.id]}
|
||||
hourCount={learnCourseHourCount[item.id]}
|
||||
|
||||
@@ -25,11 +25,11 @@ export const InitPage = (props: Props) => {
|
||||
let config: SystemConfigStoreInterface = {
|
||||
//系统配置
|
||||
"ldap-enabled": props.configData["ldap-enabled"],
|
||||
systemApiUrl: props.configData["system-api-url"],
|
||||
systemH5Url: props.configData["system-h5-url"],
|
||||
systemLogo: props.configData["system-logo"],
|
||||
systemName: props.configData["system-name"],
|
||||
systemPcUrl: props.configData["system-pc-url"],
|
||||
resourceUrl: props.configData["resource_url"],
|
||||
pcIndexFooterMsg: props.configData["system-pc-index-footer-msg"],
|
||||
//播放器配置
|
||||
playerPoster: props.configData["player-poster"],
|
||||
|
||||
@@ -87,11 +87,11 @@ const LoginPage = () => {
|
||||
let config: SystemConfigStoreInterface = {
|
||||
//系统配置
|
||||
"ldap-enabled": configRes.data["ldap-enabled"],
|
||||
systemApiUrl: configRes.data["system-api-url"],
|
||||
systemH5Url: configRes.data["system-h5-url"],
|
||||
systemLogo: configRes.data["system-logo"],
|
||||
systemName: configRes.data["system-name"],
|
||||
systemPcUrl: configRes.data["system-pc-url"],
|
||||
resourceUrl: configRes.data["resource_url"],
|
||||
pcIndexFooterMsg: configRes.data["system-pc-index-footer-msg"],
|
||||
//播放器配置
|
||||
playerPoster: configRes.data["player-poster"],
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ImageUploadItem } from "antd-mobile/es/components/image-uploader";
|
||||
import styles from "./index.module.scss";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import moreIcon from "../../assets/images/commen/icon-more.png";
|
||||
import memberDefaultAvatar from "../../assets/thumb/avatar.png";
|
||||
|
||||
const MemberPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -33,6 +34,9 @@ const MemberPage = () => {
|
||||
const currentDepId = useSelector(
|
||||
(state: any) => state.loginUser.value.currentDepId
|
||||
);
|
||||
const resourceUrl = useSelector(
|
||||
(state: any) => state.loginUser.value.resourceUrl
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "我的";
|
||||
@@ -50,30 +54,35 @@ const MemberPage = () => {
|
||||
return;
|
||||
}
|
||||
getData();
|
||||
}, [currentDepId, user]);
|
||||
}, [currentDepId]);
|
||||
|
||||
const getData = () => {
|
||||
setLoading(true);
|
||||
member.courses(currentDepId, 0).then((res: any) => {
|
||||
setStats(res.data.stats);
|
||||
let todayData = studyTimeFormat(res.data.stats.today_learn_duration);
|
||||
if (todayData) {
|
||||
setLearnTodayHour(todayData[0]);
|
||||
setLearnTodayMin(todayData[1]);
|
||||
if (todayData[1] === 0 && todayData[2] > 0) {
|
||||
setLearnTodayMin(1);
|
||||
member
|
||||
.courses(currentDepId, 0)
|
||||
.then((res: any) => {
|
||||
setStats(res.data.stats);
|
||||
let todayData = studyTimeFormat(res.data.stats.today_learn_duration);
|
||||
if (todayData) {
|
||||
setLearnTodayHour(todayData[0]);
|
||||
setLearnTodayMin(todayData[1]);
|
||||
if (todayData[1] === 0 && todayData[2] > 0) {
|
||||
setLearnTodayMin(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
let totalData = studyTimeFormat(res.data.stats.learn_duration);
|
||||
if (totalData) {
|
||||
setLearnTotalHour(totalData[0]);
|
||||
setLearnTotalMin(totalData[1]);
|
||||
if (totalData[1] === 0 && totalData[2] > 0) {
|
||||
setLearnTodayMin(1);
|
||||
let totalData = studyTimeFormat(res.data.stats.learn_duration);
|
||||
if (totalData) {
|
||||
setLearnTotalHour(totalData[0]);
|
||||
setLearnTotalMin(totalData[1]);
|
||||
if (totalData[1] === 0 && totalData[2] > 0) {
|
||||
setLearnTodayMin(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const setClick = () => {
|
||||
@@ -157,16 +166,22 @@ const MemberPage = () => {
|
||||
)}
|
||||
{init && (
|
||||
<>
|
||||
<Image
|
||||
width={100}
|
||||
height={100}
|
||||
style={{
|
||||
borderRadius: "50%",
|
||||
marginRight: 20,
|
||||
}}
|
||||
fit="cover"
|
||||
src={user?.avatar}
|
||||
/>
|
||||
{user ? (
|
||||
<Image
|
||||
width={100}
|
||||
height={100}
|
||||
style={{
|
||||
borderRadius: "50%",
|
||||
marginRight: 20,
|
||||
}}
|
||||
fit="cover"
|
||||
src={
|
||||
user.avatar === -1
|
||||
? memberDefaultAvatar
|
||||
: resourceUrl[user.avatar]
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
<div className={styles["other-cont"]}>
|
||||
<div className={styles["name"]}>{user?.name}</div>
|
||||
<div className={styles["departments"]}>
|
||||
|
||||
@@ -5,6 +5,9 @@ import styles from "./index.module.scss";
|
||||
import { course } from "../../api/index";
|
||||
import { Empty } from "../../components";
|
||||
import { CoursesModel } from "./compenents/courses-model";
|
||||
import defaultThumb1 from "../../assets/thumb/thumb1.png";
|
||||
import defaultThumb2 from "../../assets/thumb/thumb2.png";
|
||||
import defaultThumb3 from "../../assets/thumb/thumb3.png";
|
||||
import moment from "moment";
|
||||
|
||||
const StudyPage = () => {
|
||||
@@ -12,6 +15,7 @@ const StudyPage = () => {
|
||||
const [todayCourses, setTodayCourses] = useState<CourseModel[]>([]);
|
||||
const [yesterdayCourses, setYesterdayCourses] = useState<CourseModel[]>([]);
|
||||
const [courses, setCourses] = useState<CourseModel[]>([]);
|
||||
const [resourceUrl, setResourceUrl] = useState<ResourceUrlModel>({});
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "最近学习";
|
||||
@@ -26,29 +30,32 @@ const StudyPage = () => {
|
||||
course
|
||||
.latestLearn()
|
||||
.then((res: any) => {
|
||||
let data = res.data;
|
||||
let today: CourseModel[] = [];
|
||||
let yesterday: CourseModel[] = [];
|
||||
let box: CourseModel[] = [];
|
||||
if (data && data.length > 0) {
|
||||
data.map((item: any) => {
|
||||
let time = moment(item.hour_record.updated_at)
|
||||
.utcOffset(0)
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
if (moment(time).isSame(moment(), "day")) {
|
||||
today.push(item);
|
||||
} else if (
|
||||
moment(time).isSame(moment().subtract(1, "day"), "day")
|
||||
) {
|
||||
yesterday.push(item);
|
||||
} else {
|
||||
box.push(item);
|
||||
}
|
||||
});
|
||||
if (res.data.resource_url && res.data.user_latest_learns) {
|
||||
setResourceUrl(res.data.resource_url);
|
||||
let data = res.data.user_latest_learns;
|
||||
let today: CourseModel[] = [];
|
||||
let yesterday: CourseModel[] = [];
|
||||
let box: CourseModel[] = [];
|
||||
if (data && data.length > 0) {
|
||||
data.map((item: any) => {
|
||||
let time = moment(item.hour_record.updated_at)
|
||||
.utcOffset(0)
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
if (moment(time).isSame(moment(), "day")) {
|
||||
today.push(item);
|
||||
} else if (
|
||||
moment(time).isSame(moment().subtract(1, "day"), "day")
|
||||
) {
|
||||
yesterday.push(item);
|
||||
} else {
|
||||
box.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
setTodayCourses(today);
|
||||
setYesterdayCourses(yesterday);
|
||||
setCourses(box);
|
||||
}
|
||||
setTodayCourses(today);
|
||||
setYesterdayCourses(yesterday);
|
||||
setCourses(box);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
@@ -101,7 +108,15 @@ const StudyPage = () => {
|
||||
<CoursesModel
|
||||
id={item.course.id}
|
||||
title={item.course.title}
|
||||
thumb={item.course.thumb}
|
||||
thumb={
|
||||
item.course.thumb === -1
|
||||
? defaultThumb1
|
||||
: item.course.thumb === -2
|
||||
? defaultThumb2
|
||||
: item.course.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[item.course.thumb]
|
||||
}
|
||||
isRequired={item.course.is_required}
|
||||
record={item.record}
|
||||
></CoursesModel>
|
||||
@@ -119,7 +134,15 @@ const StudyPage = () => {
|
||||
<CoursesModel
|
||||
id={item.course.id}
|
||||
title={item.course.title}
|
||||
thumb={item.course.thumb}
|
||||
thumb={
|
||||
item.course.thumb === -1
|
||||
? defaultThumb1
|
||||
: item.course.thumb === -2
|
||||
? defaultThumb2
|
||||
: item.course.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[item.course.thumb]
|
||||
}
|
||||
isRequired={item.course.is_required}
|
||||
record={item.record}
|
||||
></CoursesModel>
|
||||
@@ -137,7 +160,15 @@ const StudyPage = () => {
|
||||
<CoursesModel
|
||||
id={item.course.id}
|
||||
title={item.course.title}
|
||||
thumb={item.course.thumb}
|
||||
thumb={
|
||||
item.course.thumb === -1
|
||||
? defaultThumb1
|
||||
: item.course.thumb === -2
|
||||
? defaultThumb2
|
||||
: item.course.thumb === -3
|
||||
? defaultThumb3
|
||||
: resourceUrl[item.course.thumb]
|
||||
}
|
||||
isRequired={item.course.is_required}
|
||||
record={item.record}
|
||||
></CoursesModel>
|
||||
|
||||
8
playedu-h5/src/playedu.d.ts
vendored
8
playedu-h5/src/playedu.d.ts
vendored
@@ -2,7 +2,7 @@ declare global {
|
||||
interface CourseModel {
|
||||
id: number;
|
||||
title: string;
|
||||
thumb: string;
|
||||
thumb: number;
|
||||
short_desc: string;
|
||||
is_required: number;
|
||||
charge: number;
|
||||
@@ -57,7 +57,7 @@ declare global {
|
||||
interface UserModel {
|
||||
id: number;
|
||||
name: string;
|
||||
avatar: string;
|
||||
avatar: number;
|
||||
credit1: number;
|
||||
email: string;
|
||||
create_city: string;
|
||||
@@ -72,6 +72,10 @@ declare global {
|
||||
login_at?: string;
|
||||
verify_at?: string;
|
||||
}
|
||||
|
||||
interface ResourceUrlModel {
|
||||
[key: number]: string;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
@@ -2,7 +2,6 @@ import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
type SystemConfigStoreInterface = {
|
||||
"ldap-enabled": string;
|
||||
systemApiUrl: string;
|
||||
systemPcUrl: string;
|
||||
systemH5Url: string;
|
||||
systemLogo: string;
|
||||
@@ -14,11 +13,11 @@ type SystemConfigStoreInterface = {
|
||||
playerBulletSecretText: string;
|
||||
playerBulletSecretColor: string;
|
||||
playerBulletSecretOpacity: string;
|
||||
resourceUrl?: ResourceUrlModel;
|
||||
};
|
||||
|
||||
let defaultValue: SystemConfigStoreInterface = {
|
||||
"ldap-enabled": "",
|
||||
systemApiUrl: "",
|
||||
systemPcUrl: "",
|
||||
systemH5Url: "",
|
||||
systemLogo: "",
|
||||
@@ -30,6 +29,7 @@ let defaultValue: SystemConfigStoreInterface = {
|
||||
playerBulletSecretText: "",
|
||||
playerBulletSecretColor: "",
|
||||
playerBulletSecretOpacity: "",
|
||||
resourceUrl: {},
|
||||
};
|
||||
|
||||
const systemConfigSlice = createSlice({
|
||||
|
||||
@@ -11,6 +11,7 @@ type UserStoreInterface = {
|
||||
user: UserModel | null;
|
||||
departments: string[];
|
||||
currentDepId: number;
|
||||
resourceUrl: ResourceUrlModel;
|
||||
isLogin: boolean;
|
||||
};
|
||||
|
||||
@@ -18,6 +19,7 @@ let defaultValue: UserStoreInterface = {
|
||||
user: null,
|
||||
departments: [],
|
||||
currentDepId: Number(getDepKey()) || 0,
|
||||
resourceUrl: {},
|
||||
isLogin: false,
|
||||
};
|
||||
|
||||
@@ -30,6 +32,7 @@ const loginUserSlice = createSlice({
|
||||
loginAction(stage, e) {
|
||||
stage.value.user = e.payload.user;
|
||||
stage.value.departments = e.payload.departments;
|
||||
stage.value.resourceUrl = e.payload.resource_url;
|
||||
stage.value.isLogin = true;
|
||||
if (e.payload.departments.length > 0 && stage.value.currentDepId === 0) {
|
||||
stage.value.currentDepId = e.payload.departments[0].id;
|
||||
@@ -39,6 +42,7 @@ const loginUserSlice = createSlice({
|
||||
logoutAction(stage) {
|
||||
stage.value.user = null;
|
||||
stage.value.departments = [];
|
||||
stage.value.resourceUrl = {};
|
||||
stage.value.isLogin = false;
|
||||
stage.value.currentDepId = 0;
|
||||
clearToken();
|
||||
|
||||
Reference in New Issue
Block a user