This commit is contained in:
2024-08-10 20:35:02 +08:00
parent 88233c58e3
commit 90f6ed0bc3
50 changed files with 5333 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
<script setup>
import { Star, Edit, StarFilled, Watch } from '@element-plus/icons-vue'
import { ref, onMounted, onUnmounted, watch } from 'vue';
import FingerprintJS from '@fingerprintjs/fingerprintjs';
import { useRoute } from 'vue-router';
import { request } from '@/lib/request';
import { ElMessage, ElMessageBox } from 'element-plus';
let showToolBar = defineModel();
const emit = defineEmits(['loadComment'])
watch(showToolBar, (newData, oldData) => {
if (newData)
isScrollingUp.value = true;
})
const route = useRoute();
const uuid = route.params.uuid;
let input_comment = ref('')
let input_comment_name = ref('')
let isStarted = ref(false)
let fgId;
let CommentDialogVisible = ref(false)
let isScrollingUp = ref(true);
onMounted(async () => {
window.addEventListener('wheel', handleWheel);
const fp = await FingerprintJS.load();
const result = await fp.get();
fgId = result.visitorId;
});
onUnmounted(() => {
window.removeEventListener('wheel', handleWheel);
});
function handleWheel(event) {
// deltaY > 0 表示向下滚动deltaY < 0 表示向上滚动
isScrollingUp.value = event.deltaY < 0;
showToolBar.value = isScrollingUp.value;
}
let blogLike = async () => {
if (isStarted.value) {
ElMessage({
message: '你已经点过赞啦!',
type: 'success',
})
return;
}
let res = await ServerAPI.async_getRequest(`BlogLike?uuid=${uuid}&fgId=${fgId}`);
try {
if (res && res.status == 'OK') {
if (res.code == 1) {
// 点赞成功
isStarted.value = true;
ElMessage({
message: '点赞成功!',
type: 'success',
})
} else if (res.code == 0) {
// 重复点赞
isStarted.value = true;
ElMessage({
message: '你已经点过赞啦!',
type: 'success',
})
}
} else {
throw new Error('点赞失败')
}
} catch (error) {
// 网络错误等原因
console.log(error)
ElMessage({
message: '点赞失败',
type: 'error',
})
}
}
// 评论按钮触发事件
let blogComment = async () => {
if (!input_comment.value) {
ElMessage({
message: '请先填写评论内容呀~',
type: 'warning'
})
return;
}
if (input_comment.value.length >= 65535) {
ElMessage({
message: '评论内容太长啦~',
type: 'warning'
})
return;
}
CommentDialogVisible.value = true;
}
// 提交评论
let sendComment = async () => {
if (input_comment_name.value.length >= 255) {
ElMessage({
message: '昵称太长啦~',
type: 'warning'
})
return;
}
let res = await ServerAPI.async_postRequest(`PostBlogComment`, {
'uuid': uuid,
'fgId': fgId,
'comment': input_comment.value,
'comment_name': input_comment_name.value ? input_comment_name.value : '匿名',
});
try {
if (res && res.status == 'OK') {
if (res.code == 1) {
// 评论成功
ElMessage({
message: '评论成功!',
type: 'success',
})
CommentDialogVisible.value = false;
// 重新加载评论区内容
emit('loadComment');
return;
} else if (res.code == 0) {
// 评论3次机会用完
ElMessage({
message: '您的评论次数已达上限',
type: 'warning',
})
CommentDialogVisible.value = false;
return;
}
}
throw new Error('评论失败')
} catch (error) {
// 网络错误等原因
console.log(error)
ElMessage({
message: '评论失败',
type: 'error',
})
CommentDialogVisible.value = false;
}
}
</script>
<template>
<transition name="el-zoom-in-bottom">
<div class="tool-bar-container" v-show="isScrollingUp">
<div class="tool-bar">
<el-input v-model="input_comment" autosize type="textarea" class="input-comment"
placeholder="快来留下你的评论吧~" clearable />
<el-button type="primary" :icon="Edit" class="button" circle @click="blogComment"></el-button>
<el-button type="danger" :icon="isStarted ? StarFilled : Star" class="button" @click="blogLike"
circle></el-button>
</div>
<el-dialog v-model="CommentDialogVisible" title="提示">
<div style="display: flex;flex-direction: column;gap: 5px;">
<div>每篇文章最多可发布3条评论确认要现在发布吗</div>
<div>另外您可选择留下昵称</div>
<el-input v-model="input_comment_name" placeholder="昵称(可选)" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="CommentDialogVisible = false">取消</el-button>
<el-button type="primary" @click="sendComment">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</transition>
</template>
<style scoped>
.tool-bar-container {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
/* height: 60px; */
background-color: #ffffff;
box-shadow: 0px 0px 9px 1px #ddd;
display: flex;
justify-content: center;
align-items: center;
}
.tool-bar {
width: 100%;
max-width: 600px;
display: flex;
align-items: center;
justify-content: center;
padding: 12px 20px;
}
.input-comment {
margin-right: 12px;
}
@media screen and (max-width: 570px) {
.button {
background-color: none;
}
}
</style>

View File

@@ -0,0 +1,78 @@
<script setup lang="ts">
</script>
<template>
<div @click="$emit('closeAgreement')" class="agreement-bcc">
<div class="agreement-container" onclick="event.stopPropagation()">
<div class="title">网站使用协议</div>
<li class="content">欢迎使用本网站在使用本网站之前请仔细阅读以下使用协议</li>
<li class="content">关于网站本网站是个人创建和维护的主要用于收藏各类资源和工具编写关于合法计算机技术的日记并提供与我交流的联系方式</li>
<li class="content">资源收藏声明本网站的个人收藏资源个人收藏工具栏目包含但不限于第三方链接这些资源仅供个人学习和参考本站对这些第三方链接及其内容不作任何形式的推广或认可链接内容观点或相关信息归原作者或所有者所有与本网站无关</li>
<li class="content">风险和责任访问者在使用这些第三方链接时应自行判断其内容的适用性并自行承担相关风险本网站及其所有者不承担因使用这些链接而产生的任何直接或间接损失的责任</li>
<li class="content">内容和交流本网站的日记部分包含对合法计算机技术的个人见解和经验分享访问者可以通过提供的联系方式与我就计算机技术话题进行合法交流</li>
<li class="content">版权和知识产权本网站的内容包括文本图像和代码除非另有声明均为本网站所有者个人创作并拥有版权未经许可不得复制分发或以其他方式使用这些内容</li>
<li class="content">同意协议通过使用或浏览本网站您表示您已阅读理解并同意遵守本协议的条款如果您不同意本协议的任何部分<u>停止使用</u>本网站</li>
<li class="content">变更和更新本网站的所有者保留随时更新或修改本使用协议的权利任何此类更改将在本网站上发布并生效</li>
<div class="subtitle">本使用协议的目的是确保网站的有效运行并保护访问者及网站所有者的合法权益感谢您的理解和支持</div>
</div>
</div>
</template>
<style scoped>
.agreement-bcc{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.15);
z-index: 1000;
display: flex;
align-items: center;
}
.agreement-container{
height: 75%;
width: 80%;
max-width: 700px;
padding: 40px;
border-radius: 12px;
box-sizing: border-box;
margin: auto;
background-color: #fff;
overflow-y: scroll;
transition: all 0.4s;
}
.agreement-container>.title{
font-size: 42px;
padding-bottom: 10px;
border-bottom: 2px solid #ddd;
margin-bottom: 20px;
transition: all 0.4s;
}
.agreement-container>.subtitle{
font-size: 18px;
color: #666;
margin-top: 20px;
transition: all 0.4s;
}
.agreement-container>.content{
font-size: 14px;
font-weight: 600;
margin: 15px 0;
line-height: 20px;
}
.agreement-container>.content>u{
text-decoration-thickness: 2px;
text-underline-offset: 3px;
}
@media screen and (max-width: 450px) {
.agreement-container{
padding: 25px;
}
.agreement-container>.title{
font-size: 28px;
}
.agreement-container>.subtitle{
font-size: 14px;
}
}
</style>

View File

@@ -0,0 +1,162 @@
<script setup lang="ts">
import copyText from '@/lib/copyText';
let copyTextwithMsg = (text : string) => {
if(copyText(text)){
ElMessage({
message: '复制成功',
type: 'success',
})
}else{
ElMessage({
message: '复制失败',
type: 'error',
})
}
}
</script>
<template>
<div class="footer-divider"></div>
<div class="footer-container">
<div class="left-container">
<a href="https://beian.miit.gov.cn/">
<div class="fillings">备案号渝ICP备2023009516号-1</div>
</a>
<div class="copyright">Copyright ©2020-2024 TONE All Rights Reserved.</div>
</div>
<div class="right-container">
<el-popover trigger="click" placement="top" :width="160">
<p>QQ号3341154833</p>
<div style="text-align: center; margin: 0">
<el-button size="small" type="primary" @click="copyTextwithMsg('3341154833')">复制</el-button>
</div>
<template #reference>
<div class="icon">
<svg t="1705909811918" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="5851" width="24" height="24">
<path
d="M824.8 613.2c-16-51.4-34.4-94.6-62.7-165.3C766.5 262.2 689.3 112 511.5 112 331.7 112 256.2 265.2 261 447.9c-28.4 70.8-46.7 113.7-62.7 165.3-34 109.5-23 154.8-14.6 155.8 18 2.2 70.1-82.4 70.1-82.4 0 49 25.2 112.9 79.8 159-26.4 8.1-85.7 29.9-71.6 53.8 11.4 19.3 196.2 12.3 249.5 6.3 53.3 6 238.1 13 249.5-6.3 14.1-23.8-45.3-45.7-71.6-53.8 54.6-46.2 79.8-110.1 79.8-159 0 0 52.1 84.6 70.1 82.4 8.5-1.1 19.5-46.4-14.5-155.8z"
p-id="5852" fill="#8a8a8a"></path>
</svg>
</div>
</template>
</el-popover>
<el-popover trigger="click" placement="top" :width="130">
<p>微信号tone0121</p>
<div style="text-align: center; margin: 0">
<el-button size="small" type="primary" @click="copyTextwithMsg('tone0121')">复制</el-button>
</div>
<template #reference>
<div class="icon">
<svg t="1705909888071" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="7135" width="24" height="24">
<path
d="M664.250054 368.541681c10.015098 0 19.892049 0.732687 29.67281 1.795902-26.647917-122.810047-159.358451-214.077703-310.826188-214.077703-169.353083 0-308.085774 114.232694-308.085774 259.274068 0 83.708494 46.165436 152.460344 123.281791 205.78483l-30.80868 91.730191 107.688651-53.455469c38.558178 7.53665 69.459978 15.308661 107.924012 15.308661 9.66308 0 19.230993-0.470721 28.752858-1.225921-6.025227-20.36584-9.521864-41.723264-9.521864-63.862493C402.328693 476.632491 517.908058 368.541681 664.250054 368.541681zM498.62897 285.87389c23.200398 0 38.557154 15.120372 38.557154 38.061874 0 22.846334-15.356756 38.156018-38.557154 38.156018-23.107277 0-46.260603-15.309684-46.260603-38.156018C452.368366 300.994262 475.522716 285.87389 498.62897 285.87389zM283.016307 362.090758c-23.107277 0-46.402843-15.309684-46.402843-38.156018 0-22.941502 23.295566-38.061874 46.402843-38.061874 23.081695 0 38.46301 15.120372 38.46301 38.061874C321.479317 346.782098 306.098002 362.090758 283.016307 362.090758zM945.448458 606.151333c0-121.888048-123.258255-221.236753-261.683954-221.236753-146.57838 0-262.015505 99.348706-262.015505 221.236753 0 122.06508 115.437126 221.200938 262.015505 221.200938 30.66644 0 61.617359-7.609305 92.423993-15.262612l84.513836 45.786813-23.178909-76.17082C899.379213 735.776599 945.448458 674.90216 945.448458 606.151333zM598.803483 567.994292c-15.332197 0-30.807656-15.096836-30.807656-30.501688 0-15.190981 15.47546-30.477129 30.807656-30.477129 23.295566 0 38.558178 15.286148 38.558178 30.477129C637.361661 552.897456 622.099049 567.994292 598.803483 567.994292zM768.25071 567.994292c-15.213493 0-30.594809-15.096836-30.594809-30.501688 0-15.190981 15.381315-30.477129 30.594809-30.477129 23.107277 0 38.558178 15.286148 38.558178 30.477129C806.808888 552.897456 791.357987 567.994292 768.25071 567.994292z"
fill="#8a8a8a" p-id="7136"></path>
</svg>
</div>
</template>
</el-popover>
<el-popover trigger="click" placement="top" :width="180">
<p>邮箱号3341154833@qq.com</p>
<div style="text-align: center; margin: 0">
<el-button size="small" type="primary" @click="copyTextwithMsg('3341154833@qq.com')">复制</el-button>
</div>
<template #reference>
<div class="icon">
<svg t="1705909952800" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="8336" width="24" height="24">
<path
d="M677.288 536.903l-167.315 156.052-170.532-156.052-246.146 230.058h831.748l-247.756-230.058zM954.002 287.541v423.114l-238.1-209.145 238.1-213.969zM64.336 290.756l231.666 212.361-231.666 207.534v-419.895zM93.294 234.45l418.287 389.33 413.461-389.33h-831.748z"
fill="#8a8a8a" p-id="8337"></path>
</svg>
</div>
</template>
</el-popover>
<a class="icon" href="https://github.com/tonecn">
<svg t="1705909977594" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="9342" width="24" height="24">
<path
d="M511.957333 21.333333C241.024 21.333333 21.333333 240.981333 21.333333 512c0 216.832 140.544 400.725333 335.573334 465.664 24.490667 4.394667 32.256-10.069333 32.256-23.082667 0-11.690667 0.256-44.245333 0-85.205333-136.448 29.610667-164.736-64.64-164.736-64.64-22.314667-56.704-54.4-71.765333-54.4-71.765333-44.586667-30.464 3.285333-29.824 3.285333-29.824 49.194667 3.413333 75.178667 50.517333 75.178667 50.517333 43.776 75.008 114.816 53.333333 142.762666 40.789333 4.522667-31.658667 17.152-53.376 31.189334-65.536-108.970667-12.458667-223.488-54.485333-223.488-242.602666 0-53.546667 19.114667-97.322667 50.517333-131.669334-5.034667-12.330667-21.930667-62.293333 4.778667-129.834666 0 0 41.258667-13.184 134.912 50.346666a469.802667 469.802667 0 0 1 122.88-16.554666c41.642667 0.213333 83.626667 5.632 122.88 16.554666 93.653333-63.488 134.784-50.346667 134.784-50.346666 26.752 67.541333 9.898667 117.504 4.864 129.834666 31.402667 34.346667 50.474667 78.122667 50.474666 131.669334 0 188.586667-114.730667 230.016-224.042666 242.090666 17.578667 15.232 33.578667 44.672 33.578666 90.453334v135.850666c0 13.141333 7.936 27.605333 32.853334 22.869334C862.250667 912.597333 1002.666667 728.746667 1002.666667 512 1002.666667 240.981333 783.018667 21.333333 511.957333 21.333333z"
p-id="9343" fill="#8a8a8a"></path>
</svg>
</a>
</div>
</div>
</template>
<style scoped>
.footer-divider {
height: 1px;
width: 100%;
background-color: #eee;
}
.footer-container {
/* height: 100%; */
height: 100px;
width: 100%;
margin: 0 auto;
max-width: 1170px;
display: flex;
justify-content: space-between;
align-items: center;
}
.left-container {
font-size: 12px;
margin-left: 25px;
cursor: default;
}
.fillings {
margin-bottom: 5px;
cursor: pointer;
}
.right-container {
margin-right: 25px;
display: flex;
}
.right-container>.icon {
cursor: pointer;
margin: 0 8px;
width: 30px;
height: 30px;
/* background-color: #aaa; */
border: 1.5px solid #eee;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
transition: background-color 0.3s;
}
.right-container>.icon:hover {
background-color: #eee;
}
.right-container>.icon>.icon {
width: 20px;
height: 20px;
}
@media screen and (max-width: 550px) {
.footer-container {
flex-direction: column;
align-items: center;
justify-content: flex-start;
margin-bottom: 20px;
}
.left-container {
margin: 20px 0px;
margin-bottom: 10px;
text-align: center;
}
.right-container {
margin: 0 0;
}
}
</style>

View File

@@ -0,0 +1,180 @@
<script setup lang="ts">
</script>
<template>
<div class="main-container">
<div class="header-container">
<div class="header-left">
<div>
<RouterLink :to="{ name: 'home' }" v-if="$route.name == 'home'">
<div class="emoji">🍭</div>
</RouterLink>
<RouterLink :to="{ name: 'home' }" v-else>
<div class="title">特恩(TONE)</div>
</RouterLink>
</div>
<div class="more" tabindex="0" id="header-more">
<svg t="1705913460674" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="10513" width="20" height="20">
<path
d="M150.528 431.104q37.888 0 58.368 24.064t20.48 51.712l0 11.264q0 34.816-17.92 58.88t-59.904 24.064l-7.168 0q-38.912 0-61.952-21.504t-23.04-59.392l0-14.336q0-13.312 5.632-26.624t15.872-24.064 25.6-17.408 33.792-6.656l10.24 0zM519.168 431.104q37.888 0 58.368 24.064t20.48 51.712l0 11.264q0 34.816-17.92 58.88t-59.904 24.064l-7.168 0q-38.912 0-61.952-21.504t-23.04-59.392l0-14.336q0-13.312 5.632-26.624t15.872-24.064 25.6-17.408 33.792-6.656l10.24 0zM887.808 431.104q37.888 0 58.368 24.064t20.48 51.712l0 11.264q0 34.816-17.92 58.88t-59.904 24.064l-7.168 0q-38.912 0-61.952-21.504t-23.04-59.392l0-14.336q0-13.312 5.632-26.624t15.872-24.064 25.6-17.408 33.792-6.656l10.24 0z"
p-id="10514"></path>
</svg>
</div>
</div>
<div class="header-right header-right-hidden" id="header-right">
<div class="link-list">
<RouterLink :to="{ name: 'resource' }" v-show="true">
<div class="link" :class="{ 'link-chosen': $route.name === 'resource' }">资源</div>
</RouterLink>
<RouterLink :to="{ name: 'download' }" v-show="true">
<div class="link" :class="{ 'link-chosen': $route.name === 'download' }">下载</div>
</RouterLink>
<RouterLink :to="{ name: 'blog' }" v-show="true">
<div class="link" :class="{ 'link-chosen': $route.name === 'blog' }">博客</div>
</RouterLink>
<RouterLink :to="{ name: 'login' }" v-show="true">
<div class="link" :class="{ 'link-chosen': $route.name === 'login' || $route.name === 'dashboard'}">控制台</div>
</RouterLink>
</div>
</div>
</div>
<div class="header-divider"></div>
</div>
<div class="main-container-block"></div>
</template>
<style scoped>
.main-container {
/* height: 69px; */
z-index: 500;
width: 100%;
position: fixed;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
background-color: rgba(255, 255, 255, 0.6);
}
.header-container {
/* height: 100%; */
width: 100%;
margin: 0 auto;
padding: 22px 0;
max-width: 1170px;
display: flex;
justify-content: space-between;
align-items: center;
transition: padding 0.2s;
}
.header-left,
.header-right {
margin: 0 25px;
}
.header-left .emoji {
font-size: 25px;
cursor: pointer;
}
.header-left .title {
/* 因为棒棒糖的高度为35需要保持统一 */
height: 35px;
line-height: 35px;
font-size: 18px;
font-weight: 600;
letter-spacing: 5px;
cursor: pointer;
color: #333;
}
.header-left .more {
/* 因为棒棒糖的高度为35需要保持统一 */
height: 35px;
display: none;
}
.link-list {
display: flex;
justify-content: flex-end;
align-items: center;
}
.link-list .link {
margin: 0 20px;
cursor: pointer;
color: #666;
transition: color 0.2s;
border-bottom: 3px solid rgba(0, 0, 0, 0);
}
.link-list .link:hover {
color: #000;
}
.link-list .link-chosen {
border-bottom: 3px solid #e03ebf;
}
.header-divider {
height: 1px;
width: 100%;
background-color: #eee;
}
.main-container-block {
height: 80px;
width: 100%;
transition: height 0.2s;
/* background-color: #fff; */
}
@media screen and (max-width: 800px) {
.header-container {
padding: 15px 0;
}
.main-container-block {
height: 65px;
}
.header-container {
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
.header-left {
width: 100%;
display: flex;
justify-content: space-between;
}
.header-left .more {
display: flex;
align-content: center;
flex-wrap: wrap;
margin-right: 50px;
cursor: pointer;
}
.header-right-hidden {
display: none;
}
.header-right {
/* width: 100%; */
margin-top: 15px;
}
.link-list {
display: flex;
flex-direction: column;
margin: 20px 10px;
}
.link-list .link {
font-size: 23px;
margin-top: 10px;
}
}
</style>

View File

@@ -0,0 +1,259 @@
<script setup>
import ServerSDK from '@/assets/ServerSDK';
import { onBeforeMount, onMounted, ref } from 'vue';
let imageBase64 = ref('');
const emit = defineEmits(['fail', 'success'])
let onVerifying = ref(false);
let onVerifyFail = ref(false);
onBeforeMount(async () => {
try {
let res = await ServerSDK.GetRotationVerification();
imageBase64.value = res;
} catch (error) {
console.log("获取图像验证码失败:"+error);
emit('fail');
}
})
onMounted(() => {
let slider = document.getElementById('RV-slider');
let imageEle = document.getElementById('RV-image');
let isDragging = false;// 正在移动标志位
let silderMoveable = true;// 是否可以开始移动标识位
let startX;
let deltaX;// 拖动距离
slider.addEventListener('mousedown', function(e) {
if(silderMoveable)
{
isDragging = true;
startX = e.clientX;
onVerifyFail.value = false;
}
})
slider.addEventListener('touchstart', function(e) {
if(silderMoveable) {
e.preventDefault();
isDragging = true;
startX = e.touches[0].clientX;
onVerifyFail.value = false;
}
}, { passive: false });
document.addEventListener('mousemove', function(e) {
if (isDragging) {
silderMoveable = false;// 产生了位移,则需等待验证后才可再次移动
deltaX = e.clientX - startX;
// 对位移距离限幅
if(deltaX < 0)
deltaX = 0;
if(deltaX > 200)
deltaX = 200;
// 调整滑块条位置样式
slider.style.transform = ` translateX(${deltaX}px)`;
// 调整图片旋转样式 200 -> 360映射 y = 9/5x
imageEle.style.transform = `rotate(${deltaX*9/5}deg)`
}
});
document.addEventListener('touchmove', function(e) {
if (isDragging) {
e.preventDefault();
silderMoveable = false;
deltaX = e.touches[0].clientX - startX;
if(deltaX < 0) deltaX = 0;
if(deltaX > 200) deltaX = 200;
slider.style.transform = `translateX(${deltaX}px)`;
imageEle.style.transform = `rotate(${deltaX*9/5}deg)`;
}
}, { passive: false });
document.addEventListener('mouseup', async () => {
if(isDragging)
{
isDragging = false;
if(!deltaX)
{
silderMoveable = true;// 位移距离为0无需验证可以继续移动
}else{
try {
onVerifying.value = true;
let res = await ServerSDK.CheckRotationVerification(deltaX * 9 / 5);
switch (res) {
case 1:
// 验证成功
emit('success');
break;
case -2:
// 可以再试一次
onVerifyFail.value = true;
slider.style.transition = "transform 0.6s";
slider.style.transform = "translateX(0px)";
imageEle.style.transition = "transform 0.6s";
imageEle.style.transform = "rotate(0deg)";
setTimeout(() => {
isDragging = false;
silderMoveable = true;
slider.style.transition = "transform 0s";
imageEle.style.transition = "transform 0s";
}, 600);
break;
case -1:
console.log('验证次数过多,请重试')
emit('fail');
break;
default:
// 大概率是0过期和不存在
console.log('验证session过期或不存在')
emit('fail');
break;
}
} catch (error) {
console.log("图像验证码错误:"+error);
emit('fail');
}finally{
onVerifying.value = false;
}
}
}
});
document.addEventListener('touchend', async () => {
if(isDragging)
{
isDragging = false;
if(!deltaX)
{
silderMoveable = true;// 位移距离为0无需验证可以继续移动
}else{
try {
onVerifying.value = true;
let res = await ServerSDK.CheckRotationVerification(deltaX * 9 / 5);
switch (res) {
case 1:
// 验证成功
emit('success');
break;
case -2:
// 可以再试一次
onVerifyFail.value = true;
slider.style.transition = "transform 0.6s";
slider.style.transform = "translateX(0px)";
imageEle.style.transition = "transform 0.6s";
imageEle.style.transform = "rotate(0deg)";
setTimeout(() => {
isDragging = false;
silderMoveable = true;
slider.style.transition = "transform 0s";
imageEle.style.transition = "transform 0s";
}, 600);
break;
case -1:
console.log('验证次数过多,请重试')
emit('fail');
break;
default:
// 大概率是0过期和不存在
console.log('验证session过期或不存在')
emit('fail');
break;
}
} catch (error) {
console.log("图像验证码错误:"+error);
emit('fail');
}finally{
onVerifying.value = false;
}
}
}
});
})
</script>
<template>
<transition name="el-fade-in-linear">
<div class="verification-bcc" @click="$emit('fail')">
<div class="verification-container" onclick="event.stopPropagation()">
<div class="title">安全验证</div>
<div class="subtitle">{{ onVerifying ? "正在验证,请稍后..." : (onVerifyFail?"验证失败,请再试一次":"拖动滑块,使图片角度为水平") }}</div>
<div class="image-container">
<img :src="imageBase64" alt="" id="RV-image">
</div>
<div class="slide-container">
<div class="slider" id="RV-slider">
<svg t="1706696449802" class="icon" viewBox="0 0 1024 1024" fill="#666" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1924" width="18" height="18"><path d="M567.32505 547.18536c20.970614-21.479197 20.970614-56.307424 0-77.790714L185.251168 77.115332c-20.971637-21.47715-54.975079-21.47715-75.948763 0-20.973684 21.484314-20.973684 56.30947 0 77.793784l344.188016 353.383446-344.188016 353.384469c-20.973684 21.484314-20.973684 56.311517 0 77.79276 20.971637 21.482267 54.975079 21.482267 75.948763 0l382.072858-392.280337 0.001024-0.004094zM440.60802 154.908092l344.18597 353.383446-344.18597 353.385493c-20.973684 21.484314-20.973684 56.311517 0 77.79276 20.972661 21.482267 54.975079 21.482267 75.949786 0l382.074905-392.281361c20.966521-21.478174 20.966521-56.307424 0-77.790714L516.555759 77.115332c-20.972661-21.47715-54.975079-21.47715-75.949786 0-20.971637 21.48329-20.971637 56.30947 0.002047 77.79276z" p-id="1925"></path></svg>
</div>
</div>
</div>
</div>
</transition>
</template>
<style scoped>
.verification-bcc{
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: #00000022;
z-index: 2000;
display: flex;
justify-content: center;
align-items: center;
}
.verification-container{
width: 300px;
height: 400px;
background-color: #fff;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 15px;
}
.verification-container>.title{
margin-top: 25px;
color: #888;
}
.verification-container>.subtitle{
margin-top: 8px;
}
.verification-container>.image-container{
display: flex;
margin-top: 28px;
width: 160px;
height: 160px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.verification-container>.image-container>img{
width: 226px;
height: 226px;
transform: rotate(0deg);
background-color: gray;
}
.verification-container>.slide-container{
width: 240px;
height: 40px;
border-radius: 20px;
background-color: #eeeeee;
margin-top: 25px;
display: flex;
align-items: center;
}
.verification-container>.slide-container>.slider{
width: 45px;
height: 45px;
background-color: #fff;
border-radius: 50%;
box-shadow: 0px 1px 5px 3px #ccc;
text-align: center;
line-height: 50px;
cursor: pointer;
position: relative;
transform: translateX(0);
}
</style>