From 6e0be666feee87a6c2695a8869c094c1aad5876a Mon Sep 17 00:00:00 2001 From: Wenzhe Date: Mon, 2 Feb 2026 14:56:25 +0800 Subject: [PATCH] v1.1.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、api调用库调整好http状态码处理逻辑 2、增加用户信息提交api类 3、完成用户信息提交处理,包括提交后不再弹出、重复提交、错误提交、完成提交 --- api/request.js | 7 ++- api/user.js | 22 +++++++++ components/EndPage.vue | 13 +++++ components/LotteryFormModal.vue | 31 +++++++++++- components/SinglePageContainer.vue | 77 ++++++++++++++++++++++++++++-- 5 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 api/user.js diff --git a/api/request.js b/api/request.js index 6a216d9..bbcdfe5 100644 --- a/api/request.js +++ b/api/request.js @@ -78,7 +78,12 @@ export const request = (options = {}) => { if (response.statusCode >= 200 && response.statusCode < 300) { resolve(result.data) } else { - reject(new Error(`HTTP ${response.statusCode}: ${response.errMsg || '请求失败'}`)) + // 创建包含状态码和响应数据的错误对象 + const error = new Error(`HTTP ${response.statusCode}: ${response.errMsg || '请求失败'}`) + error.statusCode = response.statusCode + error.response = response + error.data = result.data || response.data + reject(error) } }, fail: (error) => { diff --git a/api/user.js b/api/user.js new file mode 100644 index 0000000..9403da4 --- /dev/null +++ b/api/user.js @@ -0,0 +1,22 @@ +/** + * 用户信息相关 API + */ +import { post } from './request.js' + +/** + * 保存用户信息 + * @param {Object} data - 用户数据 + * @param {string} data.name - 用户姓名 + * @param {string} data.phone - 用户手机号码 + * @param {string} data.address - 用户地址 + * @param {string} data.msg - 用户留言 + * @param {string} data.page_visit_uuid - 页面访问UUID + * @returns {Promise} + */ +export const saveUserInfo = (data) => { + return post('/api/user-info', data) +} + +export default { + saveUserInfo +} diff --git a/components/EndPage.vue b/components/EndPage.vue index 0a9e20c..f7e61dd 100644 --- a/components/EndPage.vue +++ b/components/EndPage.vue @@ -122,12 +122,25 @@ const props = defineProps({ longfusi: false, dongzhimen: false }) + }, + hasSubmitted: { + type: Boolean, + default: false } }) const emit = defineEmits(['lottery', 'couplet', 'restart']) const handleLottery = () => { + // 如果已经提交过,直接提示 + if (props.hasSubmitted) { + uni.showToast({ + title: '您已经提交过信息了,请勿重复提交', + icon: 'none', + duration: 2000 + }) + return + } emit('lottery') } diff --git a/components/LotteryFormModal.vue b/components/LotteryFormModal.vue index 264c70f..b75dd35 100644 --- a/components/LotteryFormModal.vue +++ b/components/LotteryFormModal.vue @@ -5,6 +5,10 @@ const props = defineProps({ visible: { type: Boolean, default: false + }, + hasSubmitted: { + type: Boolean, + default: false } }) @@ -48,9 +52,16 @@ const showToast = (title) => { // 提交表单 const handleSubmit = () => { + // 如果已经提交过,直接提示 + if (props.hasSubmitted) { + showToast('您已经提交过信息了,请勿重复提交') + return + } + console.log('提交表单', formData.value) // 验证表单 + console.log('表单数据:', formData.value) if (!formData.value.name || !formData.value.phone || !formData.value.address || !formData.value.msg) { showToast('请填写完整信息') return @@ -58,7 +69,9 @@ const handleSubmit = () => { // 验证手机号 const phoneRegex = /^1[3-9]\d{9}$/ - if (!phoneRegex.test(formData.value.phone)) { + const phone = formData.value.phone.trim() + console.log('手机号验证:', phone, '长度:', phone.length, '匹配结果:', phoneRegex.test(phone)) + if (!phoneRegex.test(phone)) { showToast('请输入正确的手机号') return } @@ -76,7 +89,15 @@ const handleSubmit = () => { return } - emit('submit', { ...formData.value }) + // 提交前清理数据 + const submitData = { + name: formData.value.name.trim(), + phone: formData.value.phone.trim(), + address: formData.value.address.trim(), + msg: formData.value.msg.trim() + } + + emit('submit', submitData) } @@ -110,6 +131,8 @@ const handleSubmit = () => { type="text" placeholder="请输入您的姓名" class="form-input" + maxlength="30" + required /> @@ -119,6 +142,8 @@ const handleSubmit = () => { type="tel" placeholder="请输入您的联系电话" class="form-input" + maxlength="11" + required /> @@ -129,6 +154,7 @@ const handleSubmit = () => { placeholder="请输入您的邮寄地址" class="form-input" maxlength="100" + required /> @@ -138,6 +164,7 @@ const handleSubmit = () => { placeholder="请输入您的留言" class="form-textarea" maxlength="200" + required > {{ formData.msg.length }}/200 diff --git a/components/SinglePageContainer.vue b/components/SinglePageContainer.vue index f6fe375..7cabcbf 100644 --- a/components/SinglePageContainer.vue +++ b/components/SinglePageContainer.vue @@ -3,6 +3,7 @@ import { ref, onMounted, onUnmounted, computed, watch, nextTick } from 'vue' import { useSceneStore } from '../store/scene' import { useCollectionStore } from '../store/collection' import { recordPageVisit } from '../api/visit.js' +import { saveUserInfo } from '../api/user.js' import LongImageViewer from './LongImageViewer.vue' import MediaPlayer from './MediaPlayer.vue' import QianmenScene from './QianmenScene.vue' @@ -42,6 +43,10 @@ const showCoupletDisplay = ref(false) const coupletKeyword = ref('') // 生成的春联 const generatedCouplet = ref(null) +// 页面访问UUID +const pageVisitUuid = ref('') +// 是否已提交用户信息 +const hasSubmittedUserInfo = ref(false) // 推荐关键词 @@ -141,6 +146,13 @@ onMounted(() => { recordPageVisit({ user_agent: navigator.userAgent, page_name: 'home' + }).then(res => { + if (res && res.uuid) { + pageVisitUuid.value = res.uuid + console.log('页面访问UUID:', res.uuid) + } + }).catch(err => { + console.log('页面访问记录失败:', err) }) // 检查并初始化场景交互状态 @@ -340,21 +352,74 @@ const closeLotteryForm = () => { } // 提交抽奖表单 -const submitLotteryForm = (formData) => { - // 模拟提交 +const submitLotteryForm = async (formData) => { + // 检查是否已经提交过 + if (hasSubmittedUserInfo.value) { + uni.showToast({ + title: '您已经提交过信息了,请勿重复提交', + icon: 'none', + duration: 2000 + }) + return + } + + // 检查是否有UUID + if (!pageVisitUuid.value) { + uni.showToast({ + title: '系统错误,请刷新页面重试', + icon: 'none', + duration: 2000 + }) + return + } + uni.showLoading({ title: '提交中...', mask: true }) - setTimeout(() => { + try { + // 调用用户信息保存接口 + await saveUserInfo({ + name: formData.name, + phone: formData.phone, + address: formData.address, + msg: formData.msg, + page_visit_uuid: pageVisitUuid.value + }) + + // 标记为已提交 + hasSubmittedUserInfo.value = true + uni.hideLoading() uni.showToast({ - title: '报名成功!我们将在活动结束后通知您抽奖结果', + title: '提交成功!我们将在活动结束后通知您抽奖结果', duration: 2000 }) showLotteryForm.value = false - }, 1500) + } catch (error) { + uni.hideLoading() + console.error('提交用户信息失败:', error) + + // 直接展示后端返回的错误信息 + let errorMessage = '提交失败,请稍后重试' + + // 检查是否有后端返回的错误信息 + if (error.data && error.data.error) { + errorMessage = error.data.error + } else if (error.response && error.response.data && error.response.data.error) { + errorMessage = error.response.data.error + } else if (error.message) { + // 如果是网络错误或其他错误,显示通用提示 + errorMessage = '提交失败,请稍后重试' + } + + uni.showToast({ + title: errorMessage, + icon: 'none', + duration: 2000 + }) + } } // 打开AI春联生成弹窗 @@ -471,6 +536,7 @@ onUnmounted(() => { :collected-count="collectedItems.length" :total-count="scenes.length - 1" :collected-seals="collectedSeals" + :has-submitted="hasSubmittedUserInfo" @lottery="openLotteryForm" @couplet="openAICoupletForm" @restart="scrollToTop" @@ -552,6 +618,7 @@ onUnmounted(() => {