From e222de1850c78a8c4da611f0ac74b432effb559f Mon Sep 17 00:00:00 2001
From: Kunagisa <1549184870@qq.com>
Date: Fri, 13 Jun 2025 23:56:10 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/ErrorDialog.vue | 150 +++++++++++++++++++++++++++++
src/components/login_module.vue | 80 +++++++++++++--
src/components/register_module.vue | 111 ++++++++++++++++-----
src/views/index/EditorsMaps.vue | 87 ++++++++++++++++-
src/views/index/MapDetail.vue | 87 ++++++++++-------
5 files changed, 446 insertions(+), 69 deletions(-)
create mode 100644 src/components/ErrorDialog.vue
diff --git a/src/components/ErrorDialog.vue b/src/components/ErrorDialog.vue
new file mode 100644
index 0000000..e40a908
--- /dev/null
+++ b/src/components/ErrorDialog.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/login_module.vue b/src/components/login_module.vue
index 5548dfc..84bd4f5 100644
--- a/src/components/login_module.vue
+++ b/src/components/login_module.vue
@@ -9,7 +9,6 @@
id="username"
v-model="username"
placeholder="请输入QQ号"
- @blur="validateUsername"
:class="{ 'error': usernameError }"
/>
{{ usernameError }}
@@ -21,7 +20,6 @@
id="password"
v-model="password"
placeholder="请输入密码"
- @blur="validatePassword"
:class="{ 'error': passwordError }"
/>
{{ passwordError }}
@@ -34,7 +32,6 @@
id="captcha"
v-model="captcha"
placeholder="请输入验证码"
- @blur="validateCaptcha"
:class="{ 'error': captchaError }"
/>
注册账号
+
@@ -61,6 +64,7 @@
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { userLogin, getCaptcha } from '../api/login'
+import ErrorDialog from './ErrorDialog.vue'
const router = useRouter()
const username = ref('')
@@ -74,6 +78,11 @@ const usernameError = ref('')
const passwordError = ref('')
const captchaError = ref('')
+// 错误弹窗相关
+const showError = ref(false)
+const errorTitle = ref('错误提示')
+const errorMessage = ref('')
+
const validateUsername = () => {
if (!username.value) {
usernameError.value = '请输入QQ号码'
@@ -130,6 +139,12 @@ const isFormValid = computed(() => {
captcha.value
})
+const showErrorMessage = (message, title = '错误提示') => {
+ errorMessage.value = message
+ errorTitle.value = title
+ showError.value = true
+}
+
const refreshCaptcha = async () => {
try {
const response = await getCaptcha()
@@ -139,7 +154,7 @@ const refreshCaptcha = async () => {
captcha.value = '' // 清空验证码输入
} catch (error) {
console.error('获取验证码失败:', error)
- alert('获取验证码失败,请刷新页面重试')
+ showErrorMessage('获取验证码失败,请刷新页面重试')
}
}
@@ -172,10 +187,16 @@ const handleLogin = async () => {
}
} catch (error) {
console.error('登录失败:', error)
- if (error.response && error.response.status === 401) {
- alert('错误的用户名或密码')
+ if (error.response) {
+ switch (error.response.status) {
+ case 401:
+ showErrorMessage('错误的用户名或密码')
+ break
+ default:
+ showErrorMessage(error.response?.data?.message || error.message || '登录失败,请稍后重试')
+ }
} else {
- alert(error.response?.data?.message || error.message || '登录失败,请稍后重试')
+ showErrorMessage(error.message || '登录失败,请稍后重试')
}
// 登录失败时刷新验证码
refreshCaptcha()
@@ -183,7 +204,50 @@ const handleLogin = async () => {
}
const validateForm = () => {
- return validateUsername() && validatePassword() && validateCaptcha()
+ // 重置所有错误信息
+ usernameError.value = ''
+ passwordError.value = ''
+ captchaError.value = ''
+
+ // 验证用户名
+ if (!username.value) {
+ usernameError.value = '请输入QQ号码'
+ return false
+ }
+ if (!/^[/\d/g]+$/.test(username.value)) {
+ usernameError.value = 'QQ号码只能包含数字'
+ return false
+ }
+ if (username.value.length < 4) {
+ usernameError.value = 'QQ号码长度不能小于4个字符'
+ return false
+ }
+
+ // 验证密码
+ if (!password.value) {
+ passwordError.value = '请输入密码'
+ return false
+ }
+ if (password.value.length < 4) {
+ passwordError.value = '密码长度不能小于4个字符'
+ return false
+ }
+ if (password.value.length > 20) {
+ passwordError.value = '密码长度不能超过20个字符'
+ return false
+ }
+
+ // 验证验证码
+ if (!captcha.value) {
+ captchaError.value = '请输入验证码'
+ return false
+ }
+ if (captcha.value.length !== 4) {
+ captchaError.value = '验证码长度不正确'
+ return false
+ }
+
+ return true
}
diff --git a/src/components/register_module.vue b/src/components/register_module.vue
index c51bfbf..0e1346e 100644
--- a/src/components/register_module.vue
+++ b/src/components/register_module.vue
@@ -4,20 +4,20 @@
+
@@ -55,6 +60,7 @@
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { userRegister, getCaptcha } from "@/api/login.js";
+import ErrorDialog from './ErrorDialog.vue'
const router = useRouter()
const username = ref('')
@@ -73,6 +79,17 @@ const passwordError = ref('')
const confirmPasswordError = ref('')
const captchaError = ref('')
+// 错误弹窗相关
+const showError = ref(false)
+const errorTitle = ref('错误提示')
+const errorMessage = ref('')
+
+const showErrorMessage = (message, title = '错误提示') => {
+ errorMessage.value = message
+ errorTitle.value = title
+ showError.value = true
+}
+
// 表单验证规则
const validateUsername = () => {
if (!username.value) {
@@ -127,18 +144,6 @@ const validateCaptcha = () => {
return true
}
-// 计算表单是否有效
-const isFormValid = computed(() => {
- return !usernameError.value &&
- !passwordError.value &&
- !confirmPasswordError.value &&
- !captchaError.value &&
- username.value &&
- password.value &&
- confirmPassword.value &&
- captcha.value
-})
-
const refreshCaptcha = async () => {
try {
const response = await getCaptcha()
@@ -147,7 +152,7 @@ const refreshCaptcha = async () => {
captcha.value = '' // 清空验证码输入
} catch (error) {
console.error('获取验证码失败:', error)
- alert('获取验证码失败,请刷新页面重试')
+ showErrorMessage('获取验证码失败,请刷新页面重试')
}
}
@@ -158,7 +163,7 @@ onMounted(() => {
const handleRegister = async () => {
try {
// 验证表单
- if (!validateUsername() || !validatePassword() || !validateConfirmPassword() || !validateCaptcha()) {
+ if (!validateForm()) {
return
}
@@ -170,20 +175,80 @@ const handleRegister = async () => {
captcha.value
)
- alert('注册成功')
+ showErrorMessage('注册成功', '提示')
// 切换到登录模块
emit('login')
} catch (error) {
console.error('注册失败:', error)
- if (error.response && error.response.status === 400) {
- alert('该QQ号已被注册')
+ if (error.response) {
+ switch (error.response.status) {
+ case 400:
+ showErrorMessage('该QQ号已被注册')
+ break
+ case 409:
+ showErrorMessage('用户名已存在')
+ break
+ default:
+ showErrorMessage(error.response?.data?.message || error.message || '注册失败,请稍后重试')
+ }
} else {
- alert(error.response?.data?.message || error.message || '注册失败,请稍后重试')
+ showErrorMessage(error.message || '注册失败,请稍后重试')
}
// 注册失败时刷新验证码
refreshCaptcha()
}
}
+
+const validateForm = () => {
+ // 重置所有错误信息
+ usernameError.value = ''
+ passwordError.value = ''
+ confirmPasswordError.value = ''
+ captchaError.value = ''
+
+ // 验证用户名
+ if (!username.value) {
+ usernameError.value = '请输入QQ号码'
+ return false
+ }
+ // 只允许纯数字
+ if (!/^\d+$/.test(username.value)) {
+ usernameError.value = 'QQ号只能包含数字'
+ return false
+ }
+
+ // 验证密码
+ if (!password.value) {
+ passwordError.value = '请输入密码'
+ return false
+ }
+ if (password.value.length < 6) {
+ passwordError.value = '密码长度不能小于6个字符'
+ return false
+ }
+
+ // 验证确认密码
+ if (!confirmPassword.value) {
+ confirmPasswordError.value = '请再次输入密码'
+ return false
+ }
+ if (confirmPassword.value !== password.value) {
+ confirmPasswordError.value = '两次输入的密码不一致'
+ return false
+ }
+
+ // 验证验证码
+ if (!captcha.value) {
+ captchaError.value = '请输入验证码'
+ return false
+ }
+ if (captcha.value.length !== 4) {
+ captchaError.value = '验证码长度不正确'
+ return false
+ }
+
+ return true
+}
\ No newline at end of file
diff --git a/src/views/index/MapDetail.vue b/src/views/index/MapDetail.vue
index 67df520..558f74f 100644
--- a/src/views/index/MapDetail.vue
+++ b/src/views/index/MapDetail.vue
@@ -50,7 +50,7 @@
-
+
-
@@ -87,11 +82,6 @@
@click="authorScore = star"
>★
-
+
+
@@ -108,11 +105,33 @@ import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { getMapDetail } from '../../api/maps.js'
import { hasValidToken } from '../../utils/jwt'
+import ErrorDialog from '@/components/ErrorDialog.vue'
const route = useRoute()
const router = useRouter()
const map = ref(null)
+// 错误弹窗相关
+const showError = ref(false)
+const errorTitle = ref('')
+const errorMessage = ref('')
+const pendingAction = ref(null)
+
+const showErrorMessage = (message, title = '', action = null) => {
+ errorMessage.value = message
+ errorTitle.value = title
+ showError.value = true
+ pendingAction.value = action
+}
+
+const handleErrorClose = () => {
+ showError.value = false
+ if (pendingAction.value) {
+ pendingAction.value()
+ pendingAction.value = null
+ }
+}
+
// 评分相关的响应式变量
const showScoreDialog = ref(false)
const mapScore = ref(0)
@@ -129,16 +148,17 @@ const handleDownload = () => {
// 处理评分点击
const handleScoreClick = () => {
if (!hasValidToken()) {
- alert('请先登录后再进行评分')
- router.push({
- path: '/backend/login',
- query: { redirect: route.fullPath }
+ showErrorMessage('请先登录后再进行评分', '', () => {
+ router.push({
+ path: '/backend/login',
+ query: { redirect: route.fullPath }
+ })
})
return
}
if (!hasDownloaded.value) {
- alert('请先下载地图后再进行评分')
+ showErrorMessage('请先下载地图后再进行评分')
return
}
@@ -150,6 +170,7 @@ const fetchMapDetail = async () => {
map.value = await getMapDetail(route.params.id)
} catch (error) {
console.error('获取地图详情失败:', error)
+ showErrorMessage('获取地图详情失败,请稍后重试')
}
}
@@ -164,7 +185,7 @@ const formatDate = (dateString) => {
// 提交评分
const submitScores = async () => {
if (mapScore.value === 0 || authorScore.value === 0) {
- alert('请为地图和作者都进行评分')
+ showErrorMessage('请为地图和作者都进行评分')
return
}
@@ -184,10 +205,10 @@ const submitScores = async () => {
mapComment.value = ''
authorComment.value = ''
- alert('评分成功!')
+ showErrorMessage('评分成功!')
} catch (error) {
console.error('评分失败:', error)
- alert('评分失败,请稍后重试')
+ showErrorMessage('评分失败,请稍后重试')
}
}
@@ -380,6 +401,15 @@ onMounted(() => {
}
/* 评分弹窗样式 */
+.score-dialog {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1000;
+}
+
.dialog-overlay {
position: fixed;
top: 0;
@@ -387,7 +417,7 @@ onMounted(() => {
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
- z-index: 100;
+ z-index: 1001;
}
.dialog-content {
@@ -400,7 +430,7 @@ onMounted(() => {
border-radius: 8px;
width: 90%;
max-width: 500px;
- z-index: 101;
+ z-index: 1002;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
}
@@ -456,17 +486,6 @@ onMounted(() => {
color: #ffd700;
}
-.comment-input {
- width: 100%;
- height: 80px;
- padding: 8px;
- border: 1px solid #ddd;
- border-radius: 4px;
- resize: vertical;
- font-size: 14px;
- margin-top: 10px;
-}
-
.dialog-footer {
display: flex;
justify-content: flex-end;
@@ -515,9 +534,5 @@ onMounted(() => {
.star {
font-size: 20px;
}
-
- .comment-input {
- height: 60px;
- }
}
\ No newline at end of file