feat:增加关卡路线

This commit is contained in:
lixg
2023-02-13 16:26:01 +08:00
parent fd9c4c31c6
commit fafe4813bf
12 changed files with 1422 additions and 156 deletions

992
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,8 @@
"build:test": "vite build --mode test"
},
"dependencies": {
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.1.3",
"core-js": "^3.26.0",
"dayjs": "^1.11.6",

View File

@@ -2,7 +2,7 @@
* @Author: lixg lixg@dongwu-inc.com
* @Date: 2023-01-13 11:42:48
* @LastEditors: lixg lixg@dongwu-inc.com
* @LastEditTime: 2023-02-07 17:36:05
* @LastEditTime: 2023-02-10 15:31:15
* @FilePath: /stu_h5/src/api/api.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@@ -59,3 +59,5 @@ export const COMMENT_COLLECTION = '/comment/collection post'
// 外部考试详情接口
export const EXTERNALEXAM = `/external/exam/queryExternalExam`
//关卡列表接口
export const ROUTERTASK_LIST = '/stu/router/chapterList post'

View File

@@ -149,4 +149,17 @@ export async function boeRequest(_url, params) {
}).then(res => {
return JSONBigIntStr.parse(res)
})
}
}
const httpupload = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000 * 15,
headers: { "Content-Type": "multipart/form-data" },
});
export const fileUp = (data) => httpupload.post("/file/img", data, {
headers: { "Content-Type": "multipart/form-data" },
});
export const videoUp = (data) => httpupload.post("/file/uploadunlimit", data, {
headers: { "Content-Type": "multipart/form-data" },
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -0,0 +1,147 @@
<template>
<div class="pathDetail" :style="{ backgroundImage: `url('${back}')` }">
<div
v-for="(item, i) in data"
:key="i"
class="cha"
:style="{
top: `${imgAttr.positions[i]?.top - (current === i ? 5 : 0)}px`,
left: `${imgAttr.positions[i]?.left - (current === i ? 10 : 0)}px`,
}"
>
<div
@click="toDetail(i)"
class="nameClass"
:title="item.name"
:style="{
background: `url('${current === i ? currentBack : nameBack}')`,
backgroundSize: '100%',
width: `${current === i ? 139 : 123}px`,
height: `${current === i ? 60 : 60}px`,
lineHeight: '50px',
color: '#FFF',
}"
>
{{ item.name }}
</div>
</div>
</div>
</template>
<script setup>
import { computed, defineProps, ref, watch } from "vue";
import back from "@/assets/image/pathdetails/pathDetailBack.png";
import nameBack from "@/assets/image/pathdetails/pathDetailImg.png";
import currentBack from "@/assets/image/pathdetails/pathDetailImgSelect.png";
import { useRouter } from "vue-router/dist/vue-router";
import { ElLoading } from "element-plus";
import { ROUTERTASK_LIST } from "@/api/api";
import { usePage } from "@/api/request";
const listheight = document.body.clientHeight - 300 + "px";
console.log("listheight", listheight);
const props = defineProps({
value: String,
img: String,
routerId: {
type: Number,
default: null,
},
});
const router = useRouter();
const visiable = ref(true);
const imageAttrs = {
"路径图背景-1671015331292.png": {
width: 1437,
height: 594,
positions: [
{ left: -28, top: 435 },
{ left: 170, top: 360 },
{ left: 20, top: 260 },
{ left: 200, top: 183 },
{ left: 160, top: 66 },
{ left: 260, top: -30 },
],
},
};
const imgAttr = computed(
() =>
imageAttrs[Object.keys(imageAttrs).find((e) => props.img.includes(e))] || {}
);
// 使用
const loading = ref(false); // loading
const openLoading = () => {
loading.value = ElLoading.service({
lock: true,
text: "Loading",
background: "rgba(0, 0, 0, 0.7)",
});
};
openLoading();
const closeLoading = () => {
loading.value.close();
};
const { data } = usePage(ROUTERTASK_LIST, { routerId: props.routerId }, (e) => {
console.log("我请求成功了吗", e);
closeLoading();
});
const current = computed(() =>
data.value.findIndex((e) => e.chapterId === props.currentStageId)
);
console.log("data", data);
function show() {
visiable.value = true;
}
function toDetail(i) {
console.log("import.meta.env.MODE", import.meta.env.MODE);
if (current.value !== i) {
return;
}
import.meta.env.MODE === "development" || import.meta.env.MODE === "test"
? router.push({
path: "/pathdetails",
query: {
routerId: props.routerId,
// routerName: props.detail.routerName,
},
})
: window.open(
`${
window.location.protocol + import.meta.env.VITE_BOE_PATH_DETAIL_URL
}/pathdetails&params=${encodeURIComponent(
`routerId=${props.detail.routerId}&routerName=${props.detail.routerName}`
)}`,
"_top"
);
}
function close() {
visiable.value = false;
}
</script>
<style lang="scss">
.pathDetail {
width: 410px;
height: 500px;
position: relative;
background-size: 100% 100%;
background-repeat: no-repeat;
// background-position: center;
// overflow-x: scroll;
margin: 20px;
.cha {
position: absolute;
cursor: pointer;
}
.nameClass {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
padding: 0 20px 0 50px;
font-size: 12px;
}
}
</style>

View File

@@ -2,7 +2,20 @@
<div class="discusspage">
<ReturnHead text="讨论详情" :ispublish="true"></ReturnHead>
<div class="head clearfix">
<div class="title">{}</div>
<div class="title">
{{
data && data.discussDtoList && data.discussDtoList.length !== 0
? data?.discussDtoList[0].discussName
: "-"
}}
</div>
<div class="title" style="margin-top: 0px">
{{
data && data.discussDtoList && data.discussDtoList.length !== 0
? data?.discussDtoList[0].discussExplain
: "-"
}}
</div>
</div>
<div class="preview">
@@ -98,36 +111,15 @@ const router = useRouter();
const state = reactive({
onfo: true,
discuss: [
{
id: 1,
title: "从营销角度分析:我的团队需要这些能力",
contain:
"所谓团队协作能力,是指建立在团队的基础之上,发挥团队精神、互补互助以达到团队最大工作效率的能力。对于团队的成员来说...",
pinglun: 317,
dianzan: 103,
isGood: false,
},
{
id: 2,
title: "从营销角度分析:我的团队需要这些能力",
contain:
"所谓团队协作能力,是指建立在团队的基础之上,发挥团队精神、互补互助以达到团队最大工作效率的能力。对于团队的成员来说...",
pinglun: 317,
dianzan: 103,
isGood: false,
},
{
id: 3,
title: "从营销角度分析:我的团队需要这些能力",
contain:
"所谓团队协作能力,是指建立在团队的基础之上,发挥团队精神、互补互助以达到团队最大工作效率的能力。对于团队的成员来说...",
pinglun: 317,
dianzan: 103,
isGood: false,
},
// {
// id: 1,
// title: "从营销角度分析:我的团队需要这些能力",
// contain:
// "所谓团队协作能力,是指建立在团队的基础之上,发挥团队精神、互补互助以达到团队最大工作效率的能力。对于团队的成员来说...",
// pinglun: 317,
// dianzan: 103,
// isGood: false,
// },
],
});
const { onfo, discuss } = toRefs(state);
@@ -155,8 +147,103 @@ const getId = (it) => {
const {
query: { id, type },
} = useRoute();
const { data } = useRequest(DISCUSS_LIST, { id: 23, type });
const { data } = useRequest(DISCUSS_LIST, { id, type });
console.log("获取讨论", data);
// 获取帖子
function getPostList(discussId) {
console.log({
discussId: discussId,
pageNo: state.pageNo,
pageSize: state.pageSize,
searchType: state.searchType,
});
request(QueryDiscussSubmitDetailByDiscussId, {
discussId: discussId,
pageNo: state.pageNo,
pageSize: state.pageSize,
searchType: state.searchType,
})
.then((e) => {
console.log("我是当前讨论下的帖子", e);
state.postList = e.data.rows;
state.total = e.data.total;
// 添加一条假的数据 供测试使用
state.postList = [
{
createTime: "",
createUser: 0,
discussCollectionCount: "234",
discussId: "",
discussLikeCount: "3576",
discussReviewCount: "12353",
discussSubmitContent:
"帖子的内容----帖子的内容帖子的内容帖子的内容帖子的内容帖子的内容帖子的内容帖子的内容帖子的内容帖子的内容",
discussSubmitId: "",
discussSubmitPictureAddress: "",
discussSubmitTitle: "我是一个用来测试的帖子标题",
stuId: "",
stuName: "",
updateTime: "",
updateUser: 0,
submitReviewVoList: [
{
createTime: "",
createUser: 0,
discussLikeCount: "",
discussReviewContent: "",
discussReviewFlag: "",
discussReviewId: "",
discussReviewPictureAddress: "",
discussSubmitId: "",
stuId: "",
stuName: "",
submitReplyVoList: [
{
createTime: "",
createUser: 0,
discussReplyId: 0,
discussReviewId: "",
replyContent: "",
replyFlag: "",
replyPictureAddress: "",
reviewStuId: "",
reviewStuName: "",
stuId: "",
stuName: "",
updateTime: "",
updateUser: 0,
},
],
updateTime: "",
updateUser: 0,
},
],
},
];
state.total = 100;
})
.catch((err) => {
console.log(err);
});
}
// 最新
function nowPost(discussId) {
state.searchType = 1;
state.pageNo = 1;
state.currentPage = 1;
getPostList(discussId);
}
// 最热
function hotPost(discussId) {
state.searchType = 2;
state.pageNo = 1;
state.currentPage = 1;
getPostList(discussId);
}
//跳转到讨论详情
const goDetails = () => {
@@ -182,13 +269,15 @@ const goDetails = () => {
.head {
margin-top: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
background-color: #fff;
.title {
width: 90%;
margin-top: 20px;
margin-bottom: 21px;
margin-top: 10px;
margin-bottom: 10px;
color: #333330;
font-size: 13px;
line-height: 24px;

View File

@@ -13,19 +13,37 @@
<div class="inputcontainer">
<div class="inputt">
<div class="i_title">
<input type="text" id="input_title" placeholder="请输入标题" />
<el-input
type="text"
id="input_title"
placeholder="请输入标题"
v-model:value="disTitle"
/>
</div>
<div class="discusscontent">
<el-input
<!-- <el-input
type="textarea"
placeholder="请输入正文"
v-model="textarea"
autosize
></el-input>
></el-input> -->
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="min-height: 300px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated"
/>
</div>
</div>
<div class="imgcon">
<!-- <div class="imgcon">
<div class="linecon">
<div class="line"></div>
</div>
@@ -35,35 +53,95 @@
<img src="../../assets/image/discuss/next.png" />
<img src="../../assets/image/discuss/delete.png" />
</div>
</div>
</div> -->
</div>
</div>
</template>
<script>
import { reactive, toRefs } from "vue";
<script setup>
import { reactive, ref, toRefs, shallowRef, onBeforeUnmount } from "vue";
import ReturnHead from "@/components/ReturnHead.vue";
export default {
name: "UploadWork",
components: {
ReturnHead,
},
setup() {
const state = reactive({
text: "",
textarea: "",
screenHeight: document.body.clientHeight, // 屏幕高度
import "@wangeditor/editor/dist/css/style.css";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { fileUp, videoUp } from "../../api/request";
import { ElLoading } from "element-plus";
const state = reactive({
text: "",
textarea: "",
screenHeight: document.body.clientHeight, // 屏幕高度
disTitle: null,
});
// 使用
const loading = ref(false); // loading
const openLoading = () => {
loading.value = ElLoading.service({
lock: true,
text: "Loading",
background: "rgba(0, 0, 0, 0.7)",
});
};
const closeLoading = () => {
loading.value.close();
};
//发布讨论
const publishWork = () => {
console.log("点击了发布");
};
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef();
// 内容 HTML
const valueHtml = ref("");
const toolbarConfig = {
excludeKeys: ["insertVideo", "uploadVideo", "insertImage", "group-video"],
};
const editorConfig = { placeholder: "请输入内容...", MENU_CONF: {} };
editorConfig.MENU_CONF["uploadImage"] = {
// 自定义上传
async customUpload(file, insertFn) {
openLoading();
const formData = new FormData();
formData.append("file", file);
fileUp(formData).then((res) => {
closeLoading();
if (res.data.code === 200) {
// 最后插入图片 url alt href
insertFn(res.data.data, file.name, res.data.data);
}
});
//发布讨论
const publishWork = () => {
console.log("点击了发布");
};
return {
...toRefs(state),
publishWork,
};
},
};
editorConfig.MENU_CONF["uploadVideo"] = {
// 自定义上传
async customUpload(file, insertVideoFn) {
openLoading();
const formData = new FormData();
formData.append("file", file);
console.log("file", file, insertVideoFn);
videoUp(formData).then((res) => {
console.log("res", res);
if (res.data.code === 200) {
closeLoading();
// 最后插入图片 url alt href
insertVideoFn(res.data.data, file.name, res.data.data);
}
});
},
};
const handleCreated = (editor) => {
editorRef.value = editor; // 记录 editor 实例,重要!
};
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
</script>
<style lang="scss">
@@ -94,7 +172,7 @@ clearfix:after {
// padding-bottom: 79px;
.discusscontent {
height: calc(100% - 79px);
height: 100%;
overflow-y: scroll;
}
}
@@ -120,6 +198,16 @@ clearfix:after {
border: none;
outline: none;
}
.el-input__wrapper {
background-color: rgba(255, 255, 255, 0);
box-shadow: 0 0 0 0px var(--el-input-hover-border-color) inset;
}
.el-input__wrapper:hover {
box-shadow: 0 0 0 0px var(--el-input-hover-border-color) inset;
}
.el-input__wrapper:focus {
box-shadow: 0 0 0 0px var(--el-input-hover-border-color) inset;
}
}
::v-deep .el-textarea__inner {
resize: none;

View File

@@ -0,0 +1,119 @@
<!--
* @Author: lixg lixg@dongwu-inc.com
* @Date: 2023-01-19 14:59:34
* @LastEditors: lixg lixg@dongwu-inc.com
* @LastEditTime: 2023-02-10 19:02:17
* @FilePath: /stu_h5/src/views/pathmap/LevelList.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="pathdetails">
<ReturnHead
text="路径详情"
:showfile="true"
:courseId="routerId"
></ReturnHead>
<!-- 学习路径介绍 -->
<div class="pathdetail">
<div class="pathName">产品经理学习路径图</div>
<div class="pathIntro">
为了提升集团各条线产品经理的专业能力集团XX组织为产
品经理设置了统一的学习径为了提升集团各条线产品经理的
专业能力集团XX组织为产品经理设置了统一的学习径为了
提升集团各条线产品经理的专业
</div>
</div>
<!-- 学习路径介绍 -->
<!-- 关卡列表 -->
<div class="level">
<div class="leveltitle">关卡列表</div>
<div style="width: 100%; display: flex; justify-content: center">
<div class="levelItem" :style="{ height: listheight }">
<PathDetailImage
img="https://u-pre.boe.com/upload/路径图背景-1671015331292.png"
:routerId="routerId"
></PathDetailImage>
</div>
</div>
</div>
<!-- 关卡列表 -->
</div>
</template>
<script setup>
import { computed, reactive, toRefs, onUnmounted, ref } from "vue";
import ReturnHead from "@/components/ReturnHead.vue";
import PathDetailImage from "@/components/PathDetailImage.vue";
import { useRequest, request, usePage } from "@/api/request";
import {
ROUTER_PROCESS,
STUDY_RECORD,
ROUTER_DETAILS,
TASK_LIST,
} from "@/api/api";
import { useRoute, useRouter } from "vue-router";
const listheight = document.body.clientHeight - 310 + "px";
const {
query: { routerId },
} = useRoute();
// const { data } = useRequest(TASK_LIST, { routerId: routerId });
// console.log("获取路径图", data);
</script>
<style lang="scss">
.pathdetails {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
.pathdetail {
width: 90%;
min-height: 173px;
background-color: #fff;
margin-top: 10px;
padding-left: 5%;
padding-right: 5%;
.pathName {
font-size: 14px;
font-weight: 600;
color: #04243c;
line-height: 21px;
margin-top: 30px;
margin-bottom: 19px;
}
.pathIntro {
font-size: 13px;
font-weight: 400;
color: #333330;
line-height: 24px;
}
}
.level {
width: 100%;
min-height: 173px;
background-color: #fff;
margin-top: 10px;
.leveltitle {
width: 95%;
height: 50px;
border-bottom: 1px solid #f1f2f3;
display: flex;
align-items: center;
padding-left: 5%;
margin-bottom: 8px;
}
.levelItem {
width: 100%;
border-radius: 8px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
// padding-left: 5%;
// padding-right: 3%;
overflow-x: scroll;
overflow-y: scroll;
}
}
}
</style>

View File

@@ -2,7 +2,7 @@
* @Author: lixg lixg@dongwu-inc.com
* @Date: 2023-01-19 11:28:11
* @LastEditors: lixg lixg@dongwu-inc.com
* @LastEditTime: 2023-02-09 10:20:19
* @LastEditTime: 2023-02-11 09:47:29
* @FilePath: /stu_h5/src/views/projectdetails/ProjectPath.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->