Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/views/home/index.vue
#	src/views/login/index.vue
This commit is contained in:
虾壳 2024-07-17 19:42:02 +08:00
commit 0c1bceb97b
6 changed files with 329 additions and 265 deletions

View File

@ -3,7 +3,9 @@
"baseUrl": "./", "baseUrl": "./",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} },
"types": ["element-plus/global"]
}, },
"exclude": ["node_modules", "dist"] "exclude": ["node_modules", "dist"]
} }

View File

@ -25,5 +25,8 @@
"unplugin-auto-import": "^0.18.0", "unplugin-auto-import": "^0.18.0",
"unplugin-vue-components": "^0.27.2", "unplugin-vue-components": "^0.27.2",
"vite": "^5.3.1" "vite": "^5.3.1"
},
"volta": {
"node": "16.18.1"
} }
} }

View File

@ -0,0 +1,90 @@
<template>
<div class="nav">
<div class="logo-box"><span class="loogText">Xuaua</span></div>
<div>
<div class="search-box">
<!-- <el-input type="text" prefix-icon="el-icon-search" style="height: 38px;" class="search-input" placeholder="搜索关键词" v-model="selectType">
</el-input> -->
<el-input
v-model="input3"
style="max-width: 600px"
placeholder="搜索关键词"
class="input-with-select"
>
<template #prepend>
<el-button :icon="Search" />
</template>
</el-input>
</div>
<el-popover :width="700" trigger="click">
<template #reference>
<!-- <div class="selectInput">
<div @click="selectClick">
<el-icon :size="size" :color="color">
<Search />
</el-icon>
</div>
</div> -->
</template>
<TypeSelect @select="selectInput"></TypeSelect>
</el-popover>
</div>
<div @click="router.push('/user')" class="user-avatar">
<el-avatar :size="40" :src="circleUrl" />用户名
</div>
</div>
</template>
<script setup>
// import {defineProps} from "vue"
import { ElMessage } from "element-plus";
import TypeSelect from "@/components/TypeSelect.vue";
import { ref } from 'vue'
import { Search } from '@element-plus/icons-vue'
</script>
<style lang="scss">
.nav {
width: 100%;
height: 70px;
background-color: #fff;
display: flex;
// justify-content: space-between;
align-items: center;
.logo-box {
margin-top: 11px;
margin-left: 52px;
margin-bottom: 11px;
}
.input-with-select{
border-radius: 30px;
}
.search-box {
position: relative;
left: 210px;
border-radius: 30px;
overflow: hidden;
padding: 5px;
background: #fefefe;
// .search-input{
// width: 400px;
// height: 38px;
// border-radius: 30px;
// }
}
div {
display: flex;
align-items: center;
justify-content: center;
}
.user-avatar {
position: absolute;
right: 2%;
}
.loogText {
font-size: 30px;
margin-left: 10px;
}
}
</style>

View File

@ -3,19 +3,16 @@ import './assets/main.css'
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
// 如果您正在使用CDN引入请删除下面一行。 // 如果您正在使用CDN引入请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue' // 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)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.mount('#app') app.mount('#app')

View File

@ -1,26 +1,7 @@
<template> <template>
<div class="homeBox"> <div class="homeBox">
<div class="nav"> <div>
<div><span class="loogText">Xuaua</span></div> <xuaua-header></xuaua-header>
<div>
<el-popover :width="700" trigger="click">
<template #reference>
<div class="selectInput">
<div @click="selectClick">
<el-icon :size="20" >
<Search />
</el-icon>
</div>
<input type="text" placeholder="搜索关键词" v-model="selectType" />
</div>
</template>
<!-- {{ selectType }} -->
<TypeSelect @select="selectInput" :type="selectType"></TypeSelect>
</el-popover>
</div>
<div @click="router.push('/user')">
<el-avatar :size="40" :src="circleUrl" />用户名
</div>
</div> </div>
<div class="main"> <div class="main">
<div class="mainBox"> <div class="mainBox">
@ -71,121 +52,10 @@
</div> </div>
</div> </div>
</template> </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> <script setup>
import { reactive, ref, onMounted,watch } from "vue"; import { reactive, ref, onMounted } from "vue";
import { debounceRef} from '@/utils/debounceRef' 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 TypeSelect from '@/components/TypeSelect.vue' import TypeSelect from '@/components/TypeSelect.vue'
@ -193,12 +63,9 @@ 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 router from "@/router";
import { getQuestion } from "@/api/question/question"; import { getQuestion } from "@/api/question/question";
// import { c } from "vite/dist/node/types.d-aGj9QkWt";
const topicInfoItemRef = ref(null); const topicInfoItemRef = ref(null);
const selectType=debounceRef(null,500); const selectType=ref(null);
//selectType
watch(selectType,(newValue)=>{
console.log("新值",newValue);
})
const topicInfo = reactive({ const topicInfo = reactive({
index: 1, index: 1,
number: 3, number: 3,
@ -312,3 +179,98 @@ onMounted(async () => {
console.log("topicInfo", topicInfo); console.log("topicInfo", topicInfo);
}); });
</script> </script>
<style lang="scss" scoped>
.homeBox {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
.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>

View File

@ -1,11 +1,30 @@
<template> <template>
<div class="loginBox"> <div class="loginBox">
<div class="loginFrom"> <div class="loginFrom">
<div class="inputBox">账号<input type="text" v-model="user.username" /></div> <!-- <div class="inputBox">
<div class="inputBox">密码<input type="password" v-model="user.password" /></div> 账号<input type="text" v-model="user.username" />
<div class="checkBox"><el-checkbox v-model="remember"></el-checkbox>记住密码</div> </div>
<div class="inputBox">
密码<input type="password" v-model="user.password" />
</div>
<div class="checkBox">
<el-checkbox v-model="remember"></el-checkbox>记住密码
</div> -->
<el-form >
<el-form-item label="账号" prop="username" >
<el-input style="width: 200px;height: 30px;border-radius: 15px;" class="inputBox" type="medium" v-model="user.username" />
</el-form-item>
<el-form-item label="密码" prop="password" >
<el-input style="width: 200px;height: 30px;border-radius: 15px;" v-model="user.password" type="password" />
</el-form-item>
<el-form-item>
<el-checkbox v-model="remember">记住密码</el-checkbox>
</el-form-item>
</el-form>
<div class="btnBox"> <div class="btnBox">
<el-button size="large" type="success" round @click="toLogin">登录</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"
@ -46,10 +65,10 @@
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="dialogFormVisible=false">取消</el-button> <el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)"> <el-button type="primary" @click="submitForm(ruleFormRef)"
注册 >注册</el-button
</el-button> >
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -57,175 +76,166 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.loginBox { .loginBox {
width: 100vw; width: 100%;
height: 100vh; height: 100vh;
background-image: url("@/assets/image/loginbg.jpg"); background-image: url("@/assets/image/loginbg.jpg");
background-size: cover; // background-size: cover;
background-position: center; // background-position: center;
background-repeat: no-repeat; // background-repeat: no-repeat;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
// padding: 0 20px;
} }
input {
background-color: #00000000; /* 透明背景 */
border: none; /* 无边框 */
outline: none; /* 去除聚焦时的轮廓 */
padding: 0; /* 无内边距 */
margin: 0; /* 无外边距 */
width: 70%;
height: 20px;
font-size: 20px;
/* 其他样式可以根据需要添加 */
}
.inputBox {
width: 90%;
height: 2vw;
background-color: #ff1c1c00;
border: 1px #3a3a3a solid;
border-radius: 20px;
padding: 2px;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
}
input:focus {
border-bottom: 1px solid #000000;
}
.checkBox {
width: 90%;
color: #000;
font-size: 12px;
}
.btnBox {
// div{
// width: 30%;
// }
width: 87%;
display: flex;
justify-content: space-between;
align-items: center;
// background-color: #000;
}
.loginFrom { .loginFrom {
width: 27vw; width: 100%;
height: 30vh; max-width: 400px;
padding: 20px;
background: rgba(255, 255, 255, 0.8);
border-radius: 10px;
// box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between;
align-items: center; align-items: center;
margin: 0 auto; }
// .inputBox {
// // margin-bottom: 20px;
// display: flex;
// align-items: center;
// justify-content: space-between;
// }
el-input{
height: 40px;
}
.checkBox {
width: 100%;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.btnBox {
width: 80%;
display: flex;
justify-content: space-between;
}
.dialog-footer {
text-align: right;
} }
</style> </style>
<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 { login , register } from "@/api/user/user"; import { login, register } from "@/api/user/user";
import storage from '@/utils/Sotrage' import storage from "@/utils/Sotrage";
import TokenService from '@/utils/token' import TokenService from "@/utils/token";
import router from '@/router' import router from "@/router";
import { ref, reactive,onMounted } from "vue"; import { ref, reactive, onMounted } from "vue";
const user=reactive({
username: "", const user = reactive({
password: "", username: "",
password: "",
}); });
//
const remember = ref(false); const remember = ref(false);
const toLogin = async () => { const toLogin = async () => {
console.log(user); if (user.username === "" || user.password === "") {
if(user.username===""||user.username===null||user.password===""||user.password===null){ ElMessage({ message: "请输入完整信息", type: "warning" });
ElMessage({ message: "请输入完整信息", type: 'warning' }) return;
} }
let res=await login(user); let res = await login(user);
if(res.code===200){ if (res.code === 200) {
ElMessage({ message: "登录成功", type: 'success' }) ElMessage({ message: "登录成功", type: "success" });
if(remember.value){ if (remember.value) {
storage.setStorage("username",user.username); storage.setStorage("username", user.username);
storage.setStorage("password",user.password); storage.setStorage("password", user.password);
}else{ } else {
storage.removeStorage("username"); storage.removeStorage("username");
storage.removeStorage("password"); storage.removeStorage("password");
}
TokenService.saveToken(res.token);
router.push("/");
} }
TokenService.saveToken(res.token)
//
router.push('/');
}
}; };
//
const dialogFormVisible = ref(false); const dialogFormVisible = ref(false);
const ruleFormRef = ref(null); const ruleFormRef = ref(null);
//
const ruleForm = reactive({ const ruleForm = reactive({
username: "", username: "",
password: "", password: "",
password2: "", password2: "",
}); });
//
const usernamevalidate = (rule, value, callback) => { const usernamevalidate = (rule, value, callback) => {
if (value === ""||value==null) { if (value === "") {
callback(new Error("请输入账号")); callback(new Error("请输入账号"));
} else {
callback();
} }
callback();
}; };
const validatePass = (rule, value, callback) => { const validatePass = (rule, value, callback) => {
if (value === "") { if (value === "") {
callback(new Error("请输入密码")); callback(new Error("请输入密码"));
} } else {
else {
if (ruleForm.password !== "") { if (ruleForm.password !== "") {
if (!ruleFormRef.value) return; if (!ruleFormRef.value) return;
ruleFormRef.value.validateField("密码不一致"); ruleFormRef.value.validateField("password2");
} }
callback(); callback();
} }
}; };
const validatePass2 = (rule, value, callback) => { const validatePass2 = (rule, value, callback) => {
if (value === "") { if (value === "") {
callback(new Error("请输入确认密码")); callback(new Error("请输入确认密码"));
} } else if (value !== ruleForm.password) {
else if (value !== ruleForm.password) {
callback(new Error("密码不一致")); callback(new Error("密码不一致"));
} } else {
else {
callback(); callback();
} }
}; };
//
const rules = reactive({ const rules = reactive({
username: [ username: [{ validator: usernamevalidate, trigger: "blur" }],
{
// type: "String",
validator: usernamevalidate,
trigger: "blur",
},
],
password: [{ validator: validatePass, trigger: "blur" }], password: [{ validator: validatePass, trigger: "blur" }],
password2: [{ validator: validatePass2, trigger: "blur" }], password2: [{ validator: validatePass2, trigger: "blur" }],
}); });
//
const submitForm = (formEl) => { const submitForm = (formEl) => {
if (!formEl) return; if (!formEl) return;
formEl.validate(async(valid) => { formEl.validate(async (valid) => {
if (valid) { if (valid) {
// console.log("submit!"); let res = await register({
let res =await register({username:ruleForm.username,password:ruleForm.password}); username: ruleForm.username,
if(res.code===200){ password: ruleForm.password,
ElMessage({ message: "注册成功", type: 'success' }) });
dialogFormVisible.value=false; if (res.code === 200) {
}else{ ElMessage({ message: "注册成功", type: "success" });
ElMessage({ message: res.msg, type: 'error' }) dialogFormVisible.value = false;
} else {
ElMessage({ message: res.msg, type: "error" });
} }
} } else {
else {
console.log("error submit!"); console.log("error submit!");
} }
}); });
}; };
onMounted(() => { onMounted(() => {
console.log("onMounted"); user.username = storage.getStorage("username") || "";
user.username=storage.getStorage("username"); user.password = storage.getStorage("password") || "";
user.password=storage.getStorage("password");
}); });
</script> </script>