大部分
This commit is contained in:
parent
2bbccd9a5f
commit
8f92dc3ed3
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.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>
|
||||||
<title>Vite App</title>
|
<title>Vite App</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
"name": "zt-sys",
|
"name": "zt-sys",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"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",
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"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",
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import http from "@/utils/http";
|
||||||
|
//获取题目
|
||||||
|
export const getQuestion= (type)=>{
|
||||||
|
if(type==null||type==undefined){
|
||||||
|
type="refresh";
|
||||||
|
}
|
||||||
|
return http({
|
||||||
|
url:"/question/getQuestion",
|
||||||
|
method:"get",
|
||||||
|
params:{
|
||||||
|
type
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//注册
|
||||||
|
export const validationAnswer= (user)=>{
|
||||||
|
return http({
|
||||||
|
url:"/question/validationAnswer",
|
||||||
|
method:"get",
|
||||||
|
data:user,
|
||||||
|
headers:{
|
||||||
|
isToken:false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import http from "@/utils/http";
|
||||||
|
//登录
|
||||||
|
export const login= (user)=>{
|
||||||
|
return http({
|
||||||
|
url:"/user/login",
|
||||||
|
method:"post",
|
||||||
|
data:user,
|
||||||
|
headers:{
|
||||||
|
isToken:false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//注册
|
||||||
|
export const register= (user)=>{
|
||||||
|
return http({
|
||||||
|
url:"/user/register",
|
||||||
|
method:"post",
|
||||||
|
data:user,
|
||||||
|
headers:{
|
||||||
|
isToken:false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//获取用户信息
|
||||||
|
export const getUserInfo= ()=>{
|
||||||
|
return http({
|
||||||
|
url:"/user",
|
||||||
|
method:"get"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//修改用户信息
|
||||||
|
export const updateUserInfo= (user)=>{
|
||||||
|
return http.request({
|
||||||
|
url:"/user/update",
|
||||||
|
method:"post",
|
||||||
|
params:user
|
||||||
|
})
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 295 KiB |
|
@ -1,44 +0,0 @@
|
||||||
<script setup>
|
|
||||||
defineProps({
|
|
||||||
msg: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="greetings">
|
|
||||||
<h1 class="green">{{ msg }}</h1>
|
|
||||||
<h3>
|
|
||||||
You’ve successfully created a project with
|
|
||||||
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
|
|
||||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
h1 {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 2.6rem;
|
|
||||||
position: relative;
|
|
||||||
top: -10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.greetings h1,
|
|
||||||
.greetings h3 {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.greetings h1,
|
|
||||||
.greetings h3 {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,88 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import WelcomeItem from './WelcomeItem.vue'
|
|
||||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
|
||||||
import ToolingIcon from './icons/IconTooling.vue'
|
|
||||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
|
||||||
import CommunityIcon from './icons/IconCommunity.vue'
|
|
||||||
import SupportIcon from './icons/IconSupport.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<DocumentationIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Documentation</template>
|
|
||||||
|
|
||||||
Vue’s
|
|
||||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
|
||||||
provides you with all information you need to get started.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<ToolingIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Tooling</template>
|
|
||||||
|
|
||||||
This project is served and bundled with
|
|
||||||
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
|
||||||
recommended IDE setup is
|
|
||||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
|
|
||||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
|
|
||||||
you need to test your components and web pages, check out
|
|
||||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
|
|
||||||
<a href="https://on.cypress.io/component" target="_blank" rel="noopener"
|
|
||||||
>Cypress Component Testing</a
|
|
||||||
>.
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
More instructions are available in <code>README.md</code>.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<EcosystemIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Ecosystem</template>
|
|
||||||
|
|
||||||
Get official tools and libraries for your project:
|
|
||||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
|
||||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
|
||||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
|
||||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
|
||||||
you need more resources, we suggest paying
|
|
||||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
|
||||||
a visit.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<CommunityIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Community</template>
|
|
||||||
|
|
||||||
Got stuck? Ask your question on
|
|
||||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
|
|
||||||
Discord server, or
|
|
||||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
|
||||||
>StackOverflow</a
|
|
||||||
>. You should also subscribe to
|
|
||||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
|
|
||||||
the official
|
|
||||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
|
||||||
twitter account for latest news in the Vue world.
|
|
||||||
</WelcomeItem>
|
|
||||||
|
|
||||||
<WelcomeItem>
|
|
||||||
<template #icon>
|
|
||||||
<SupportIcon />
|
|
||||||
</template>
|
|
||||||
<template #heading>Support Vue</template>
|
|
||||||
|
|
||||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
|
||||||
us by
|
|
||||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
|
||||||
</WelcomeItem>
|
|
||||||
</template>
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<div class="topicInfoBox">
|
||||||
|
<div class="flex gap-2" style="width: 90%; margin: 0 auto">
|
||||||
|
<el-tag v-for="itme in props.tags" :key="itme.name" type="primary">{{ itme.name}}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="introduce">
|
||||||
|
{{ props.introduce }}
|
||||||
|
</div>
|
||||||
|
<p style="width: 90%; margin: 0 auto">
|
||||||
|
{{ props.topicTitle }}
|
||||||
|
</p>
|
||||||
|
<div class="introduce">
|
||||||
|
<el-radio-group v-model="radio">
|
||||||
|
<el-radio
|
||||||
|
v-for="itme in topicSelect"
|
||||||
|
:key="itme.key"
|
||||||
|
:value="itme.key"
|
||||||
|
>{{ itme.key + "." + itme.name }}</el-radio
|
||||||
|
>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div class="introduce">
|
||||||
|
<el-button v-if="radio != null" type="success">提交</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.topicInfoBox {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.introduce {
|
||||||
|
margin: 10px auto;
|
||||||
|
width: 90%;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
const props = defineProps({
|
||||||
|
id: { type: Number, default: null },
|
||||||
|
videoUrl: { type: String, default: null },
|
||||||
|
topicList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: { type: Number, default: null },
|
||||||
|
topicTitle: { type: String, default: "题目" },
|
||||||
|
introduce: { type: String, default: "介绍" },
|
||||||
|
tags: { type: Array, default: null },
|
||||||
|
});
|
||||||
|
const topicSelect = ref([]);
|
||||||
|
onMounted(() => {
|
||||||
|
topicSelect.value = props.topicList;
|
||||||
|
});
|
||||||
|
const radio = ref(null);
|
||||||
|
</script>
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div class="word-list">
|
||||||
|
<div
|
||||||
|
v-for="word in words"
|
||||||
|
:key="word"
|
||||||
|
class="word-item"
|
||||||
|
@click="handleWordClick(word)"
|
||||||
|
>
|
||||||
|
{{ word }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
const emit=defineEmits(['select'])
|
||||||
|
// 包含所有可点击词的数组
|
||||||
|
const words = ref([
|
||||||
|
'高数上', '高数下', '线性代数', '数学分析', '解析几何',
|
||||||
|
'概率论与数理统计', '复变函数', '实变函数', '常微分方程',
|
||||||
|
'近世代数', '数据结构', 'C语言', '软件工程类', '大学物理(简明)',
|
||||||
|
'物理实验', '力学', '热学', '光学', '电磁学', '原子物理学',
|
||||||
|
'物理专业', '高中物理', '初中物理', '高中化学', '初中化学',
|
||||||
|
'高中数学', '初中数学', '小学数学', '高中生物', '初中生物',
|
||||||
|
'有机化学', '无机化学', '分析化学', '物理化学', '结构化学',
|
||||||
|
'高分子化学', '配位化学', '生物化学', '普通生物学', '细胞生物学',
|
||||||
|
'遗传学', '微生物学', '植物学', '动物学', '数学', '物理', '化学', '生物',
|
||||||
|
'法学', '经济学', '其他'
|
||||||
|
]);
|
||||||
|
const handleWordClick = (word) => {
|
||||||
|
console.log(`Clicked word: ${word}`);
|
||||||
|
emit('select',word);
|
||||||
|
// 这里可以抛出一个事件,或者调用其他方法
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.word-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
/* gap: 10px; */
|
||||||
|
}
|
||||||
|
.word-item {
|
||||||
|
padding: 8px;
|
||||||
|
border-bottom: 1px solid #43CF7C;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none; /* 防止用户选择文本 */
|
||||||
|
}
|
||||||
|
.word-item:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<div class="video-container">
|
||||||
|
<video
|
||||||
|
ref="videoRef"
|
||||||
|
:src="props.src"
|
||||||
|
width="100%"
|
||||||
|
height="400px"
|
||||||
|
controls
|
||||||
|
@play="handlePlay"
|
||||||
|
@fullscreenchange="handleFullscreenChange"
|
||||||
|
>
|
||||||
|
您的浏览器不支持 video 标签。
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted, onUnmounted } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
src: String
|
||||||
|
});
|
||||||
|
|
||||||
|
const videoSrc = ref(props.src);
|
||||||
|
const videoRef = ref(null);
|
||||||
|
const isFullscreen = ref(false);
|
||||||
|
|
||||||
|
const handlePlay = () => {
|
||||||
|
console.log('视频开始播放');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFullscreenChange = () => {
|
||||||
|
isFullscreen.value = document.fullscreenElement === videoRef.value;
|
||||||
|
};
|
||||||
|
watch(() => props.src, (newSrc) => {
|
||||||
|
videoSrc.value = newSrc;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('视频组件挂载完成');
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
console.log('视频组件卸载');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.video-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640px; /* 可以根据需要调整 */
|
||||||
|
/* margin: 0 auto; */
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,86 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="item">
|
|
||||||
<i>
|
|
||||||
<slot name="icon"></slot>
|
|
||||||
</i>
|
|
||||||
<div class="details">
|
|
||||||
<h3>
|
|
||||||
<slot name="heading"></slot>
|
|
||||||
</h3>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.item {
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
|
||||||
flex: 1;
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
place-content: center;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 0.4rem;
|
|
||||||
color: var(--color-heading);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.item {
|
|
||||||
margin-top: 0;
|
|
||||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
top: calc(50% - 25px);
|
|
||||||
left: -26px;
|
|
||||||
position: absolute;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
background: var(--color-background);
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:before {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:after {
|
|
||||||
content: ' ';
|
|
||||||
border-left: 1px solid var(--color-border);
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: calc(50% + 25px);
|
|
||||||
height: calc(50% - 25px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:first-of-type:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item:last-of-type:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
|
||||||
<path
|
|
||||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
|
||||||
<path
|
|
||||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
|
||||||
<path
|
|
||||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<template>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
|
||||||
<path
|
|
||||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
|
@ -1,19 +0,0 @@
|
||||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
|
||||||
<template>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
aria-hidden="true"
|
|
||||||
role="img"
|
|
||||||
class="iconify iconify--mdi"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
preserveAspectRatio="xMidYMid meet"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
|
||||||
fill="currentColor"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
|
@ -6,11 +6,16 @@ import ElementPlus from 'element-plus'
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
// 如果您正在使用CDN引入,请删除下面一行。
|
||||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(ElementPlus, { size: 'small', zIndex: 3000 })
|
app.use(ElementPlus, { size: 'small', zIndex: 3000 })
|
||||||
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
|
app.component(key, component)
|
||||||
|
}
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
const storage ={
|
||||||
|
setStorage:function(key,value){
|
||||||
|
window.localStorage.setItem(key,JSON.stringify(value))
|
||||||
|
},
|
||||||
|
getStorage:function(key){
|
||||||
|
return JSON.parse(window.localStorage.getItem(key))
|
||||||
|
},
|
||||||
|
removeStorage:function(key){
|
||||||
|
window.localStorage.removeItem(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default storage
|
|
@ -0,0 +1,35 @@
|
||||||
|
import axios from 'axios'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import 'element-plus/theme-chalk/el-message.css'
|
||||||
|
import TokenService from '@/utils/token'
|
||||||
|
import router from '@/router'
|
||||||
|
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
||||||
|
const httpInstance=axios.create({
|
||||||
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
// axios请求拦截器
|
||||||
|
httpInstance.interceptors.request.use(config => {
|
||||||
|
// 是否需要设置 token
|
||||||
|
const isToken = (config.headers || {}).isToken === false
|
||||||
|
if (TokenService.hasToken() && !isToken) {
|
||||||
|
config.headers['Authorization'] = TokenService.getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}, e => Promise.reject(e))
|
||||||
|
|
||||||
|
// axios响应式拦截器
|
||||||
|
httpInstance.interceptors.response.use(res => {
|
||||||
|
if (res.data.code === 401){
|
||||||
|
router.push('/login')
|
||||||
|
}
|
||||||
|
if(res.data.code==0){
|
||||||
|
ElMessage.error(res.data.msg)
|
||||||
|
}
|
||||||
|
return res.data
|
||||||
|
}, e => {
|
||||||
|
return Promise.reject(e)
|
||||||
|
})
|
||||||
|
// let abb=1;
|
||||||
|
export default httpInstance;
|
||||||
|
|
|
@ -1,154 +0,0 @@
|
||||||
import axios from 'axios'
|
|
||||||
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
|
|
||||||
import 'element-plus/theme-chalk/el-message.css'
|
|
||||||
import 'element-plus/theme-chalk/el-message-box.css'
|
|
||||||
import { getToken } from '@/utils/auth'
|
|
||||||
import errorCode from '@/utils/errorCode'
|
|
||||||
import { tansParams, blobValidate } from '@/utils/ruoyi'
|
|
||||||
import cache from '@/plugins/cache'
|
|
||||||
import { saveAs } from 'file-saver'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
|
|
||||||
let downloadLoadingInstance;
|
|
||||||
// 是否显示重新登录
|
|
||||||
export let isRelogin = { show: false };
|
|
||||||
|
|
||||||
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
|
||||||
// 创建axios实例
|
|
||||||
const service = axios.create({
|
|
||||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
|
||||||
// 超时
|
|
||||||
timeout: 10000
|
|
||||||
})
|
|
||||||
|
|
||||||
// request拦截器
|
|
||||||
service.interceptors.request.use(config => {
|
|
||||||
// 是否需要设置 token
|
|
||||||
const isToken = (config.headers || {}).isToken === false
|
|
||||||
// 是否需要防止数据重复提交
|
|
||||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
|
|
||||||
if (getToken() && !isToken) {
|
|
||||||
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
|
||||||
}
|
|
||||||
// get请求映射params参数
|
|
||||||
if (config.method === 'get' && config.params) {
|
|
||||||
let url = config.url + '?' + tansParams(config.params);
|
|
||||||
url = url.slice(0, -1);
|
|
||||||
config.params = {};
|
|
||||||
config.url = url;
|
|
||||||
}
|
|
||||||
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
|
|
||||||
const requestObj = {
|
|
||||||
url: config.url,
|
|
||||||
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
|
|
||||||
time: new Date().getTime()
|
|
||||||
}
|
|
||||||
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
|
|
||||||
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
|
|
||||||
if (requestSize >= limitSize) {
|
|
||||||
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
const sessionObj = cache.session.getJSON('sessionObj')
|
|
||||||
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
|
|
||||||
cache.session.setJSON('sessionObj', requestObj)
|
|
||||||
} else {
|
|
||||||
const s_url = sessionObj.url; // 请求地址
|
|
||||||
const s_data = sessionObj.data; // 请求数据
|
|
||||||
const s_time = sessionObj.time; // 请求时间
|
|
||||||
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
|
|
||||||
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
|
|
||||||
const message = '数据正在处理,请勿重复提交';
|
|
||||||
console.warn(`[${s_url}]: ` + message)
|
|
||||||
return Promise.reject(new Error(message))
|
|
||||||
} else {
|
|
||||||
cache.session.setJSON('sessionObj', requestObj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}, error => {
|
|
||||||
console.log(error)
|
|
||||||
Promise.reject(error)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 响应拦截器
|
|
||||||
service.interceptors.response.use(res => {
|
|
||||||
// 未设置状态码则默认成功状态
|
|
||||||
const code = res.data.code || 200;
|
|
||||||
// 获取错误信息
|
|
||||||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
|
||||||
// 二进制数据则直接返回
|
|
||||||
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
|
|
||||||
return res.data
|
|
||||||
}
|
|
||||||
if (code === 401) {
|
|
||||||
if (!isRelogin.show) {
|
|
||||||
isRelogin.show = true;
|
|
||||||
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
|
||||||
isRelogin.show = false;
|
|
||||||
useUserStore().logOut().then(() => {
|
|
||||||
location.href = '/index';
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
isRelogin.show = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
|
||||||
} else if (code === 500) {
|
|
||||||
ElMessage({ message: msg, type: 'error' })
|
|
||||||
return Promise.reject(new Error(msg))
|
|
||||||
} else if (code === 601) {
|
|
||||||
ElMessage({ message: msg, type: 'warning' })
|
|
||||||
return Promise.reject(new Error(msg))
|
|
||||||
} else if (code !== 200) {
|
|
||||||
ElNotification.error({ title: msg })
|
|
||||||
return Promise.reject('error')
|
|
||||||
} else {
|
|
||||||
return Promise.resolve(res.data)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('err' + error)
|
|
||||||
let { message } = error;
|
|
||||||
if (message == "Network Error") {
|
|
||||||
message = "后端接口连接异常";
|
|
||||||
} else if (message.includes("timeout")) {
|
|
||||||
message = "系统接口请求超时";
|
|
||||||
} else if (message.includes("Request failed with status code")) {
|
|
||||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
|
||||||
}
|
|
||||||
ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// 通用下载方法
|
|
||||||
export function download(url, params, filename, config) {
|
|
||||||
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
|
|
||||||
return service.post(url, params, {
|
|
||||||
transformRequest: [(params) => { return tansParams(params) }],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
responseType: 'blob',
|
|
||||||
...config
|
|
||||||
}).then(async (data) => {
|
|
||||||
const isBlob = blobValidate(data);
|
|
||||||
if (isBlob) {
|
|
||||||
const blob = new Blob([data])
|
|
||||||
saveAs(blob, filename)
|
|
||||||
} else {
|
|
||||||
const resText = await data.text();
|
|
||||||
const rspObj = JSON.parse(resText);
|
|
||||||
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
|
|
||||||
ElMessage.error(errMsg);
|
|
||||||
}
|
|
||||||
downloadLoadingInstance.close();
|
|
||||||
}).catch((r) => {
|
|
||||||
console.error(r)
|
|
||||||
ElMessage.error('下载文件出现错误,请联系管理员!')
|
|
||||||
downloadLoadingInstance.close();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default service
|
|
|
@ -1,8 +1,309 @@
|
||||||
<template>
|
<template>
|
||||||
<div>首页</div>
|
<div class="homeBox">
|
||||||
</template>
|
<div class="nav">
|
||||||
|
<div><span class="loogText">Xuaua</span></div>
|
||||||
<style lang="scss" scoped></style>
|
<div>
|
||||||
<script setup>
|
<el-popover :width="700" trigger="click">
|
||||||
</script>
|
<template #reference>
|
||||||
|
<div class="selectInput">
|
||||||
|
<div @click="selectClick">
|
||||||
|
<el-icon :size="size" :color="color">
|
||||||
|
<Search />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<input type="text" placeholder="搜索关键词" v-model="selectType" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<TypeSelect @select="selectInput"></TypeSelect>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
<div @click="router.push('/user')">
|
||||||
|
<el-avatar :size="40" :src="circleUrl" />用户名
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="main">
|
||||||
|
<div class="mainBox">
|
||||||
|
<div class="topicInfo" ref="topicInfoRef" @click="huadong">
|
||||||
|
<div
|
||||||
|
ref="topicInfoItemRef"
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transition: 0.7s;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="itme in topicInfo.topicList"
|
||||||
|
: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"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="topicAnswer">
|
||||||
|
<div class="SelectAnswer">
|
||||||
|
<div @click="get">视频</div>
|
||||||
|
<div>解析</div>
|
||||||
|
<div>
|
||||||
|
<el-icon :size="27" :color="color">
|
||||||
|
<Star />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="answerInfo">
|
||||||
|
<VideoBox
|
||||||
|
:src="topicInfo.topicList[topicInfo.index - 1].videoUrl"
|
||||||
|
></VideoBox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.homeBox {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.nav {
|
||||||
|
width: 100%;
|
||||||
|
height: 8vh;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.loogText {
|
||||||
|
font-size: 30px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
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;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
.topicInfo {
|
||||||
|
// animation-duration: 2s;
|
||||||
|
// animation-delay: 250ms;
|
||||||
|
width: 30%;
|
||||||
|
height: 100%;
|
||||||
|
// background-color: #f0f9cc;
|
||||||
|
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%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
.SelectAnswer {
|
||||||
|
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/tibg.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%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref, onMounted } from "vue";
|
||||||
|
import TopicBox from "@/components/TopicBox.vue";
|
||||||
|
import VideoBox from "@/components/VideoBox.vue";
|
||||||
|
import TypeSelect from '@/components/TypeSelect.vue'
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import "element-plus/theme-chalk/el-message.css";
|
||||||
|
import router from "@/router";
|
||||||
|
import { getQuestion } from "@/api/question/question";
|
||||||
|
// import { c } from "vite/dist/node/types.d-aGj9QkWt";
|
||||||
|
const topicInfoItemRef = ref(null);
|
||||||
|
const selectType=ref(null);
|
||||||
|
const topicInfo = reactive({
|
||||||
|
index: 1,
|
||||||
|
number: 3,
|
||||||
|
topicList: [{ id: 1 }, { id: 2 }, { id: 3 }],
|
||||||
|
});
|
||||||
|
let mouseDown = false;
|
||||||
|
const selectInput=(word)=>{
|
||||||
|
selectType.value=word;
|
||||||
|
}
|
||||||
|
const selectClick=async()=>{
|
||||||
|
let res = await getQuestionInfo(selectType.value);
|
||||||
|
topicInfo.index=1;
|
||||||
|
topicInfo.topicList = res;
|
||||||
|
topicInfo.number = res.length;
|
||||||
|
}
|
||||||
|
// 鼠标按下时的位
|
||||||
|
let lastY = null;
|
||||||
|
//实时鼠标位
|
||||||
|
let currentY = null;
|
||||||
|
// 鼠标按下时触发的事件
|
||||||
|
const huadong = () => {};
|
||||||
|
document.addEventListener("mousedown", function (event) {
|
||||||
|
mouseDown = true;
|
||||||
|
// lastX = event.clientX;
|
||||||
|
lastY = event.clientY;
|
||||||
|
// currentX = event.clientX;
|
||||||
|
currentY = event.clientY;
|
||||||
|
// console.log("鼠标按下位置:", lastX, lastY);
|
||||||
|
|
||||||
|
// 开始实时监听鼠标移动
|
||||||
|
document.addEventListener("mousemove", onMouseMove);
|
||||||
|
});
|
||||||
|
// 鼠标移动时触发的事件
|
||||||
|
function onMouseMove(event) {
|
||||||
|
if (mouseDown) {
|
||||||
|
let deltaY = event.clientY - currentY;
|
||||||
|
currentY = event.clientY;
|
||||||
|
setScrollY(deltaY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 鼠标松开时触发的事件
|
||||||
|
document.addEventListener("mouseup", function (event) {
|
||||||
|
mouseDown = false;
|
||||||
|
let deltaY = event.clientY - lastY;
|
||||||
|
console.log("变化", deltaY);
|
||||||
|
flipPage(deltaY);
|
||||||
|
document.removeEventListener("mousemove", onMouseMove);
|
||||||
|
});
|
||||||
|
const topicInfoRef = ref(null);
|
||||||
|
const get = () => {
|
||||||
|
console.log("信息", getScrollbarPosition());
|
||||||
|
};
|
||||||
|
const setScrollY = (y) => {
|
||||||
|
if (topicInfoRef.value) {
|
||||||
|
topicInfoRef.value.scrollTop = topicInfoRef.value.scrollTop - y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const flipPage = (y) => {
|
||||||
|
if (topicInfoItemRef.value) {
|
||||||
|
topicInfoRef.value.scrollTop = 0;
|
||||||
|
if (y < -80) {
|
||||||
|
topicInfo.index++;
|
||||||
|
if (topicInfo.index > topicInfo.number) {
|
||||||
|
topicInfo.index = topicInfo.number;
|
||||||
|
ElMessage({ message: "没有更多了", type: "warning" });
|
||||||
|
}
|
||||||
|
if (topicInfo.index == topicInfo.number) {
|
||||||
|
//最后一个了准备记载新数据
|
||||||
|
// topicInfo.number+=3;
|
||||||
|
// topicInfo.topicList=[...topicInfo.topicList,...[{id:topicInfo.number+1},{id:topicInfo.number+2},{id:topicInfo.number+3}
|
||||||
|
// ]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (y > 80) {
|
||||||
|
topicInfo.index--;
|
||||||
|
if (topicInfo.index == 0) {
|
||||||
|
topicInfo.index = 1;
|
||||||
|
ElMessage({ message: "到顶了", type: "warning" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// alert("123")
|
||||||
|
topicInfoItemRef.value.style.top =
|
||||||
|
-(topicInfo.index - 1) * topicInfoItemRef.value.clientHeight + "px";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getScrollbarPosition = () => {
|
||||||
|
if (topicInfoRef.value) {
|
||||||
|
const element = topicInfoRef.value;
|
||||||
|
return {
|
||||||
|
scrollLeft: element.scrollLeft, // 水平滚动条位置
|
||||||
|
scrollTop: element.scrollTop, // 垂直滚动条位置
|
||||||
|
scrollWidth: element.scrollWidth, // 元素内容的总宽度
|
||||||
|
scrollHeight: element.scrollHeight, // 元素内容的总高度
|
||||||
|
clientWidth: element.clientWidth, // 元素可视区域的宽度
|
||||||
|
clientHeight: element.clientHeight, // 元素可视区域的高度
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
const getQuestionInfo = async (type) => {
|
||||||
|
let res = await getQuestion(type);
|
||||||
|
console.log("res", res);
|
||||||
|
return res.data;
|
||||||
|
};
|
||||||
|
onMounted(async () => {
|
||||||
|
let res = await getQuestionInfo();
|
||||||
|
topicInfo.index=1;
|
||||||
|
topicInfo.topicList = res;
|
||||||
|
topicInfo.number = res.length;
|
||||||
|
console.log("topicInfo", topicInfo);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="inputBox">密码<input type="password" v-model="user.password" /></div>
|
<div class="inputBox">密码<input type="password" v-model="user.password" /></div>
|
||||||
<div class="checkBox"><el-checkbox v-model="remember"></el-checkbox>记住密码</div>
|
<div class="checkBox"><el-checkbox v-model="remember"></el-checkbox>记住密码</div>
|
||||||
<div class="btnBox">
|
<div class="btnBox">
|
||||||
<el-button size="large" type="success" round @click="login">登录</el-button>
|
<el-button size="large" type="success" round @click="toLogin">登录</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="large"
|
size="large"
|
||||||
type="danger"
|
type="danger"
|
||||||
|
@ -121,19 +121,37 @@ input:focus {
|
||||||
<script setup>
|
<script setup>
|
||||||
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 'element-plus/theme-chalk/el-message-box.css'
|
import { login , register } from "@/api/user/user";
|
||||||
import { ref, reactive } from "vue";
|
import storage from '@/utils/Sotrage'
|
||||||
|
import TokenService from '@/utils/token'
|
||||||
|
import router from '@/router'
|
||||||
|
import { ref, reactive,onMounted } from "vue";
|
||||||
const user=reactive({
|
const user=reactive({
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
});
|
});
|
||||||
//是否记住密码
|
//是否记住密码
|
||||||
const remember = ref(false);
|
const remember = ref(false);
|
||||||
const login = () => {
|
const toLogin = async () => {
|
||||||
if(user.username===""||user.password===""){
|
|
||||||
ElMessage({ message: "请输入完整信息", type: 'warning' })
|
|
||||||
}
|
|
||||||
console.log(user);
|
console.log(user);
|
||||||
|
if(user.username===""||user.username===null||user.password===""||user.password===null){
|
||||||
|
ElMessage({ message: "请输入完整信息", type: 'warning' })
|
||||||
|
}
|
||||||
|
|
||||||
|
let res=await login(user);
|
||||||
|
if(res.code===200){
|
||||||
|
ElMessage({ message: "登录成功", type: 'success' })
|
||||||
|
if(remember.value){
|
||||||
|
storage.setStorage("username",user.username);
|
||||||
|
storage.setStorage("password",user.password);
|
||||||
|
}else{
|
||||||
|
storage.removeStorage("username");
|
||||||
|
storage.removeStorage("password");
|
||||||
|
}
|
||||||
|
TokenService.saveToken(res.token)
|
||||||
|
//跳转
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//表单弹窗开关
|
//表单弹窗开关
|
||||||
const dialogFormVisible = ref(false);
|
const dialogFormVisible = ref(false);
|
||||||
|
@ -146,10 +164,10 @@ const ruleForm = reactive({
|
||||||
});
|
});
|
||||||
//表单验证
|
//表单验证
|
||||||
const usernamevalidate = (rule, value, callback) => {
|
const usernamevalidate = (rule, value, callback) => {
|
||||||
if (value === "") {
|
if (value === ""||value==null) {
|
||||||
callback(new Error("请输入账号"));
|
callback(new Error("请输入账号"));
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
|
callback();
|
||||||
};
|
};
|
||||||
const validatePass = (rule, value, callback) => {
|
const validatePass = (rule, value, callback) => {
|
||||||
if (value === "") {
|
if (value === "") {
|
||||||
|
@ -189,13 +207,25 @@ const rules = reactive({
|
||||||
//提交注册
|
//提交注册
|
||||||
const submitForm = (formEl) => {
|
const submitForm = (formEl) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.validate((valid) => {
|
formEl.validate(async(valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
console.log("submit!");
|
// console.log("submit!");
|
||||||
|
let res =await register({username:ruleForm.username,password:ruleForm.password});
|
||||||
|
if(res.code===200){
|
||||||
|
ElMessage({ message: "注册成功", type: 'success' })
|
||||||
|
dialogFormVisible.value=false;
|
||||||
|
}else{
|
||||||
|
ElMessage({ message: res.msg, type: 'error' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("error submit!");
|
console.log("error submit!");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
console.log("onMounted");
|
||||||
|
user.username=storage.getStorage("username");
|
||||||
|
user.password=storage.getStorage("password");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,8 +1,108 @@
|
||||||
<template>
|
<template>
|
||||||
<div>用户</div>
|
<div class="userBox">
|
||||||
</template>
|
<div class="userInfo">
|
||||||
|
<div class="userT">
|
||||||
<style lang="scss" scoped></style>
|
<el-avatar :size="150" :src="circleUrl" />
|
||||||
<script setup>
|
</div>
|
||||||
</script>
|
<div class="userName">用户名</div>
|
||||||
|
<div class="userName" @click="router.push('/');">返回首页</div>
|
||||||
|
</div>
|
||||||
|
<div class="collectionTopic">
|
||||||
|
<div class="title">收藏</div>
|
||||||
|
<div class="collectionList">
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<div class="collectionTme"></div>
|
||||||
|
<!-- <div class="collectionTme"></div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.userBox {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url("@/assets/image/userbg.jpg");
|
||||||
|
background-size: cover; // 背景图片铺满元素
|
||||||
|
background-position: center; // 背景图片居中显示
|
||||||
|
background-repeat: no-repeat; // 背景图片不重复
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.userInfo {
|
||||||
|
height: 90%;
|
||||||
|
width: 20%;
|
||||||
|
// background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
// justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.userName {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
.userT {
|
||||||
|
margin-top: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.collectionTopic {
|
||||||
|
margin-left: 30px;
|
||||||
|
width: 60%;
|
||||||
|
height: 90%;
|
||||||
|
// background-color: #ff0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
// justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.title {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 90%;
|
||||||
|
height: 5%;
|
||||||
|
background-color: #d2fce3;
|
||||||
|
border-radius: 70px;
|
||||||
|
}
|
||||||
|
.collectionList {
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* IE 10+ */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none; /* Chrome Safari */
|
||||||
|
}
|
||||||
|
flex: 1;
|
||||||
|
width: 90%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
// justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 10px;
|
||||||
|
.collectionTme {
|
||||||
|
/* 宽度是固定好的 */
|
||||||
|
width: 30%;
|
||||||
|
height: 47%;
|
||||||
|
background-color: #D2FCE3;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
// border: 1px solid red;
|
||||||
|
/*这个数值需要自己去调*/
|
||||||
|
margin-right: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.collectionList:after {
|
||||||
|
content: "";
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script setup>
|
||||||
|
import router from '@/router'
|
||||||
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue