答题完整代码
This commit is contained in:
parent
d3ce47bd52
commit
23cb65e721
|
@ -1,2 +1,2 @@
|
||||||
# VITE_APP_BASE_API = 'http://127.0.0.1:8088'
|
# VITE_APP_BASE_API = 'http://127.0.0.1:8088'
|
||||||
VITE_APP_BASE_API = 'http://aw.9miao.fun/prod-api'
|
VITE_APP_BASE_API = 'https://xuaua.com/prod-api'
|
|
@ -1 +1 @@
|
||||||
VITE_APP_BASE_API = 'http://aw.9miao.fun/prod-api'
|
VITE_APP_BASE_API = 'https://xuaua.com/prod-api'
|
|
@ -2,10 +2,10 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/logo.ico">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<script src="//unpkg.com/@element-plus/icons-vue"></script>
|
<script src="//unpkg.com/@element-plus/icons-vue"></script>
|
||||||
<title>Vite App</title>
|
<title>Xuaxua</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"element-plus": "^2.7.7",
|
"element-plus": "^2.7.7",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
|
"swiper": "^8.4.7",
|
||||||
"vue": "^3.4.29",
|
"vue": "^3.4.29",
|
||||||
|
"vue-awesome-swiper": "^5.0.1",
|
||||||
"vue-router": "^4.3.3"
|
"vue-router": "^4.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1371,6 +1373,14 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dom7": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/dom7/-/dom7-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ssr-window": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/element-plus": {
|
"node_modules/element-plus": {
|
||||||
"version": "2.7.7",
|
"version": "2.7.7",
|
||||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.7.7.tgz",
|
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.7.7.tgz",
|
||||||
|
@ -2654,6 +2664,11 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ssr-window": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
|
||||||
|
},
|
||||||
"node_modules/strip-ansi": {
|
"node_modules/strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
@ -2702,6 +2717,29 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swiper": {
|
||||||
|
"version": "8.4.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/swiper/-/swiper-8.4.7.tgz",
|
||||||
|
"integrity": "sha512-VwO/KU3i9IV2Sf+W2NqyzwWob4yX9Qdedq6vBtS0rFqJ6Fa5iLUJwxQkuD4I38w0WDJwmFl8ojkdcRFPHWD+2g==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/swiperjs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "open_collective",
|
||||||
|
"url": "http://opencollective.com/swiper"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"dom7": "^4.0.4",
|
||||||
|
"ssr-window": "^4.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/text-table": {
|
"node_modules/text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
|
@ -3016,6 +3054,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-awesome-swiper": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-awesome-swiper/-/vue-awesome-swiper-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-mWjFJzUqA4lG+DmsmibvMpoiBnl+IH2SSeiiQ3i5M0t1y9FknTxnGT0DsMb2YdJLgjYMEK3sYOWzqgLnZMH8Lg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"swiper": "^7.0.0 || ^8.0.0",
|
||||||
|
"vue": "3.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue-eslint-parser": {
|
"node_modules/vue-eslint-parser": {
|
||||||
"version": "9.4.3",
|
"version": "9.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build:prod": "vite build",
|
"build:prod": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,9 @@
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"element-plus": "^2.7.7",
|
"element-plus": "^2.7.7",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
|
"swiper": "^8.4.7",
|
||||||
"vue": "^3.4.29",
|
"vue": "^3.4.29",
|
||||||
|
"vue-awesome-swiper": "^5.0.1",
|
||||||
"vue-router": "^4.3.3"
|
"vue-router": "^4.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -8,4 +8,7 @@ import { RouterView } from 'vue-router'
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
img{
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import http from "@/utils/http";
|
import http from "@/utils/http";
|
||||||
|
import keyboard from "uview-ui/libs/config/props/keyboard";
|
||||||
//获取题目
|
//获取题目
|
||||||
export const getQuestion= (type)=>{
|
export const getQuestion= (type)=>{
|
||||||
if(type==null||type==undefined){
|
if(type==null||type==undefined){
|
||||||
|
@ -47,3 +48,20 @@ export const validationAnswer = ({questionId,answer})=>{
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export const answered = (questionId)=>{
|
||||||
|
return http({
|
||||||
|
url:"/question/answered",
|
||||||
|
method:"get",
|
||||||
|
params:{
|
||||||
|
questionId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const searchQuestion = (data)=>{
|
||||||
|
return http({
|
||||||
|
url:"/search",
|
||||||
|
method:"get",
|
||||||
|
params:data
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,16 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="topicInfoBox">
|
<div class="topicInfoBox">
|
||||||
<div class="introduce title">
|
<!-- <el-image :src="question.questionImage" style="width: 80%;pointer-events: none;"></el-image> -->
|
||||||
[{{ props.type=="select"?"选择题":"填空题" }}]{{ props.introduce }}
|
<!-- <div class="introduce title">
|
||||||
|
[{{ props.type == "select" ? "选择题" : "填空题" }}]{{ props.introduce }}
|
||||||
</div>
|
</div>
|
||||||
<div class="introduce tag">
|
<div class="introduce tag">
|
||||||
<el-tag v-for="itme in props.tags" :key="itme.name" type="primary">{{ itme.name}}</el-tag>
|
<el-tag v-for="itme in props.tags" :key="itme.name" type="primary">{{
|
||||||
|
itme.name
|
||||||
|
}}</el-tag
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="introduce hod">
|
<div class="introduce hod" >
|
||||||
{{ props.topicTitle }}
|
<div v-html="props.topicTitle" style="width: 400px;">
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="introduce">
|
<div class="introduce">
|
||||||
<el-radio-group v-if="props.type!='fill_topic'" v-model="radio">
|
<el-radio-group v-if="props.type != 'fill_topic'" v-model="radio">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="itme in topicSelect"
|
v-for="itme in topicSelect"
|
||||||
:key="itme.key"
|
:key="itme.key"
|
||||||
|
@ -18,19 +24,25 @@
|
||||||
>{{ itme.key + "." + itme.name }}</el-radio
|
>{{ itme.key + "." + itme.name }}</el-radio
|
||||||
>
|
>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-input v-else v-model="radio" type="textarea" :rows="2" placeholder="请输入内容" ></el-input>
|
<el-input
|
||||||
|
v-else
|
||||||
|
v-model="radio"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
></el-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="introduce">
|
-->
|
||||||
<el-button v-if="radio != null" type="success" @click="tupClick">提交</el-button>
|
<div class="button">
|
||||||
|
<el-button type="primary" @click="tupClick"
|
||||||
|
>作答</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="native.isAnswer" class="introduce jg">
|
<!-- <el-button type="primary" style="z-index: 9;" @click="show=true">查看答案</el-button>
|
||||||
已作答,<span v-if="!native.correct" style="color: red;">答案错误</span>
|
<div class="introduce jg" v-if="show">
|
||||||
<span v-else style="color: rgb(17, 255, 0);">答案正确</span><br>
|
|
||||||
<br>
|
|
||||||
<span>你的答案:{{ native.userAnswer }}</span><br>
|
|
||||||
<br>
|
|
||||||
<span>正确答案:{{ ArrayToString(native.correctAnswer) }}</span>
|
<span>正确答案:{{ ArrayToString(native.correctAnswer) }}</span>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -38,7 +50,8 @@ import { onMounted, ref } from "vue";
|
||||||
import { useTopicStore } from "@/stores/topic.js";
|
import { useTopicStore } from "@/stores/topic.js";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
const topStore = useTopicStore();
|
const topStore = useTopicStore();
|
||||||
const radio = ref('');
|
const radio = ref("");
|
||||||
|
const show = ref(false);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: { type: Number, default: null },
|
id: { type: Number, default: null },
|
||||||
videoUrl: { type: String, default: null },
|
videoUrl: { type: String, default: null },
|
||||||
|
@ -48,75 +61,90 @@ const props = defineProps({
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
native:{
|
native: {
|
||||||
type:Object,
|
type: Object,
|
||||||
default:()=>{
|
default: () => {
|
||||||
return {
|
return {
|
||||||
isAnswer:false,
|
isAnswer: false,
|
||||||
analysis:'解析',
|
analysis: "解析",
|
||||||
correctAnswer:'正确答案',
|
correctAnswer: "正确答案",
|
||||||
//是否答对
|
//是否答对
|
||||||
correct:false,
|
correct: false,
|
||||||
}
|
};
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
question: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
type: { type: String, default: null },
|
type: { type: String, default: null },
|
||||||
topicTitle: { type: String, default: "题目" },
|
topicTitle: { type: String, default: "题目" },
|
||||||
introduce: { type: String, default: "介绍" },
|
introduce: { type: String, default: "介绍" },
|
||||||
tags: { type: Array, default: null },
|
tags: { type: Array, default: null },
|
||||||
});
|
});
|
||||||
const tupClick=async()=>{
|
const tupClick = async () => {
|
||||||
if(radio.value==null){
|
|
||||||
ElMessage.error("请选择答案");
|
let res = await topStore.submitAnswer(radio.value);
|
||||||
}
|
|
||||||
console.log("radio.value",radio.value)
|
};
|
||||||
let res=await topStore.submitAnswer(radio.value);
|
const ArrayToString = (arr) => {
|
||||||
console.log("res",res);''
|
if (arr instanceof Array) {
|
||||||
}
|
|
||||||
const ArrayToString=(arr)=>{
|
|
||||||
if(arr instanceof Array){
|
|
||||||
return arr.join(",");
|
return arr.join(",");
|
||||||
}else if(arr instanceof Object){
|
} else if (arr instanceof Object) {
|
||||||
return arr.toSting();
|
return arr.toSting();
|
||||||
}else{
|
} else {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
const topicSelect = ref([]);
|
const topicSelect = ref([]);
|
||||||
|
console.log("props.native", props.question);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
topicSelect.value = props.topicList;
|
topicSelect.value = props.topicList;
|
||||||
radio.value=props.native.userAnswer?props.native.userAnswer:null;
|
radio.value = props.native.userAnswer ? props.native.userAnswer : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.button{
|
||||||
|
z-index: 99;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
.topicInfoBox {
|
.topicInfoBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-family: "KaiTi"
|
font-family: "KaiTi";
|
||||||
}
|
}
|
||||||
.introduce {
|
.introduce {
|
||||||
|
z-index: 9;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
img {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.title{
|
.title {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
margin-top:30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
.tag{
|
.tag {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
.jg{
|
.jg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 17vw;
|
height: 17vw;
|
||||||
box-sizing:border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 19%;
|
padding-top: 19%;
|
||||||
padding-left: 23%;
|
padding-left: 23%;
|
||||||
font-family: "黑体";
|
font-family: "黑体";
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
|
@ -127,4 +155,4 @@ onMounted(() => {
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="video-container">
|
<div class="video-container">
|
||||||
<video
|
<video
|
||||||
|
style="height: inherit;"
|
||||||
ref="videoRef"
|
ref="videoRef"
|
||||||
:src="props.src"
|
:src="props.src"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -49,8 +50,9 @@
|
||||||
.video-container {
|
.video-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 640px; /* 可以根据需要调整 */
|
max-width: 100%; /* 可以根据需要调整 */
|
||||||
/* margin: 0 auto; */
|
height: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|
|
@ -1,115 +1,141 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<div class="logo-box"><span class="loogText">Xuaua</span></div>
|
<div class="logo-box">
|
||||||
|
<span class="logo-text" v-if="pageType!='view'">Xuaua</span>
|
||||||
|
<span class="logo-text" v-else @click="goback">
|
||||||
|
|
||||||
|
<svg t="1724411009623" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6748" width="48" height="48"><path d="M512 65C264.66 65 65 264.66 65 512s199.66 447 447 447 447-199.66 447-447S759.34 65 512 65z m253.32 470.93h-0.8c-18.93 0.42-37.92 0-56.85 0H312.21l88.31 86.91 64.68 63.66c9.53 9.38 8.71 24.35 0 33.84s-24.91 8.79-33.84 0L407.69 697l-103.1-101.43-64.69-63.66c-9.28-9.14-9-24.69 0-33.84l23.52-23.88 103.15-104.74 64.79-65.79c9.38-9.53 24.35-8.71 33.84 0s8.79 24.91 0 33.84l-23.52 23.88q-51.57 52.38-103.15 104.74l-21.44 21.77c12.44 0 24.88 0.18 37.3 0.18h410.93c13.41 0 23.35 11 23.93 23.93s-11.41 23.93-23.93 23.93z" p-id="6749" fill="#e6e6e6"></path></svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-popover :width="700" trigger="click">
|
<div class="search-box">
|
||||||
<template #reference>
|
<div class="selectInput">
|
||||||
<div class="search-box">
|
<div>
|
||||||
<div class="selectInput">
|
<el-icon :size="20">
|
||||||
<div @click="selectClick">
|
<Search />
|
||||||
<el-icon :size="20" >
|
</el-icon>
|
||||||
<Search />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
<input type="text" placeholder="搜索关键词" v-model="type" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<input type="text" @click="goSearch" placeholder="搜索关键词" />
|
||||||
<TypeSelect @select="selectInput" :type="type"></TypeSelect>
|
</div>
|
||||||
</el-popover>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div @click="toUser" class="user-avatar">
|
<div @click="toUser" class="user-avatar">
|
||||||
<el-avatar :size="40" :src="useSotr.avatar" />{{ useSotr.username }}
|
<el-avatar :size="40" :src="user.avatar" />{{ user.nickname || "用户" }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// import {defineProps} from "vue"
|
import { useUserStore } from "@/stores/user.js";
|
||||||
import TypeSelect from "@/components/TypeSelect.vue";
|
|
||||||
import { debounceRef } from "@/utils/debounceRef";
|
|
||||||
import router from "@/router";
|
|
||||||
import { useTopicStore } from "@/stores/topic.js";
|
import { useTopicStore } from "@/stores/topic.js";
|
||||||
import {useUserStore } from "@/stores/user.js";
|
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import "element-plus/theme-chalk/el-message.css";
|
|
||||||
const useSotr=useUserStore();
|
|
||||||
const topStore = useTopicStore();
|
|
||||||
// import { ref } from 'vue'
|
|
||||||
import { Search } from "@element-plus/icons-vue";
|
import { Search } from "@element-plus/icons-vue";
|
||||||
|
import router from "@/router";
|
||||||
|
import { debounceRef } from "@/utils/debounceRef";
|
||||||
|
import {computed, defineProps,defineEmits} from "vue"
|
||||||
|
const useSotr = useUserStore();
|
||||||
|
const emit = defineEmits(["back"])
|
||||||
|
const user = computed(() => {
|
||||||
|
return useSotr.user;
|
||||||
|
});
|
||||||
|
const topStore = useTopicStore();
|
||||||
const type = debounceRef("", 300);
|
const type = debounceRef("", 300);
|
||||||
const selectInput = (a) => {
|
const {pageType} = defineProps({
|
||||||
type.value = a;
|
pageType:{
|
||||||
};
|
type:String,
|
||||||
const toUser=()=>{
|
default:''
|
||||||
router.push({
|
}
|
||||||
path:"/user"
|
})
|
||||||
})
|
function goback(){
|
||||||
|
// router.go(-1);
|
||||||
|
emit("back")
|
||||||
}
|
}
|
||||||
const selectClick=()=>{
|
const toUser = () => {
|
||||||
// console.log("点击")
|
router.push({
|
||||||
console.log("123",useSotr)
|
path: "/user",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const goSearch = () => {
|
||||||
|
router.replace({
|
||||||
|
path: "/search",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectClick = () => {
|
||||||
topStore.loadData(type.value);
|
topStore.loadData(type.value);
|
||||||
ElMessage({ message: "已切换标签", type: "success" });
|
ElMessage({ message: "已切换标签", type: "success" });
|
||||||
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.selectInput {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 7px 10px;
|
|
||||||
border: 2px #000000 solid;
|
|
||||||
border-radius: 30px;
|
|
||||||
input {
|
|
||||||
background-color: #00000000; /* 透明背景 */
|
|
||||||
border: none; /* 无边框 */
|
|
||||||
outline: none; /* 去除聚焦时的轮廓 */
|
|
||||||
padding: 0; /* 无内边距 */
|
|
||||||
margin: 0; /* 无外边距 */
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.nav {
|
.nav {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
background-color: #fff;
|
background: linear-gradient(135deg, #409eff, #66b1ff);
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
// justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 0 20px;
|
||||||
|
|
||||||
.logo-box {
|
.logo-box {
|
||||||
margin-top: 11px;
|
|
||||||
margin-left: 52px;
|
margin-left: 52px;
|
||||||
margin-bottom: 11px;
|
.logo-text {
|
||||||
}
|
font-size: 30px;
|
||||||
.input-with-select {
|
font-weight: bold;
|
||||||
border-radius: 30px;
|
color: #ffffff;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-box {
|
.search-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 210px;
|
margin-left: 30px;
|
||||||
border-radius: 30px;
|
margin-right: auto;
|
||||||
overflow: hidden;
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background: #fefefe;
|
|
||||||
// .search-input{
|
|
||||||
// width: 400px;
|
|
||||||
// height: 38px;
|
|
||||||
// border-radius: 30px;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
div {
|
|
||||||
|
.selectInput {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
padding: 7px 15px;
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
border-radius: 30px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
transition: background-color 0.3s ease, border-color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
border-color: #dcdfe6;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
&::placeholder {
|
||||||
|
color: #dcdfe6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-avatar {
|
.user-avatar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 2%;
|
right: 20px;
|
||||||
}
|
display: flex;
|
||||||
.loogText {
|
align-items: center;
|
||||||
font-size: 30px;
|
cursor: pointer;
|
||||||
margin-left: 10px;
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
39
src/main.js
39
src/main.js
|
@ -1,21 +1,26 @@
|
||||||
import './assets/main.css'
|
import { createApp } from 'vue';
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
import ElementPlus from 'element-plus';
|
||||||
|
import 'element-plus/dist/index.css';
|
||||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import router from './router';
|
||||||
|
import './assets/main.css';
|
||||||
|
import 'swiper/css';
|
||||||
|
const app = createApp(App);
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import VueAwesomeSwiper from 'vue-awesome-swiper'
|
||||||
import { createPinia } from 'pinia'
|
import 'swiper/swiper-bundle.css'
|
||||||
import ElementPlus from 'element-plus'
|
|
||||||
import 'element-plus/dist/index.css'
|
|
||||||
import App from './App.vue'
|
|
||||||
import router from './router'
|
|
||||||
// 如果您正在使用CDN引入,请删除下面一行。
|
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
const app = createApp(App)
|
// import 'swiper/swiper-bundle.css'
|
||||||
|
app.use(VueAwesomeSwiper)
|
||||||
|
app.use(createPinia());
|
||||||
|
app.use(router);
|
||||||
|
app.use(ElementPlus);
|
||||||
|
|
||||||
app.use(createPinia())
|
// Register Element Plus icons globally
|
||||||
app.use(router)
|
Object.entries(ElementPlusIconsVue).forEach(([key, component]) => {
|
||||||
app.use(ElementPlus)
|
app.component(key, component);
|
||||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
});
|
||||||
app.component(key, component)
|
|
||||||
}
|
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app');
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router'
|
||||||
import TokenService from '@/utils/token'
|
import TokenService from '@/utils/token'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(import.meta.env.BASE_URL),
|
history: createWebHashHistory(),
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
@ -18,6 +18,10 @@ const router = createRouter({
|
||||||
path: '/user',
|
path: '/user',
|
||||||
name: 'USER',
|
name: 'USER',
|
||||||
component: () => import('@/views/user/index.vue')
|
component: () => import('@/views/user/index.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path:"/search",
|
||||||
|
component:()=>import('@/views/search/index.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,176 +1,261 @@
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from "vue";
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from "pinia";
|
||||||
import { getQuestionByTagName ,validationAnswer} from '@/api/question/question'
|
import {
|
||||||
import {collect, cancelCollect ,getCollectList} from '@/api/collect/collect'
|
getQuestionByTagName,
|
||||||
|
validationAnswer,
|
||||||
|
getQuestion,
|
||||||
|
answered,
|
||||||
|
} from "@/api/question/question";
|
||||||
|
import { collect, cancelCollect, getCollectList } from "@/api/collect/collect";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import "element-plus/theme-chalk/el-message.css";
|
import "element-plus/theme-chalk/el-message.css";
|
||||||
|
import router from "@/router";
|
||||||
|
import { ElLoading } from 'element-plus'
|
||||||
// import { fa } from 'element-plus/es/locale';
|
// import { fa } from 'element-plus/es/locale';
|
||||||
export const useTopicStore = defineStore('useTopicStore', () => {
|
export const useTopicStore = defineStore("useTopicStore", () => {
|
||||||
//当前标签
|
//当前标签
|
||||||
const tagName = ref('');
|
const tagName = ref("");
|
||||||
//当前索引
|
//当前索引
|
||||||
const index = ref(1);
|
const index = ref(0);
|
||||||
//题目列表
|
//题目列表
|
||||||
const Topics=ref([]);
|
const Topics = ref([]);
|
||||||
//当前题目
|
//当前题目
|
||||||
const Topic=computed(()=>{
|
const Topic = computed(() => {
|
||||||
return Topics.value[index.value-1];
|
return Topics.value[index.value - 1];
|
||||||
|
});
|
||||||
|
//收藏列表
|
||||||
|
const collectTopics = ref([]);
|
||||||
|
//收藏列表id
|
||||||
|
const collectTopicIds = computed(() => {
|
||||||
|
return collectTopics.value.map((item) => item.id);
|
||||||
|
});
|
||||||
|
const count = computed(() => Topics.value.length);
|
||||||
|
const init = () => {
|
||||||
|
index.value = 0;
|
||||||
|
if (Topics.value.length == 0) {
|
||||||
|
CollectList();
|
||||||
|
getData();
|
||||||
|
console.log("刷新数据");
|
||||||
|
} else {
|
||||||
|
console.log("已存在");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setQuestion = (question) => {
|
||||||
|
CollectList();
|
||||||
|
Topics.value = [];
|
||||||
|
Topic.value = question;
|
||||||
|
Topics.value.push({
|
||||||
|
...question,
|
||||||
|
isCollect: collectTopicIds.value.includes(question.id),
|
||||||
});
|
});
|
||||||
//收藏列表
|
};
|
||||||
const collectTopics=ref([]);
|
|
||||||
//收藏列表id
|
|
||||||
const collectTopicIds=computed(()=>{
|
|
||||||
return collectTopics.value.map(item=>item.id);
|
|
||||||
})
|
|
||||||
const count = computed(()=>Topics.value.length);
|
|
||||||
const init=()=>{
|
|
||||||
if(Topics.value.length==0){
|
|
||||||
CollectList();
|
|
||||||
getData();
|
|
||||||
console.log("刷新数据");
|
|
||||||
}else{
|
|
||||||
console.log("已存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//设置标签
|
|
||||||
const setTagName=(name)=>{
|
|
||||||
tagName.value=name;
|
|
||||||
}
|
|
||||||
//根据传入标签情况判断是刷新还是加载
|
|
||||||
const loadData=async(name)=>{
|
|
||||||
if(name===tagName.value){
|
|
||||||
await getData();
|
|
||||||
}else{
|
|
||||||
setTagName(name)
|
|
||||||
await refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//刷新
|
|
||||||
const refresh=async()=>{
|
|
||||||
clear();
|
|
||||||
let res=await getQuestionByTagName(tagName.value);
|
|
||||||
if(res.code==200){
|
|
||||||
res.data=res.data.map(e=>{
|
|
||||||
return {
|
|
||||||
...e,
|
|
||||||
isCollect:collectTopicIds.value.includes(e.id),
|
|
||||||
|
|
||||||
}})
|
const setQuestions = (questions,item) => {
|
||||||
Topics.value=res.data;
|
CollectList();
|
||||||
index.value=Topics.value.length>0?1:0;
|
index.value =0
|
||||||
}
|
Topics.value = [];
|
||||||
|
Topic.value = item;
|
||||||
|
questions.forEach(e => {
|
||||||
|
Topics.value.push({
|
||||||
|
...e,
|
||||||
|
isCollect: collectTopicIds.value.includes(e.id),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
//获取题目
|
||||||
|
//设置标签
|
||||||
|
const setTagName = (name) => {
|
||||||
|
tagName.value = name;
|
||||||
|
};
|
||||||
|
//根据传入标签情况判断是刷新还是加载
|
||||||
|
const loadData = async (name) => {
|
||||||
|
if (name === tagName.value) {
|
||||||
|
await getData();
|
||||||
|
} else {
|
||||||
|
setTagName(name);
|
||||||
|
await refresh();
|
||||||
}
|
}
|
||||||
//加载数据
|
};
|
||||||
const getData=async()=>{
|
//刷新
|
||||||
let res=await getQuestionByTagName(tagName.value);
|
const refresh = async () => {
|
||||||
if(res.code==200){
|
clear();
|
||||||
res.data=res.data.map(e=>{
|
let res = await getQuestion("refresh");
|
||||||
return {
|
if (res.code == 200) {
|
||||||
...e,
|
if (res.data.length == 0) {
|
||||||
isCollect:collectTopicIds.value.includes(e.id),
|
ElMessage({ message: "题库为空你已经打完所有题目", type: "warning" });
|
||||||
|
return;
|
||||||
}})
|
}
|
||||||
Topics.value=[...Topics.value,...res.data];
|
res.data = res.data.map((e) => {
|
||||||
}
|
return {
|
||||||
|
...e,
|
||||||
|
// isCollect: collectTopicIds.value.includes(e.id),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
Topics.value = res.data;
|
||||||
|
index.value = Topics.value.length > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
//清空数据
|
};
|
||||||
const clear=()=>{
|
//加载数据
|
||||||
index.value=0;
|
const getData = async () => {
|
||||||
Topics.value=[];
|
const loadingInstance = ElLoading.service()
|
||||||
collectTopics.value=[];
|
let res = await getQuestion();
|
||||||
|
if (res.code == 200) {
|
||||||
}
|
if (res.data.length == 0) {
|
||||||
//提交答案
|
ElMessage({ message: "题库为空你已经打完所有题目", type: "warning" });
|
||||||
const submitAnswer=async(answer)=>{
|
res.data = [
|
||||||
//先判断是否已经答过
|
{
|
||||||
// if(Topic.value.isAnswer){
|
id: 0,
|
||||||
// ElMessage({ message: "已经做过了", type: "warning" });
|
question: "没有题目了",
|
||||||
// return;
|
analysis: "没有题目了",
|
||||||
// }
|
correctAnswer: "没有题目了",
|
||||||
console.log(Topic.value)
|
correct: false,
|
||||||
let res=await validationAnswer({questionId:Topic.value.id,answer});
|
userAnswer: "没有题目了",
|
||||||
console.log(res);
|
isAnswer: false,
|
||||||
if(res.code==200){
|
isCollect: false,
|
||||||
setAnswer({
|
},
|
||||||
isAnswer:true,
|
];
|
||||||
analysis:res.data.analysis,
|
}
|
||||||
correctAnswer:res.data.correctAnswer?res.data.correctAnswer:answer,
|
res.data = res.data.map((e) => {
|
||||||
correct:res.data.correct,
|
return {
|
||||||
userAnswer:answer
|
...e,
|
||||||
});
|
// isCollect: collectTopicIds.value.includes(e.id),
|
||||||
}
|
};
|
||||||
|
});
|
||||||
|
Topics.value = [...Topics.value, ...res.data];
|
||||||
|
loadingInstance.close()
|
||||||
|
|
||||||
}
|
}
|
||||||
//设置答题情况
|
};
|
||||||
const setAnswer=({isAnswer,analysis,userAnswer,correctAnswer,correct})=>{
|
//清空数据
|
||||||
Topics.value[index.value-1]={
|
const clear = () => {
|
||||||
...Topic.value,
|
index.value = 0;
|
||||||
isAnswer,
|
Topics.value = [];
|
||||||
analysis,
|
collectTopics.value = [];
|
||||||
correctAnswer,
|
};
|
||||||
correct,
|
//提交答案
|
||||||
userAnswer
|
const submitAnswer = async (answer) => {
|
||||||
}
|
//先判断是否已经答过
|
||||||
|
// if(Topic.value.isAnswer){
|
||||||
|
// ElMessage({ message: "已经做过了", type: "warning" });
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// console.log(Topic.value);
|
||||||
|
// let res = await validationAnswer({ questionId: Topic.value.id, answer });
|
||||||
|
// console.log(res);
|
||||||
|
// if (res.code == 200) {
|
||||||
|
// setAnswer({
|
||||||
|
// isAnswer: true,
|
||||||
|
// analysis: res.data.analysis,
|
||||||
|
// correctAnswer: res.data.correctAnswer ? res.data.correctAnswer : answer,
|
||||||
|
// correct: res.data.correct,
|
||||||
|
// userAnswer: answer,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
let res = await answered(Topic.value.id);
|
||||||
|
ElMessage({ message: res.msg, type: "info" });
|
||||||
|
refresh();
|
||||||
|
};
|
||||||
|
//设置答题情况
|
||||||
|
const setAnswer = ({
|
||||||
|
isAnswer,
|
||||||
|
analysis,
|
||||||
|
userAnswer,
|
||||||
|
correctAnswer,
|
||||||
|
correct,
|
||||||
|
}) => {
|
||||||
|
Topics.value[index.value - 1] = {
|
||||||
|
...Topic.value,
|
||||||
|
isAnswer,
|
||||||
|
analysis,
|
||||||
|
correctAnswer,
|
||||||
|
correct,
|
||||||
|
userAnswer,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//收藏题目
|
||||||
|
const Collect = async () => {
|
||||||
|
console.log("执行");
|
||||||
|
let res;
|
||||||
|
if (isCollect()) {
|
||||||
|
res = await cancelCollect(Topic.value.id);
|
||||||
|
if (res.code == 200) {
|
||||||
|
ElMessage({ message: "取消收藏", type: "info" });
|
||||||
|
Topics.value[index.value - 1].isCollect = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = await collect(Topic.value.id);
|
||||||
|
if (res.code == 200) {
|
||||||
|
ElMessage({ message: "收藏成功", type: "info" });
|
||||||
|
Topics.value[index.value - 1].isCollect = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//收藏题目
|
await CollectList();
|
||||||
const Collect=async()=>{
|
};
|
||||||
console.log("执行")
|
//上一题
|
||||||
let res;
|
const prev = () => {
|
||||||
if(isCollect()){
|
if (index.value >= 1) {
|
||||||
res=await cancelCollect(Topic.value.id);
|
index.value--;
|
||||||
if(res.code==200){
|
return true;
|
||||||
ElMessage({ message: "取消收藏", type: "info" });
|
|
||||||
Topics.value[index.value-1].isCollect=false;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
res= await collect(Topic.value.id);
|
|
||||||
if(res.code==200){
|
|
||||||
ElMessage({ message: "收藏成功", type: "info" });
|
|
||||||
Topics.value[index.value-1].isCollect=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await CollectList();
|
|
||||||
}
|
}
|
||||||
//上一题
|
return false;
|
||||||
const prev=()=>{
|
};
|
||||||
if(index.value>=1){
|
//下一题
|
||||||
index.value--;
|
const next = () => {
|
||||||
return true;
|
index.value++;
|
||||||
}
|
if (index.value > count.value) {
|
||||||
return false;
|
index.value = count.value;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
//下一题
|
const type = router.currentRoute.value.query.type;
|
||||||
const next=()=>{
|
if (type == "view") {
|
||||||
index.value++;
|
return true;
|
||||||
if(index.value>count.value){
|
|
||||||
index.value=count.value;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(index.value==count.value){
|
|
||||||
getData();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
//获取收藏题目列表
|
if (index.value == count.value) {
|
||||||
const CollectList=async()=>{
|
getData();
|
||||||
let res=await getCollectList();
|
|
||||||
if(res.code==200){
|
|
||||||
collectTopics.value=res.data.map(item=>item.questionVo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//判断是否收藏
|
return true;
|
||||||
const isCollect=()=>{
|
};
|
||||||
if(count.value==0){
|
//获取收藏题目列表
|
||||||
return false;
|
const CollectList = async () => {
|
||||||
}
|
let res = await getCollectList();
|
||||||
console.log("123",Topic.value,index.value)
|
if (res.code == 200) {
|
||||||
return collectTopicIds.value.includes(Topic.value.id);
|
collectTopics.value = res.data.map((item) => item.questionVo);
|
||||||
}
|
}
|
||||||
onMounted(()=>{
|
};
|
||||||
init();
|
//判断是否收藏
|
||||||
})
|
const isCollect = () => {
|
||||||
return { index, Topics, count,collectTopics ,collectTopicIds,Topic,
|
if (count.value == 0) {
|
||||||
setAnswer,loadData,setTagName,refresh,submitAnswer,Collect,isCollect,clear,getData,
|
return false;
|
||||||
prev,next,CollectList,init}
|
}
|
||||||
})
|
console.log("123", Topic.value, index.value);
|
||||||
|
return collectTopicIds.value.includes(Topic.value.id);
|
||||||
|
};
|
||||||
|
// onMounted(() => {
|
||||||
|
// init();
|
||||||
|
// });
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
Topics,
|
||||||
|
count,
|
||||||
|
collectTopics,
|
||||||
|
collectTopicIds,
|
||||||
|
Topic,
|
||||||
|
setAnswer,
|
||||||
|
loadData,
|
||||||
|
setTagName,
|
||||||
|
refresh,
|
||||||
|
submitAnswer,
|
||||||
|
Collect,
|
||||||
|
isCollect,
|
||||||
|
clear,
|
||||||
|
getData,
|
||||||
|
prev,
|
||||||
|
next,
|
||||||
|
CollectList,
|
||||||
|
init,
|
||||||
|
setQuestion,
|
||||||
|
setQuestions
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted, reactive } from 'vue'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { getUserInfo } from '../api/user/user'
|
import { getUserInfo } from '../api/user/user'
|
||||||
export const useUserStore = defineStore('useUserStore', () => {
|
// export const useUserStore = defineStore('useUserStore', () => {
|
||||||
//用户头像
|
// state: () => ({
|
||||||
const avatar = ref('')
|
// user:{}
|
||||||
const username = ref('')
|
// }),
|
||||||
//手机号
|
// actions: {
|
||||||
const phone = ref('')
|
|
||||||
//备注
|
// },
|
||||||
const remark = ref('')
|
// })
|
||||||
//获取用户信息
|
|
||||||
const UserInfo = async() => {
|
export const useUserStore = defineStore('useUserStore', {
|
||||||
let res= await getUserInfo();
|
state: () => ({
|
||||||
console.log("用户信息",res)
|
user:{}
|
||||||
if(res.code==200){
|
}),
|
||||||
avatar.value=res.data.avatar;
|
actions: {
|
||||||
username.value=res.data.username;
|
UserInfo(){
|
||||||
phone.value=res.data.phone;
|
getUserInfo().then(res => {
|
||||||
remark.value=res.data.remark;
|
this.user = res.data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
onMounted(()=>{
|
})
|
||||||
UserInfo();
|
|
||||||
})
|
|
||||||
return { avatar, username,phone,remark,UserInfo}
|
|
||||||
})
|
|
|
@ -1,76 +1,84 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="homeBox">
|
<div ref="topicInfoRef" class="scroll-container">
|
||||||
<div>
|
<div
|
||||||
<xuaua-header></xuaua-header>
|
ref="topicInfoItemRef"
|
||||||
</div>
|
:style="{
|
||||||
<div class="main">
|
height: '100%',
|
||||||
<div class="mainBox">
|
width: '100%',
|
||||||
<div class="topicInfo" ref="topicInfoRef" @click="huadong">
|
transition: '0.7s',
|
||||||
<div
|
marginTop: top,
|
||||||
ref="topicInfoItemRef"
|
}"
|
||||||
style="
|
>
|
||||||
position: absolute;
|
<div
|
||||||
height: 100%;
|
v-for="item in questionList"
|
||||||
width: 100%;
|
:key="item.id"
|
||||||
transition: 0.7s;
|
style="overflow: hidden"
|
||||||
"
|
class="homeBox"
|
||||||
:style="'top:' + top"
|
>
|
||||||
>
|
<div>
|
||||||
<div
|
<xuaua-header :page-type="PageType" @back="PageRest()"></xuaua-header>
|
||||||
v-for="itme in topStore.Topics"
|
|
||||||
:key="itme.id"
|
|
||||||
class="topicInfoItem"
|
|
||||||
>
|
|
||||||
<TopicBox
|
|
||||||
:id="itme.id"
|
|
||||||
:videoUrl="itme.videoUrl"
|
|
||||||
:introduce="itme.introduce"
|
|
||||||
:tags="itme.tags"
|
|
||||||
:topicTitle="itme.topicTitle"
|
|
||||||
:type="itme.type"
|
|
||||||
:topicList="itme.xuauaQuestionAnswerList"
|
|
||||||
:native="itme"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="topicAnswer">
|
<div class="main">
|
||||||
<div class="answerNav">
|
<div class="mainBox">
|
||||||
<div style="flex: 1;">
|
<div
|
||||||
<el-tabs
|
class="topicInfo"
|
||||||
v-model="activeName"
|
:style="{ backgroundImage: `url(${item.questionImage})` }"
|
||||||
class="demo-tabs"
|
@click="huadong"
|
||||||
@tab-change="handleClick"
|
>
|
||||||
>
|
<div class="topicInfoItem">
|
||||||
<el-tab-pane label="视频" name="视频"></el-tab-pane>
|
<TopicBox
|
||||||
<el-tab-pane label="解析" name="解析"></el-tab-pane>
|
:id="item.id"
|
||||||
</el-tabs>
|
:question="item"
|
||||||
|
:videoUrl="item.videoUrl"
|
||||||
|
:introduce="item.introduce"
|
||||||
|
:tags="item.tags"
|
||||||
|
:topicTitle="item.topicTitle"
|
||||||
|
:type="item.type"
|
||||||
|
:topicList="item.xuauaQuestionAnswerList"
|
||||||
|
:native="item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="topicAnswer">
|
||||||
<div class="StarIcon" @click="addCollect">
|
<div class="answerNav">
|
||||||
<el-icon
|
<div style="width: 80%; display: flex; justify-content: center">
|
||||||
v-if="topStore.Topic?.isCollect == true"
|
<el-tabs
|
||||||
|
style="margin: 0 auto"
|
||||||
:size="30"
|
v-model="activeName"
|
||||||
color="#FEE082"
|
class="demo-tabs"
|
||||||
>
|
@tab-change="handleClick"
|
||||||
<!-- <Star /> -->
|
>
|
||||||
<StarFilled />
|
<el-tab-pane label="视频" name="视频"></el-tab-pane>
|
||||||
</el-icon>
|
<el-tab-pane label="解析" name="解析"></el-tab-pane>
|
||||||
<el-icon v-else :size="30" color="#2B2B2B">
|
</el-tabs>
|
||||||
<Star />
|
</div>
|
||||||
<!-- <StarFilled /> -->
|
<div class="StarIcon" @click="addCollect">
|
||||||
</el-icon>
|
<el-icon
|
||||||
{{ topStore.Topic?.isCollect == true ? "已" : "未" }}收藏
|
v-if="topStore.Topic?.isCollect"
|
||||||
|
:size="30"
|
||||||
|
color="#FEE082"
|
||||||
|
>
|
||||||
|
<StarFilled />
|
||||||
|
</el-icon>
|
||||||
|
<el-icon v-else :size="30" color="#2B2B2B">
|
||||||
|
<Star />
|
||||||
|
</el-icon>
|
||||||
|
{{ topStore.Topic?.isCollect ? "已" : "未" }}收藏
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="answerInfo">
|
||||||
|
<VideoBox
|
||||||
|
v-if="activeName === '视频'"
|
||||||
|
:src="topStore.Topic?.videoUrl"
|
||||||
|
></VideoBox>
|
||||||
|
<div
|
||||||
|
class="jiexi"
|
||||||
|
v-else
|
||||||
|
v-html="topStore.Topic?.analysis"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="answerInfo">
|
|
||||||
<VideoBox
|
|
||||||
v-if="activeName == '视频'"
|
|
||||||
:src="topStore.Topic?.videoUrl"
|
|
||||||
></VideoBox>
|
|
||||||
<div class="jiexi" v-else>{{ topStore.Topic.analysis }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,198 +86,252 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed } from "vue";
|
import { ref, onMounted, computed, watch, onUnmounted } from "vue";
|
||||||
import xuauaHeader from "@/components/Xuaua_header.vue";
|
import xuauaHeader from "@/components/Xuaua_header.vue";
|
||||||
import TopicBox from "@/components/TopicBox.vue";
|
import TopicBox from "@/components/TopicBox.vue";
|
||||||
import VideoBox from "@/components/VideoBox.vue";
|
import VideoBox from "@/components/VideoBox.vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import "element-plus/theme-chalk/el-message.css";
|
|
||||||
import { useTopicStore } from "@/stores/topic.js";
|
import { useTopicStore } from "@/stores/topic.js";
|
||||||
import { debounce } from '@/utils/debounceRef'
|
import { debounce } from "@/utils/debounceRef";
|
||||||
|
import router from "@/router";
|
||||||
|
import { useUserStore } from "@/stores/user";
|
||||||
|
const PageType = ref("home");
|
||||||
const topicInfoItemRef = ref(null);
|
const topicInfoItemRef = ref(null);
|
||||||
|
const topicInfoRef = ref(null);
|
||||||
const topStore = useTopicStore();
|
const topStore = useTopicStore();
|
||||||
const activeName = ref("视频");
|
const activeName = ref("视频");
|
||||||
let mouseDown = false;
|
let mouseDown = false;
|
||||||
let lastY = null;
|
let lastY = null;
|
||||||
let currentY = null;
|
let currentY = null;
|
||||||
|
const questionList = computed(() => {
|
||||||
|
return topStore.Topics;
|
||||||
|
});
|
||||||
const top = computed(() => {
|
const top = computed(() => {
|
||||||
const height = topicInfoItemRef?.value?.clientHeight || 0;
|
const height = topicInfoItemRef.value?.clientHeight || 0;
|
||||||
return `-${(topStore.index - 1 < 0 ? 0 : topStore.index - 1) * height}px`;
|
return `-${(topStore.index - 1 < 0 ? 0 : topStore.index - 1) * height}px`;
|
||||||
});
|
});
|
||||||
const isCollect = computed(() => {
|
|
||||||
return topStore.isCollect();
|
const isFlipping = ref(false);
|
||||||
});
|
|
||||||
const addCollect = () => {
|
const addCollect = () => {
|
||||||
debounce(()=>{
|
debounce(
|
||||||
// alert(1)
|
() => {
|
||||||
topStore.Collect();
|
topStore.Collect();
|
||||||
},500,true)();
|
},
|
||||||
|
500,
|
||||||
|
true
|
||||||
|
)();
|
||||||
};
|
};
|
||||||
document.addEventListener("mousedown", function (event) {
|
|
||||||
|
const setScrollY = (y) => {
|
||||||
|
if (topicInfoRef.value) {
|
||||||
|
topicInfoRef.value.scrollTop -= y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const flipPage = (y) => {
|
||||||
|
if (topicInfoRef.value) {
|
||||||
|
topicInfoRef.value.scrollTop = 0;
|
||||||
|
if (y < -80) {
|
||||||
|
if (!topStore.next()) {
|
||||||
|
ElMessage({ message: "没有更多了", type: "warning" });
|
||||||
|
}
|
||||||
|
isFlipping.value = true;
|
||||||
|
} else if (y > 80) {
|
||||||
|
if (!topStore.prev()) {
|
||||||
|
ElMessage({ message: "到顶了", type: "warning" });
|
||||||
|
}
|
||||||
|
isFlipping.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = (e) => {
|
||||||
|
// if (e === "解析" && !topStore.Topics[topStore.index - 1]?.isAnswer) {
|
||||||
|
// ElMessage({ message: "未作答不能查看解析", type: "warning" });
|
||||||
|
// setTimeout(() => {
|
||||||
|
// activeName.value = "视频";
|
||||||
|
// }, 1);
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMouseMove = (event) => {
|
||||||
|
const deltaY = event.clientY - currentY;
|
||||||
|
currentY = event.clientY;
|
||||||
|
setScrollY(deltaY);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", (event) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
lastY = event.clientY;
|
lastY = event.clientY;
|
||||||
currentY = event.clientY;
|
currentY = event.clientY;
|
||||||
document.addEventListener("mousemove", onMouseMove);
|
document.addEventListener("mousemove", onMouseMove);
|
||||||
});
|
});
|
||||||
// 鼠标移动时触发的事件
|
|
||||||
function onMouseMove(event) {
|
document.addEventListener("mouseup", (event) => {
|
||||||
if (mouseDown) {
|
|
||||||
let deltaY = event.clientY - currentY;
|
|
||||||
currentY = event.clientY;
|
|
||||||
setScrollY(deltaY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 鼠标松开时触发的事件
|
|
||||||
document.addEventListener("mouseup", function (event) {
|
|
||||||
mouseDown = false;
|
mouseDown = false;
|
||||||
let deltaY = event.clientY - lastY;
|
const deltaY = event.clientY - lastY;
|
||||||
console.log("变化", deltaY);
|
|
||||||
flipPage(deltaY);
|
flipPage(deltaY);
|
||||||
document.removeEventListener("mousemove", onMouseMove);
|
document.removeEventListener("mousemove", onMouseMove);
|
||||||
});
|
});
|
||||||
const topicInfoRef = ref(null);
|
|
||||||
const setScrollY = (y) => {
|
const preventScroll = (event) => {
|
||||||
if (topicInfoRef.value) {
|
event.preventDefault();
|
||||||
topicInfoRef.value.scrollTop = topicInfoRef.value.scrollTop - y;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const flipPage = (y) => {
|
|
||||||
if (topicInfoItemRef.value) {
|
function PageRest() {
|
||||||
topicInfoRef.value.scrollTop = 0;
|
const type = router.currentRoute.value.query.type;
|
||||||
if (y < -80) {
|
|
||||||
let is = topStore.next();
|
if (type == "view") {
|
||||||
if (!is) {
|
PageType.value = "home";
|
||||||
ElMessage({ message: "没有更多了", type: "warning" });
|
topStore.init();
|
||||||
}
|
router.back();
|
||||||
}
|
return;
|
||||||
else if (y > 80) {
|
|
||||||
let is = topStore.prev();
|
|
||||||
if (!is) {
|
|
||||||
ElMessage({ message: "到顶了", type: "warning" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
const handleClick = (e) => {
|
|
||||||
if (e == "解析" && !topStore.Topics[topStore.index-1].isAnswer) {
|
|
||||||
ElMessage({ message: "未作答不能查看解析", type: "warning" });
|
|
||||||
setTimeout(() => {
|
|
||||||
activeName.value = "视频";
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
|
||||||
topStore.init();
|
topStore.init();
|
||||||
|
router.replace({
|
||||||
|
path: "/",
|
||||||
|
});
|
||||||
|
|
||||||
|
// router.back()
|
||||||
|
}
|
||||||
|
|
||||||
|
function pageInit() {
|
||||||
|
useUserStore().UserInfo();
|
||||||
|
|
||||||
|
const type = router.currentRoute.value.query.type;
|
||||||
|
console.log(type);
|
||||||
|
if (type == "view") {
|
||||||
|
//判断是否是查看模式
|
||||||
|
console.log(questionList.value);
|
||||||
|
PageType.value = "view";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
topStore.init();
|
||||||
|
|
||||||
|
}
|
||||||
|
pageInit();
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener("wheel", onScroll, { passive: true });
|
||||||
|
|
||||||
|
document.addEventListener("wheel", preventScroll, { passive: false });
|
||||||
|
});
|
||||||
|
const onScroll = (event) => {
|
||||||
|
if (isFlipping.value) return;
|
||||||
|
|
||||||
|
const deltaY = event.deltaY;
|
||||||
|
flipPage(-deltaY);
|
||||||
|
};
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener("wheel", onScroll);
|
||||||
|
|
||||||
|
document.removeEventListener("wheel", preventScroll);
|
||||||
|
});
|
||||||
|
watch(isFlipping, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
setTimeout(() => {
|
||||||
|
isFlipping.value = false;
|
||||||
|
}, 700);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.scroll-container {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
.homeBox {
|
.homeBox {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-image: url("@/assets/image/loginback.jpg");
|
background-image: url("@/assets/image/loginback.jpg");
|
||||||
background-size: cover; // 背景图片铺满元
|
background-size: cover;
|
||||||
// background-position: center; // 背景图片居中显示
|
background-repeat: no-repeat;
|
||||||
background-repeat: no-repeat; // 背景图片不重复
|
transition: transform 0.7s;
|
||||||
.main {
|
transform-style: preserve-3d;
|
||||||
width: 100%;
|
}
|
||||||
//占满的剩余空间
|
|
||||||
flex: 1;
|
.main {
|
||||||
background-color: #ededed;
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
background-color: #ededed;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.mainBox {
|
||||||
|
width: 97%;
|
||||||
|
height: 97%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
align-items: center;
|
box-sizing: border-box;
|
||||||
.mainBox {
|
padding: 20px;
|
||||||
width: 97%;
|
|
||||||
height: 97%;
|
.topicInfo {
|
||||||
background-color: #fff;
|
width: 30%;
|
||||||
border-radius: 10px;
|
height: 100%;
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
justify-content: space-between;
|
// background-image: url("@/assets/image/tibg.jpg");
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
background-size: contain;
|
||||||
.topicInfo {
|
background-repeat: no-repeat;
|
||||||
// animation-duration: 2s;
|
background-position: center;
|
||||||
// animation-delay: 250ms;
|
|
||||||
width: 30%;
|
.topicInfoItem {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// background-color: #f0f9cc;
|
width: 100%;
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
background-image: url("@/assets/image/tibg.jpg");
|
|
||||||
background-size: cover; // 背景图片铺满元
|
|
||||||
// background-position: center; // 背景图片居中显示
|
|
||||||
background-repeat: no-repeat; // 背景图片不重复
|
|
||||||
background-position: left left;
|
|
||||||
.topicInfoItem {
|
|
||||||
// top: -10px;
|
|
||||||
// animation-duration: 2s;
|
|
||||||
// animation-delay: 250ms;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: content-box;
|
|
||||||
// border: 1px solid red;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.topicAnswer {
|
}
|
||||||
width: 69%;
|
|
||||||
height: 100%;
|
.topicAnswer {
|
||||||
|
width: 69%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.answerInfo {
|
||||||
|
width: 100%;
|
||||||
|
height: 92%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
// background-image: url("@/assets/image/videoBack.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
align-items: center;
|
||||||
.SelectAnswer {
|
justify-content: center;
|
||||||
width: 97%;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-bottom: 1px #43cf7c solid;
|
|
||||||
height: 7%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
.answerInfo {
|
|
||||||
width: 100%;
|
|
||||||
height: 92%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
|
||||||
// background-color: #f0f9cc;
|
|
||||||
background-image: url("@/assets/image/videoBack.jpg");
|
|
||||||
background-size: cover; // 背景图片铺满元
|
|
||||||
background-position: center; // 背景图片居中显示
|
|
||||||
background-repeat: no-repeat; // 背景图片不重复
|
|
||||||
}
|
|
||||||
// background-color: #F0F9CC;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.selectInput {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 7px 10px;
|
|
||||||
border: 2px #000000 solid;
|
|
||||||
border-radius: 30px;
|
|
||||||
input {
|
|
||||||
background-color: #00000000; /* 透明背景 */
|
|
||||||
border: none; /* 无边框 */
|
|
||||||
outline: none; /* 去除聚焦时的轮廓 */
|
|
||||||
padding: 0; /* 无内边距 */
|
|
||||||
margin: 0; /* 无外边距 */
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.jiexi {
|
.jiexi {
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answerNav {
|
.answerNav {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.StarIcon {
|
.StarIcon {
|
||||||
// float: right;
|
|
||||||
margin-right: 3vw;
|
margin-right: 3vw;
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="userPage">
|
<div class="userPage">
|
||||||
<div style="height: 3vh;margin: 0 auto;width: 97%;">
|
<div style="height: 3vh;margin: 0 auto;width: 97%;">
|
||||||
<el-page-header @back="router.push('/')">
|
<el-page-header @back="goback()">
|
||||||
<template #content>
|
<template #content>
|
||||||
<span class="text-large font-600 mr-3"> 个人信息 </span>
|
<span class="text-large font-600 mr-3"> 个人信息 </span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -14,9 +14,9 @@
|
||||||
<div class="userBox">
|
<div class="userBox">
|
||||||
<div class="userInfo">
|
<div class="userInfo">
|
||||||
<div class="userT" @click="drawer = true">
|
<div class="userT" @click="drawer = true">
|
||||||
<el-avatar :size="150" :src="useSotr.avatar" />
|
<el-avatar :size="150" :src="userInfo.avatar" />
|
||||||
</div>
|
</div>
|
||||||
<div class="userName">{{ useSotr.username }}</div>
|
<div class="userName">{{ userInfo.nickname }}</div>
|
||||||
<!-- <div class="userName" @click="router.push('/')">返回首页</div> -->
|
<!-- <div class="userName" @click="router.push('/')">返回首页</div> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="collectionTopic">
|
<div class="collectionTopic">
|
||||||
|
@ -24,9 +24,10 @@
|
||||||
<div class="collectionList">
|
<div class="collectionList">
|
||||||
<div
|
<div
|
||||||
class="collectionTme"
|
class="collectionTme"
|
||||||
v-for="emit in topStore.collectTopics"
|
v-for="emit in cpllectList"
|
||||||
:key="emit.id"
|
:key="emit.id"
|
||||||
:Topic="emit"
|
:Topic="emit"
|
||||||
|
@click="goQuestion(emit)"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
[{{ emit.type == "select" ? "选择题" : "填空题" }}]{{
|
[{{ emit.type == "select" ? "选择题" : "填空题" }}]{{
|
||||||
|
@ -68,7 +69,7 @@
|
||||||
<div class="infoItme">
|
<div class="infoItme">
|
||||||
<div class="text">用户名</div>
|
<div class="text">用户名</div>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="userForm.username"
|
v-model="userForm.nickname"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
placeholder="Please input"
|
placeholder="Please input"
|
||||||
:disabled="!isUpdata"
|
:disabled="!isUpdata"
|
||||||
|
@ -138,6 +139,167 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import router from "@/router";
|
||||||
|
import ImageUpload from "@/components/ImageUpload.vue";
|
||||||
|
import { ElMessage, ElStep } from "element-plus";
|
||||||
|
import { ElMessageBox } from "element-plus";
|
||||||
|
import "element-plus/theme-chalk/el-message.css";
|
||||||
|
import { login } from "@/api/user/user";
|
||||||
|
import { updateUserInfo } from "@/api/user/user";
|
||||||
|
import { computed, onMounted, reactive, ref } from "vue";
|
||||||
|
import { useTopicStore } from "@/stores/topic.js";
|
||||||
|
import { useUserStore } from "@/stores/user.js";
|
||||||
|
import TokenService from "@/utils/token";
|
||||||
|
const cpllectList = computed(() => topStore.collectTopics);
|
||||||
|
function goQuestion(item){
|
||||||
|
useTopicStore().setQuestions(cpllectList.value,item)
|
||||||
|
router.push({
|
||||||
|
path: "/",
|
||||||
|
query: {
|
||||||
|
type: 'view'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function goback(){
|
||||||
|
router.go(-1);
|
||||||
|
}
|
||||||
|
const upload = (url) => {
|
||||||
|
console.log(url);
|
||||||
|
userForm.value.avatar = url;
|
||||||
|
};
|
||||||
|
const utLogin = () => {
|
||||||
|
TokenService.removeToken();
|
||||||
|
router.push("/login");
|
||||||
|
};
|
||||||
|
const dialogFormVisible = ref(false);
|
||||||
|
const useSotr = useUserStore();
|
||||||
|
const userInfo = computed(() => useSotr.user);
|
||||||
|
const topStore = useTopicStore();
|
||||||
|
const ruleFormRef = ref(null);
|
||||||
|
const drawer = ref(false);
|
||||||
|
const isUpdata = ref(false);
|
||||||
|
let userForm = ref({
|
||||||
|
username: null,
|
||||||
|
phone: null,
|
||||||
|
remark: null,
|
||||||
|
avatar: null,
|
||||||
|
});
|
||||||
|
const updateClick = async () => {
|
||||||
|
if (
|
||||||
|
! userForm.value
|
||||||
|
) {
|
||||||
|
ElMessage({ message: "请完善信息", type: "error" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let res = await updateUserInfo(userForm.value);
|
||||||
|
if (res.code == 200) {
|
||||||
|
ElMessage({ message: "更新成功", type: "success" });
|
||||||
|
isUpdata.value = false;
|
||||||
|
await useSotr.UserInfo();
|
||||||
|
userForm.value = userInfo.value
|
||||||
|
}
|
||||||
|
console.log(res);
|
||||||
|
};
|
||||||
|
const handleClose = (done) => {
|
||||||
|
if (isUpdata.value) {
|
||||||
|
ElMessageBox.confirm("更改未保存,确定退出吗?", {
|
||||||
|
confirmButtonText: "确定退出",
|
||||||
|
cancelButtonText: "继续修改",
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
userForm.value = userInfo.value
|
||||||
|
isUpdata.value = false;
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// catch error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ruleForm = reactive({
|
||||||
|
password: "",
|
||||||
|
newPassword: "",
|
||||||
|
newPassword2: "",
|
||||||
|
});
|
||||||
|
const usernamevalidate = async (rule, value, callback) => {
|
||||||
|
if (value === "") {
|
||||||
|
callback(new Error("请输旧密码"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let res = await login({ username: useSotr.username, password: value });
|
||||||
|
if (res.code == 200) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback(new Error("密码错误"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const validatePass = (rule, value, callback) => {
|
||||||
|
if (value === "") {
|
||||||
|
callback(new Error("请输新入密码"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ruleForm.password !== "") {
|
||||||
|
if (!ruleFormRef.value) return;
|
||||||
|
ruleFormRef.value.validateField("》》");
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const validatePass2 = (rule, value, callback) => {
|
||||||
|
if (value === "") {
|
||||||
|
callback(new Error("请输确认新密码"));
|
||||||
|
}
|
||||||
|
else if (value !== ruleForm.newPassword) {
|
||||||
|
callback(new Error("密码不一致"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const submitForm = () => {
|
||||||
|
ruleFormRef.value.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
let res = await updateUserInfo({
|
||||||
|
password: ruleForm.newPassword,
|
||||||
|
});
|
||||||
|
if (res.code == 200) {
|
||||||
|
ElMessage({ message: "更新成功,请重新登录账号", type: "success" });
|
||||||
|
dialogFormVisible.value = false;
|
||||||
|
ruleForm.password = "";
|
||||||
|
ruleForm.newPassword = "";
|
||||||
|
ruleForm.newPassword2 = "";
|
||||||
|
TokenService.removeToken();
|
||||||
|
router.push("/login");
|
||||||
|
// await useSotr.UserInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const rules = reactive({
|
||||||
|
password: [{ validator: usernamevalidate, trigger: "blur" }],
|
||||||
|
newPassword: [{ validator: validatePass, trigger: "blur" }],
|
||||||
|
newPassword2: [{ validator: validatePass2, trigger: "blur" }],
|
||||||
|
});
|
||||||
|
onMounted(async () => {
|
||||||
|
await useSotr.UserInfo();
|
||||||
|
userForm.value = userInfo.value;
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(userInfo.value)
|
||||||
|
|
||||||
|
}, 400);
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.userPage {
|
.userPage {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
@ -264,156 +426,4 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script setup>
|
|
||||||
import router from "@/router";
|
|
||||||
import ImageUpload from "@/components/ImageUpload.vue";
|
|
||||||
import { ElMessage, ElStep } from "element-plus";
|
|
||||||
import { ElMessageBox } from "element-plus";
|
|
||||||
import "element-plus/theme-chalk/el-message.css";
|
|
||||||
import { login } from "@/api/user/user";
|
|
||||||
import { updateUserInfo } from "@/api/user/user";
|
|
||||||
import { onMounted, reactive, ref } from "vue";
|
|
||||||
import { useTopicStore } from "@/stores/topic.js";
|
|
||||||
import { useUserStore } from "@/stores/user.js";
|
|
||||||
import TokenService from "@/utils/token";
|
|
||||||
const upload = (url) => {
|
|
||||||
userForm.avatar = url;
|
|
||||||
};
|
|
||||||
const utLogin = () => {
|
|
||||||
TokenService.removeToken();
|
|
||||||
router.push("/login");
|
|
||||||
};
|
|
||||||
const dialogFormVisible = ref(false);
|
|
||||||
const useSotr = useUserStore();
|
|
||||||
const topStore = useTopicStore();
|
|
||||||
const ruleFormRef = ref(null);
|
|
||||||
const drawer = ref(false);
|
|
||||||
const isUpdata = ref(false);
|
|
||||||
const userForm = reactive({
|
|
||||||
username: null,
|
|
||||||
phone: null,
|
|
||||||
remark: null,
|
|
||||||
avatar: null,
|
|
||||||
});
|
|
||||||
const updateClick = async () => {
|
|
||||||
if (
|
|
||||||
userForm.username == null ||
|
|
||||||
userForm.phone == null ||
|
|
||||||
userForm.avatar == null
|
|
||||||
) {
|
|
||||||
ElMessage({ message: "请完善信息", type: "error" });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let res = await updateUserInfo(userForm);
|
|
||||||
if (res.code == 200) {
|
|
||||||
ElMessage({ message: "更新成功", type: "success" });
|
|
||||||
isUpdata.value = false;
|
|
||||||
await useSotr.UserInfo();
|
|
||||||
userForm.username = useSotr.username;
|
|
||||||
userForm.phone = useSotr.phone;
|
|
||||||
userForm.remark = useSotr.remark;
|
|
||||||
userForm.avatar = useSotr.avatar;
|
|
||||||
isUpdata.value = false;
|
|
||||||
}
|
|
||||||
console.log(res);
|
|
||||||
};
|
|
||||||
const handleClose = (done) => {
|
|
||||||
if (isUpdata.value) {
|
|
||||||
ElMessageBox.confirm("更改未保存,确定退出吗?", {
|
|
||||||
confirmButtonText: "确定退出",
|
|
||||||
cancelButtonText: "继续修改",
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
userForm.username = useSotr.username;
|
|
||||||
userForm.phone = useSotr.phone;
|
|
||||||
userForm.remark = useSotr.remark;
|
|
||||||
userForm.avatar = useSotr.avatar;
|
|
||||||
isUpdata.value = false;
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// catch error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const ruleForm = reactive({
|
|
||||||
password: "",
|
|
||||||
newPassword: "",
|
|
||||||
newPassword2: "",
|
|
||||||
});
|
|
||||||
const usernamevalidate = async (rule, value, callback) => {
|
|
||||||
if (value === "") {
|
|
||||||
callback(new Error("请输旧密码"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let res = await login({ username: useSotr.username, password: value });
|
|
||||||
if (res.code == 200) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(new Error("密码错误"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const validatePass = (rule, value, callback) => {
|
|
||||||
if (value === "") {
|
|
||||||
callback(new Error("请输新入密码"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ruleForm.password !== "") {
|
|
||||||
if (!ruleFormRef.value) return;
|
|
||||||
ruleFormRef.value.validateField("》》");
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const validatePass2 = (rule, value, callback) => {
|
|
||||||
if (value === "") {
|
|
||||||
callback(new Error("请输确认新密码"));
|
|
||||||
}
|
|
||||||
else if (value !== ruleForm.newPassword) {
|
|
||||||
callback(new Error("密码不一致"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const submitForm = () => {
|
|
||||||
ruleFormRef.value.validate(async (valid) => {
|
|
||||||
if (valid) {
|
|
||||||
let res = await updateUserInfo({
|
|
||||||
password: ruleForm.newPassword,
|
|
||||||
});
|
|
||||||
if (res.code == 200) {
|
|
||||||
ElMessage({ message: "更新成功,请重新登录账号", type: "success" });
|
|
||||||
dialogFormVisible.value = false;
|
|
||||||
ruleForm.password = "";
|
|
||||||
ruleForm.newPassword = "";
|
|
||||||
ruleForm.newPassword2 = "";
|
|
||||||
TokenService.removeToken();
|
|
||||||
router.push("/login");
|
|
||||||
// await useSotr.UserInfo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const rules = reactive({
|
|
||||||
password: [{ validator: usernamevalidate, trigger: "blur" }],
|
|
||||||
newPassword: [{ validator: validatePass, trigger: "blur" }],
|
|
||||||
newPassword2: [{ validator: validatePass2, trigger: "blur" }],
|
|
||||||
});
|
|
||||||
onMounted(async () => {
|
|
||||||
await useSotr.UserInfo();
|
|
||||||
userForm.username = useSotr.username;
|
|
||||||
userForm.phone = useSotr.phone;
|
|
||||||
userForm.remark = useSotr.remark;
|
|
||||||
userForm.avatar = useSotr.avatar;
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -22,6 +22,7 @@ export default defineConfig({
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue