优化代码

This commit is contained in:
pengxiaolong
2025-08-15 13:05:19 +08:00
parent 784a19bdda
commit 15335e8921
17 changed files with 1501 additions and 133 deletions

6
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"core-js": "^3.8.3",
"echarts": "^5.6.0",
"element-plus": "^2.10.4",
"goeasy": "^2.13.21",
"pinia": "^3.0.3",
"qwebchannel": "^6.2.0",
"vue": "^3.2.13",
@@ -7376,6 +7377,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/goeasy": {
"version": "2.13.21",
"resolved": "https://registry.npmjs.org/goeasy/-/goeasy-2.13.21.tgz",
"integrity": "sha512-KxzYC9KRu02tt3Cv+9QHqP/yD6kl/kmI07UZw6BzRFjJUpNNuefZTD/bKC9a9nYbmLWYxYneoQqowHwl2GaEPw=="
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",

View File

@@ -12,6 +12,7 @@
"core-js": "^3.8.3",
"echarts": "^5.6.0",
"element-plus": "^2.10.4",
"goeasy": "^2.13.21",
"pinia": "^3.0.3",
"qwebchannel": "^6.2.0",
"vue": "^3.2.13",

View File

@@ -9,6 +9,18 @@ export function getVxQrcode() {
export function getScanResult(data) {
return getAxios({ url: 'user/check/' + data})
}
//获取用户信息
export function getUserInfo(data) {
return postAxios({ url: 'user/getUserInfo',data})
}
//修改用户信息
export function editUserInfo(data) {
return postAxios({ url: 'user/updateUserInfo', data })
}
//检查用户名
export function checkUsername(data) {
return postAxios({ url: 'user/checkUserName', data })
}
//注册
export function register(data) {
return postAxios({ url: 'user/registerWithMail', data })
@@ -90,3 +102,19 @@ export function topPkInfo(data) {
export function cancelTopPkInfo(data) {
return postAxios({ url: 'user/cancelPin', data })
}
//获取积分详情
export function getIntegralDetail(data) {
return postAxios({ url: 'user/pointsDetail', data })
}
//获取PK记录
export function getPkRecord(data) {
return postAxios({ url: 'user/handlePkInfo', data })
}
//签到
export function signIn(data) {
return postAxios({ url: 'user/signIn', data })
}
//修改邮箱
export function editEmail(data) {
return postAxios({ url: 'user/updateUserMail', data })
}

File diff suppressed because it is too large Load Diff

View File

@@ -102,7 +102,7 @@
</el-splitter>
</div>
<!-- 确认删除弹窗 -->
<el-dialog
<el-dialog center
class="center-dialog"
v-model="centerDialogVisible"
title="提示"
@@ -328,8 +328,7 @@ onUnmounted(() => {
.card-content {
width: 90%;
height: 100%;
border-radius: 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
border-radius: 10px;
background-image: url(../../assets/PKbackground.png);
background-size: 100% 100%;
transition: all 0.4s ease;
@@ -337,7 +336,7 @@ onUnmounted(() => {
align-items: center;
}
.card-content:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.8);
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
transform: scale(1.05);
opacity: 0.8;
}
@@ -397,11 +396,19 @@ onUnmounted(() => {
.modify-icon:hover {
transform: scale(1.2);
}
.modify-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.delete-icon {
width: 30px;
height: 30px;
transition: all 0.4s ease;
}
.delete-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.delete-icon:hover {
transform: scale(1.2);
}
@@ -474,6 +481,10 @@ onUnmounted(() => {
transform: scale(1.1);
opacity: 0.8;
}
.Confirm:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.Reset {
width: 400px;
height: 50px;
@@ -492,6 +503,10 @@ onUnmounted(() => {
transform: scale(1.1);
opacity: 0.8;
}
.Reset:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.center-dialog {
background-color: #03aba8;
}

View File

@@ -125,6 +125,11 @@ import {
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
} from "vue";
import {getPkRecord} from "@/api/account";
import { ElMessage } from "element-plus";
import {getPromiseStorage } from "@/utils/storage.js";
const user = ref(null); // 用户信息
const refname = ref("");
const segmentedvalue = ref(1);
const options = [
@@ -141,9 +146,44 @@ const options = [
SelectedIcon: require("@/assets/InvitationSelected.png"),
},
];
const list = ref([{}, {}, {}, {}, {}, {}, {}]);
const list = ref([]);
const page = ref(0);
const IPKPostedData = ref([]);
const InvitationData = ref([]);
//获取PK记录列表
function PkRecord() {
getPkRecord({
type: segmentedvalue.value,
userId: user.value.id,
page: page.value,
size: 10,
}).then((res) => {
console.log(res);
if (segmentedvalue.value === 1) {
IPKPostedData.value.push(...res);
list.value = IPKPostedData.value;
}else{
InvitationData.value.push(...res);
list.value = InvitationData.value;
}
})
}
// 加载更多
function load() {}
// 组件挂载完成后执行
onMounted(() => {
getPromiseStorage("user")
.then((res) => {
user.value = res;
PkRecord();
})
.catch((err) => {
console.log(err);
});
});
onUpdated(() => {
// 组件更新后执行
});

View File

@@ -108,7 +108,9 @@
@blur="handleChange()"
/>
<div class="myanchor">
<div class="myanchor-btn" @click="myAnchorDialogVisible = true">选择我的主播</div>
<div class="myanchor-btn" @click="myAnchorDialogVisible = true">
选择我的主播
</div>
</div>
</div>
<div class="country">
@@ -176,7 +178,8 @@
</el-splitter>
</div>
<!-- 确认删除弹窗 -->
<el-dialog
<el-dialog
center
class="center-dialog"
v-model="centerDialogVisible"
title="提示"
@@ -192,41 +195,82 @@
</template>
</el-dialog>
<!-- 选择我的主播弹窗 -->
<el-dialog v-model="myAnchorDialogVisible" title="选择我的主播库主播" width="800">
<el-dialog align-center center v-model="myAnchorDialogVisible" title="选择我的主播库主播" width="800">
<div class="myanchor-content">
<div class="myanchor-list">
<div class="anchor-library-card" v-for="(item, index) in anchorLibrary" :key="index" @click="selectStreamerLibrary(item)" :style="{transform: item == selectAnchor? 'scale(1.05)':'scale(1)'}">
<div class="card-content">
<div class="card-avatar">
<img
style="width: 100%; height: 100%; border-radius: 100px"
:src="item.headerIcon"
alt=""
/>
</div>
<div class="personalInformation">
<div class="name">{{ item.anchorId }}</div>
<div class="GenderAndCountry">
<div
class="Gender"
:style="{
background: item.gender == 1 ? '#59D8DB' : '#F3876F',
}"
>
{{ item.gender == 1 ? "男" : "女" }}
</div>
<div class="Country">{{ item.country }}</div>
</div>
<div
class="anchor-library-card"
v-for="(item, index) in anchorLibrary"
:key="index"
@click="selectStreamerLibrary(item)"
>
<div class="card-content" :style="{ backgroundImage: item == selectAnchor ? '' : '',background: item == selectAnchor ? '#FFFBFA' : '',border: item == selectAnchor ? '1px solid #F4D0C9' : ''}">
<div class="card-avatar">
<img
style="width: 100%; height: 100%; border-radius: 100px"
:src="item.headerIcon"
alt=""
/>
</div>
<div class="personalInformation">
<div class="name">{{ item.anchorId }}</div>
<div class="GenderAndCountry">
<div
class="Gender"
:style="{
background: item.gender == 1 ? '#59D8DB' : '#F3876F',
}"
>
{{ item.gender == 1 ? "男" : "女" }}
</div>
<div class="Country">{{ item.country }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="myAnchorDialogVisible = false">取消</div>
<div class="Confirm" @click="handleSelect">确认</div>
<div class="Confirm" @click="myAnchorDialogConfirm()">确认</div>
</div>
</div>
</el-dialog>
<!-- 置顶弹窗 -->
<el-dialog align-center center v-model="topPositionstate" title="置顶" width="800">
<div class="topPosition-content">
<div class="topPosition-content-title">
置顶后该用户将在首页置顶并在指定时长内享有置顶特权置顶时长
不足1小时系统将按1小时计算积分扣除请选择置顶时长
</div>
<div class="topPosition-input">
<el-select-v2
v-model="topPositionvalue"
:options="topPositionOptions"
placeholder="请选择置顶时长"
style="width: 100%"
size="large"
filterable
/>
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="topPositionstate = false">取消</div>
<div class="Confirm" @click="topPositionstateConfirm()">确认</div>
</div>
</div>
</el-dialog>
<!-- 取消置顶弹窗 -->
<el-dialog center v-model="cancelTopPositionstate" title="取消置顶" width="700" align-center>
<div class="cancelTopPosition">
<div class="cancelTopPosition-content">
您确定要取消置顶吗?取消置顶后该用户将不再享有置顶特权但仍可继续参与
PK挑战若置顶时长不足1小时系统将按1小时计算积分扣除取消后按实际使用时长比例返还剩余积分是否确认执行此操作?
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="cancelTopPositionstate = false">取消</div>
<div class="Confirm" @click="cancelTopPositionstateConfirm()">确认</div>
</div>
</div>
</el-dialog>
</template>
<script setup>
@@ -245,7 +289,7 @@ import {
delPkInfo,
topPkInfo,
cancelTopPkInfo,
getAnchorList
getAnchorList,
} from "@/api/account";
import { TimestamptolocalTime } from "@/utils/timeConversion.js";
import { getCountryNamesArray } from "../../utils/countryUtil";
@@ -276,25 +320,88 @@ const modifyDialogstateID = ref(null); // 修改弹窗ID
const myAnchorDialogVisible = ref(false); // 选择我的主播弹窗
const anchorLibrary = ref([]); // 我的主播库
const selectAnchor = ref(null); //选中的主播信息
const topPositionstate = ref(false); // 置顶弹窗
const cancelTopPositionstate = ref(false); // 取消置顶弹窗
const topPositiondata = ref(null); // 置顶or取消置顶数据
const topPositionvalue = ref(null); // 置顶时长
const topPositionOptions = ref([]); // 置顶时长选项
// 选择我的主播
function selectStreamerLibrary(item) {
selectAnchor.value = item
selectAnchor.value = item;
}
function myAnchorDialogConfirm() {
AnchorProfilePicture.value = selectAnchor.value.headerIcon.split("/").pop();
anchorName.value = selectAnchor.value.anchorId;
gendervalue.value = selectAnchor.value.gender;
countryvalue.value = selectAnchor.value.country;
myAnchorDialogVisible.value = false;
}
//获取我的主播库数据
function getMyAnchorLibrary() {
getAnchorList({id: user.value.id}).then((res) => {
getAnchorList({ id: user.value.id }).then((res) => {
console.log("anchorLibrary", res);
anchorLibrary.value = res
})
anchorLibrary.value = res;
});
}
// 置顶or取消置顶
function topPosition(item) {
if (item.isPin == false) {
topPositionstate.value = true;
const currentTime = Math.floor(Date.now() / 1000);
topPositionOptions.value = generateTimeOptions(currentTime, item.pkTime);
} else {
cancelTopPositionstate.value = true;
}
topPositiondata.value = item;
}
// 修改
// 确认置顶
function topPositionstateConfirm() {
if (topPositionvalue.value == 0) {
topPositionstate.value = false;
return;
}
topPkInfo({
articleId: topPositiondata.value.id,
pinExpireTime: topPositionvalue.value,
}).then((res) => {
ElMessage.success("置顶成功");
topPositionstate.value = false;
list.value = [];
page.value = 0;
PKInfo();
});
}
// 确认取消置顶
function cancelTopPositionstateConfirm() {
cancelTopPkInfo({articleId: topPositiondata.value.id}).then((res) => {
ElMessage.success(res);
cancelTopPositionstate.value = false;
list.value = [];
page.value = 0;
PKInfo();
});
}
//计算置顶时长
function generateTimeOptions(currentTimestamp, targetTimestamp) {
const timeDiff = targetTimestamp - currentTimestamp;
// 时间差小于0说明已过期
if (timeDiff <= 0) return [{ value: 0, label: "已过期" }];
const hours = Math.ceil(timeDiff / 3600);
const options = Array.from({ length: hours }, (_, i) => {
const hour = i + 1;
return {
value: currentTimestamp + hour * 3600,
label: `${hour}个小时`,
};
});
return options;
}
//修改
function modify(item) {
if (modifyDialogstate.value) {
cancel();
@@ -311,7 +418,7 @@ function modify(item) {
sessionnum.value = item.pkNumber;
remark.value = item.remark;
}
// 取消
// 取消修改
function cancel() {
modifyDialogstateID.value = null;
modifyDialogstate.value = false;
@@ -324,12 +431,14 @@ function cancel() {
sessionnum.value = null;
remark.value = null;
}
// 删除
const deletePKInfodata = ref(null);
function deletePKInfo(item) {
deletePKInfodata.value = item;
centerDialogVisible.value = true;
}
// 确认删除
function deleteAnchor() {
centerDialogVisible.value = false;
@@ -436,7 +545,7 @@ function Reset() {
goldvalue.value = null;
sessionnum.value = null;
remark.value = null;
countryvalue.value = null
countryvalue.value = null;
}
//输入框失去焦点
@@ -530,7 +639,7 @@ watch(refname, async (newQuestion, oldQuestion) => {
width: 90%;
height: 100%;
border-radius: 10px;
background-image: url(../../assets/PKbackground.png);
background-image: url(@/assets/PKbackground.png);
background-size: 100% 100%;
transition: all 0.4s ease;
display: flex;
@@ -623,6 +732,10 @@ watch(refname, async (newQuestion, oldQuestion) => {
.modify-icon:hover {
transform: scale(1.3);
}
.modify-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.delete-icon {
width: 20px;
height: 28px;
@@ -631,6 +744,10 @@ watch(refname, async (newQuestion, oldQuestion) => {
.delete-icon:hover {
transform: scale(1.3);
}
.delete-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.add-anchor-library {
width: 100%;
height: 100%;
@@ -692,6 +809,10 @@ watch(refname, async (newQuestion, oldQuestion) => {
.myanchor-btn:hover {
transform: scale(1.03);
}
.myanchor-btn:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.country {
width: 90%;
height: 50px;
@@ -763,6 +884,10 @@ watch(refname, async (newQuestion, oldQuestion) => {
transition: all 0.4s ease;
border-radius: 25px;
}
.Confirm:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.Confirm:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
transform: scale(1.05);
@@ -786,14 +911,18 @@ watch(refname, async (newQuestion, oldQuestion) => {
transform: scale(1.05);
opacity: 0.8;
}
.myanchor-content{
.Reset:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.myanchor-content {
width: 100%;
height: 600px;
}
.myanchor-list{
.myanchor-list {
width: 100%;
height: 500px;
background-color: #E0F4F1;
background-color: #e0f4f1;
border-radius: 16px;
border: 1px solid #4fcacd;
overflow: auto;
@@ -801,11 +930,43 @@ watch(refname, async (newQuestion, oldQuestion) => {
.myanchor-list::-webkit-scrollbar {
display: none;
}
.myanchor-dialog-btn{
.myanchor-dialog-btn {
width: 100%;
height: 100px;
display: flex;
justify-content:space-around;
justify-content: space-around;
align-items: center;
}
.topPosition-content {
width: 100%;
height: 500px;
display: flex;
align-items: center;
flex-direction: column;
}
.topPosition-content-title {
width: 80%;
height: 100px;
margin-top: 50px;
color: #999999;
font-size: 24px;
}
.topPosition-input {
width: 80%;
margin-top: 70px;
margin-bottom: 70px;
}
.cancelTopPosition{
width: 100%;
height: 400px;
display: flex;
flex-direction: column;
align-items: center;
}
.cancelTopPosition-content{
width: 80%;
color: #999999;
font-size: 24px;
height: 300px;
}
</style>

View File

@@ -8,23 +8,23 @@
mode="scaleToFill"
/>
<div class="points-text">
我的积分:
我的积分:{{ user.points }}
<div class="points-alwaysnum">
9999999999999999999999999999999
</div>
</div>
</div>
<div class="points-list" style="overflow: auto;">
<div class="points-list-item" v-for="(item, index) in pointsList" :key="index">
<div class="points-list-content">
<div class="points-list-content" :style="{background: item.status == 1 ? '#DFFEFC':'#FBECE9'}">
<div class="Event">
签到增加积分
{{ item.info }}
</div>
<div class="points-num">
+200
{{ item.number }}
</div>
<div class="time">
2025-08-01 14:27
{{TimestamptolocalTime(item.time*1000) }}
</div>
</div>
</div>
@@ -41,20 +41,48 @@ import {
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
} from "vue";
const refname = ref('');
const pointsList = ref([{},{},{},{},{},{},{},{},{},{},{},{},{},{}]);
watch(refname, async (newQuestion, oldQuestion) => {
// 变化后执行
});
import {getIntegralDetail} from "@/api/account";
import { ElMessage } from "element-plus";
import {getPromiseStorage } from "@/utils/storage.js";
import { TimestamptolocalTime } from "../../utils/timeConversion";
const pointsList = ref([]);
const user = ref({});//用户信息
const page = ref(0);
//获取积分数据
function getPointsList () {
getIntegralDetail({
page: page.value,
size: 30,
userId: user.value.id,
}).then((res) => {
console.log(res);
pointsList.value.push(...res);
})
}
// 组件挂载完成后执行
onMounted(() => {
// 组件挂载完成后执行
getPromiseStorage("user")
.then((res) => {
user.value = res;
getPointsList()
})
.catch((err) => {
console.log(err);
});
});
onUpdated(() => {
// 组件更新后执行
});
onUnmounted(() => {
// 组件销毁前执行
});
const refname = ref('');
watch(refname, async (newQuestion, oldQuestion) => {
// 变化后执行
});
</script>
<style scoped lang="less">
@@ -106,7 +134,6 @@ onUnmounted(() => {
display: flex;
justify-content: space-around;
align-items: center;
background-color:#E0F4F1;
}
.Event{
color: @Supplementary-text-color;

View File

@@ -7,8 +7,17 @@ import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; // 引入中文语言包
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import GoEasy from 'goeasy'
const goeasy = GoEasy.getInstance({
host:"hangzhou.goeasy.io", //若是新加坡区域singapore.goeasy.io
appkey:"您的common key",
modules:['pubsub']//根据需要传入pubsub或'im或数组方式同时传入
});
const app = createApp(App);
app.config.globalProperties.goeasy = goeasy;
export { goeasy };
app.use(ElementPlus, {
locale: zhCn, // 配置中文
});

View File

@@ -1,6 +1,7 @@
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import emailRegistration from '../views/emailRegistration.vue'
import ActivateEmail from '../views/ActivateEmail.vue'
import { setStorage , getStorage } from '@/utils/storage.js';
const routes = [
{
@@ -13,6 +14,11 @@ const routes = [
name: 'emailRegistration',
component: emailRegistration
},
{
path: '/ActivateEmail',
name: 'ActivateEmail',
component: ActivateEmail
},
{
path: '/nav',
name: 'nav',
@@ -47,23 +53,23 @@ const router = createRouter({
routes
})
// // 添加导航守卫
// router.beforeEach((to, from, next) => {
// // 假设你有一个方法来检查用户是否已登录
// const isAuthenticated = () => {
// return localStorage.getItem('token') !== null;
// };
// 添加导航守卫
router.beforeEach((to, from, next) => {
// 假设你有一个方法来检查用户是否已登录
const isAuthenticated = () => {
return localStorage.getItem('token') !== null;
};
// // 定义需要登录才能访问的路由
// const requiresAuth = ['nav', 'pk', 'Forum', 'Message', 'Mine'];
// 定义需要登录才能访问的路由
const requiresAuth = ['nav', 'pk', 'Forum', 'Message', 'Mine'];
// // 如果需要登录且用户未登录,则重定向到登录页面
// if (requiresAuth.includes(to.name) && !isAuthenticated()) {
// next({ name: 'login' });
// } else {
// next();
// }
// });
// 如果需要登录且用户未登录,则重定向到登录页面
if (requiresAuth.includes(to.name) && !isAuthenticated()) {
next({ name: 'login' });
} else {
next();
}
});
export default router

21
src/utils/goeasy.js Normal file
View File

@@ -0,0 +1,21 @@
import { goeasy } from '../main'
export function goEasyLink(data) {
return new Promise((resolve, reject) => {
goeasy.connect({
id:data.id, //im必填最大长度60字符
data:{"avatar":data.avatar,"nickname":data.nickname},
otp:data.key,
onSuccess: function () { //连接成功
console.log("连接成功");
resolve(true);
},
onFailed: function (error) { //连接失败
console.log("连接失败,错误码:" + error.code + ",错误信息:" + error.content);
},
onProgress:function(attempts) { //连接或自动重连中
console.log("正在重连中..." + attempts);
}
});
})
}

View File

@@ -24,7 +24,9 @@ export function getPromiseStorage(key) {
}
});
}
//清除localStorage
export function clearStorage() {
window.localStorage.clear();
// 删除特定的localStorage
export function clearStorage(key) {
if (key) {
window.localStorage.removeItem(key);
}
}

View File

@@ -0,0 +1,95 @@
<template>
<div class="activate-email">
<div class="activate-email-content">
您的邮箱{{ user.email }},尚未激活请在您的邮箱中点击激活链接激活您的账号
</div>
<div class="activate-email-btn" @click="sendActivateEmail">
重发激活邮件
</div>
</div>
</template>
<script setup>
import {
ref, // 响应式基础
watch, // 侦听器
onMounted, // 组件挂载完成后执行
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
} from "vue";
import {getPromiseStorage} from '@/utils/storage.js';
import {resendEmail} from "@/api/account";
import { useRouter } from 'vue-router';
import { ElMessage } from "element-plus";
const router = useRouter();
const refname = ref('');
function sendActivateEmail() {
resendEmail({
mailAddress:user.value.email,
type:1
}).then(res => {
ElMessage.success('激活邮件已发送,请注意查收。');
router.push('/');
}).catch(err => {
ElMessage.error('激活邮件发送失败,请稍后再试。');
})
}
watch(refname, async (newQuestion, oldQuestion) => {
// 变化后执行
});
const user = ref({});
onMounted(() => {
getPromiseStorage('user').then(res => {
console.log(res);
user.value = res;
});
});
onUpdated(() => {
// 组件更新后执行
});
onUnmounted(() => {
// 组件销毁前执行
});
</script>
<style scoped>
.activate-email{
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
background-image: url(@/assets/bg.png);
background-size: 100% 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.activate-email-content{
font-size: 30px;
color: #4FCACD;
font-weight: bold;
}
.activate-email-btn{
background-color: #4FCACD;
color: #fff;
font-size: 20px;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
margin-top: 50px;
}
.activate-email-btn:hover{
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3);
transform: scale(1.08);
opacity: 0.8;
}
.activate-email-btn:active{
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
</style>

View File

@@ -25,7 +25,7 @@
size="large"
class="input-text"
v-model="refEmail"
placeholder="请输入邮箱"
placeholder="请输入邮箱或用户名"
/>
</div>
<div class="input-Password">
@@ -64,6 +64,7 @@ import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { tokenStore, UserStore } from '@/stores/notice'
import { setStorage , getStorage } from '@/utils/storage.js';
import { goEasyLink } from '@/utils/goeasy.js';
const router = useRouter();
const refname = ref("");
const refEmail = ref(""); // 邮箱
@@ -74,29 +75,42 @@ const token = tokenStore()
const user = UserStore()
// 登录
function EmailLogin() {
// 邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(refEmail.value)) {
ElMessage.error("请输入有效的邮箱地址");
return;
}
// // 邮箱验证
// const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// if (!emailRegex.test(refEmail.value)) {
// ElMessage.error("请输入有效的邮箱地址");
// return;
// }
// 密码验证
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{6,16}$/;
if (!passwordRegex.test(refpassword.value)) {
ElMessage.error("密码必须包含大小写字母和数字长度6-16位");
return;
}
const loading = ElLoading.service({
lock: true,
text: "登录中.....",
background: "rgba(0, 0, 0, 0.7)",
});
login({
email: refEmail.value,
userNameOrEmail: refEmail.value,
// email: refEmail.value,
password: refpassword.value,
}).then((res) => {
console.log(res);
token.setToken(res.token);
setStorage("token", res.token);
setStorage("email", refEmail.value);
setStorage("password", refpassword.value);
user.setUser(res);
setStorage("user", res);
router.push("/nav");
// otp/getopt 调用
goEasyLink().then(() => {
loading.close();
router.push("/nav");
});
});
}
// 登录切换
@@ -145,6 +159,8 @@ watch(refname, async (newQuestion, oldQuestion) => {
});
onMounted(() => {
refEmail.value = getStorage("email");
refpassword.value = getStorage("password");
// 初始化获取二维码
fetchQrcode();
// 设置每两分钟轮询一次
@@ -164,7 +180,7 @@ onUnmounted(() => {
margin: 0;
width: 100vw;
height: 100vh;
background-image: url(../assets/bg.png);
background-image: url(@/assets/bg.png);
background-size: 100% 100%;
display: flex;
flex-direction: column;

View File

@@ -17,6 +17,9 @@
<div class="Email">
<el-input type="text" size="large" class="input-item" v-model="Email" placeholder="请输入邮箱" />
</div>
<div class="Email">
<el-input type="text" size="large" class="input-item" v-model="userName" placeholder="请输入用户名" @blur="userNameBlur"/>
</div>
<div class="Password">
<el-input type="Password" size="large" class="input-item" v-model="Password" show-password placeholder="请输入密码" />
<text class="password-tip">您的密码必须包含大小字母和数字长度在6-16位之间</text>
@@ -26,7 +29,7 @@
</div>
<div class="btn">
<div class="Return" @click="Return">返回</div>
<div class="nextStep"@click="nextStep">下一步</div>
<div class="nextStep" @click="nextStep" >下一步</div>
</div>
</div>
<!-- 完成注册 -->
@@ -43,7 +46,7 @@
</template>
<script setup>
import { register,checkStatus,resendEmail} from "@/api/account"; // 导入登录接口
import { register,checkStatus,resendEmail,checkUsername} from "@/api/account"; // 导入登录接口
import { tokenStore, UserStore } from '@/stores/notice'
import { setStorage , getStorage } from '@/utils/storage.js';
import {
@@ -58,12 +61,36 @@ import { useRouter } from 'vue-router'
const router = useRouter()
const active = ref(0);// 当前步骤
const Email = ref("");// 邮箱
const userName = ref("");// 用户名
const Password = ref("");// 密码
const ConfirmPassword = ref("");// 确认密码
const token = tokenStore()
const user = UserStore()
const userNamebtn = ref(false)
// 用户名失去焦点
function userNameBlur() {
if (userName.value.length < 6 || userName.value.length > 16 || userName.value == '' || userName.value == null) {
ElMessage.error('用户名长度不能小于2不能大于16,不能为空');
return;
}
checkUsername({ userName: userName.value }).then(res => {
if (res==false) {
ElMessage.error('用户名已存在');
userNamebtn.value = false
return;
} else {
ElMessage.success('用户名可用');
userNamebtn.value = true
}
})
}
//下一步
function nextStep() {
//用户名验证
if (userNamebtn.value == false) {
ElMessage.error('用户名已存在');
return;
}
// 邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(Email.value)) {
@@ -78,12 +105,18 @@ function nextStep() {
return;
}
//用户名验证
if (userName.value.length < 6 || userName.value.length > 16 || userName.value == '' || userName.value == null) {
ElMessage.error('用户名长度不能小于2不能大于16,不能为空');
return;
}
// 确认密码验证
if (Password.value !== ConfirmPassword.value) {
ElMessage.error('两次输入的密码不一致');
return;
}
register({password: Password.value, email: Email.value, nickName: '用户' + Math.floor(Math.random() * 1000000),headerIcon:'181754562968_.pic_hd.jpg'}).then(res => {
register({ userName: userName.value,password: Password.value, email: Email.value, nickName: '用户' + Math.floor(Math.random() * 1000000),headerIcon:'181754562968_.pic_hd.jpg'}).then(res => {
active.value = active.value + 1;
check(res.id);
token.setToken(res.token);
@@ -195,14 +228,14 @@ onUnmounted(() => {
opacity: 0.8;
}
.Email{
margin-top: 70px;
margin-top: 30px;
width: 90%;
display: flex;
justify-content: center;
align-items: center;
}
.Password{
margin-top: 50px;
margin-top: 30px;
width: 90%;
display: flex;
flex-direction: column;
@@ -210,7 +243,7 @@ onUnmounted(() => {
align-items: center;
}
.ConfirmPassword{
margin-top: 50px;
margin-top: 30px;
width: 90%;
display: flex;
flex-direction: column;

View File

@@ -89,6 +89,6 @@ onUnmounted(() => {
}
.card-body{
color: #333333;
font-size: 24px;
font-size: 16px;
}
</style>

View File

@@ -645,6 +645,10 @@ onUnmounted(() => {
background-size: 100% 100%;
transition: all 0.4s ease;
}
.search:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.search:hover {
transform: scale(1.2);
opacity: 0.8;
@@ -653,6 +657,10 @@ onUnmounted(() => {
transform: scale(1.2);
opacity: 0.8;
}
.primary:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.infinite-list {
width: 100%;
height: 100%;