| | |
| | | "name": "my-project", |
| | | "version": "0.0.0", |
| | | "dependencies": { |
| | | "@vant/icons": "^3.0.2", |
| | | "@zxing/library": "^0.21.3", |
| | | "axios": "^1.9.0", |
| | | "echarts": "^5.6.0", |
| | |
| | | "event-source-polyfill": "^1.0.31", |
| | | "qs": "^6.14.0", |
| | | "speak-tts": "^2.0.8", |
| | | "vant": "^3.4.3", |
| | | "vue": "^3.5.13", |
| | | "vue-router": "^4.0.13" |
| | | }, |
| | |
| | | "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", |
| | | "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", |
| | | "license": "MIT" |
| | | }, |
| | | "node_modules/@vant/icons": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmmirror.com/@vant/icons/-/icons-3.0.2.tgz", |
| | | "integrity": "sha512-4OlRVMd0uiDtD9hgSISZW8hB95vU0fFtc41tQchRIyiXkR0tS+DydZOLb8/bQkithrNWhW7Uud38MbKjlJ9lJw==", |
| | | "license": "MIT" |
| | | }, |
| | | "node_modules/@vant/popperjs": { |
| | | "version": "1.3.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/popperjs/-/popperjs-1.3.0.tgz", |
| | | "integrity": "sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw==", |
| | | "license": "MIT" |
| | | }, |
| | | "node_modules/@vant/use": { |
| | | "version": "1.6.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/use/-/use-1.6.0.tgz", |
| | | "integrity": "sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==", |
| | | "license": "MIT", |
| | | "peerDependencies": { |
| | | "vue": "^3.0.0" |
| | | } |
| | | }, |
| | | "node_modules/@vitejs/plugin-vue": { |
| | | "version": "5.2.1", |
| | |
| | | "node": ">=14.17" |
| | | } |
| | | }, |
| | | "node_modules/vant": { |
| | | "version": "3.4.3", |
| | | "resolved": "https://registry.npmmirror.com/vant/-/vant-3.4.3.tgz", |
| | | "integrity": "sha512-vkOgMspRxqhTwX6huPjEiWgTDULZZVVVv2IaAeyXq21heKIJazv2Nymolhzmk4Ar/ZFfoxC/yOeG7MhnhTbrew==", |
| | | "license": "MIT", |
| | | "dependencies": { |
| | | "@vant/icons": "^1.7.1", |
| | | "@vant/popperjs": "^1.1.0", |
| | | "@vant/use": "^1.3.5" |
| | | }, |
| | | "peerDependencies": { |
| | | "vue": "^3.0.0" |
| | | } |
| | | }, |
| | | "node_modules/vant/node_modules/@vant/icons": { |
| | | "version": "1.8.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/icons/-/icons-1.8.0.tgz", |
| | | "integrity": "sha512-sKfEUo2/CkQFuERxvkuF6mGQZDKu3IQdj5rV9Fm0weJXtchDSSQ+zt8qPCNUEhh9Y8shy5PzxbvAfOOkCwlCXg==", |
| | | "license": "MIT" |
| | | }, |
| | | "node_modules/vite": { |
| | | "version": "6.0.7", |
| | | "resolved": "https://registry.npmmirror.com/vite/-/vite-6.0.7.tgz", |
| | |
| | | "version": "0.0.16", |
| | | "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", |
| | | "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" |
| | | }, |
| | | "@vant/icons": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmmirror.com/@vant/icons/-/icons-3.0.2.tgz", |
| | | "integrity": "sha512-4OlRVMd0uiDtD9hgSISZW8hB95vU0fFtc41tQchRIyiXkR0tS+DydZOLb8/bQkithrNWhW7Uud38MbKjlJ9lJw==" |
| | | }, |
| | | "@vant/popperjs": { |
| | | "version": "1.3.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/popperjs/-/popperjs-1.3.0.tgz", |
| | | "integrity": "sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw==" |
| | | }, |
| | | "@vant/use": { |
| | | "version": "1.6.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/use/-/use-1.6.0.tgz", |
| | | "integrity": "sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==", |
| | | "requires": {} |
| | | }, |
| | | "@vitejs/plugin-vue": { |
| | | "version": "5.2.1", |
| | |
| | | "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", |
| | | "devOptional": true |
| | | }, |
| | | "vant": { |
| | | "version": "3.4.3", |
| | | "resolved": "https://registry.npmmirror.com/vant/-/vant-3.4.3.tgz", |
| | | "integrity": "sha512-vkOgMspRxqhTwX6huPjEiWgTDULZZVVVv2IaAeyXq21heKIJazv2Nymolhzmk4Ar/ZFfoxC/yOeG7MhnhTbrew==", |
| | | "requires": { |
| | | "@vant/icons": "^1.7.1", |
| | | "@vant/popperjs": "^1.1.0", |
| | | "@vant/use": "^1.3.5" |
| | | }, |
| | | "dependencies": { |
| | | "@vant/icons": { |
| | | "version": "1.8.0", |
| | | "resolved": "https://registry.npmmirror.com/@vant/icons/-/icons-1.8.0.tgz", |
| | | "integrity": "sha512-sKfEUo2/CkQFuERxvkuF6mGQZDKu3IQdj5rV9Fm0weJXtchDSSQ+zt8qPCNUEhh9Y8shy5PzxbvAfOOkCwlCXg==" |
| | | } |
| | | } |
| | | }, |
| | | "vite": { |
| | | "version": "6.0.7", |
| | | "resolved": "https://registry.npmmirror.com/vite/-/vite-6.0.7.tgz", |
| | |
| | | "preview": "vite preview" |
| | | }, |
| | | "dependencies": { |
| | | "@vant/icons": "^3.0.2", |
| | | "@zxing/library": "^0.21.3", |
| | | "axios": "^1.9.0", |
| | | "echarts": "^5.6.0", |
| | |
| | | "event-source-polyfill": "^1.0.31", |
| | | "qs": "^6.14.0", |
| | | "speak-tts": "^2.0.8", |
| | | "vant": "^3.4.3", |
| | | "vue": "^3.5.13", |
| | | "vue-router": "^4.0.13" |
| | | }, |
| | |
| | | import { createApp } from 'vue' |
| | | import ElementPlus from 'element-plus' |
| | | import 'element-plus/dist/index.css' |
| | | import 'element-plus/dist/index.css' |
| | | import Vant from 'vant' |
| | | import 'vant/lib/index.css' |
| | | import router from './router'; |
| | | import './style.css' |
| | | import App from './App.vue' |
| | | |
| | | createApp(App).use(router).use(ElementPlus).mount('#app') |
| | | createApp(App).use(router).use(ElementPlus).use(Vant).mount('#app') |
| | |
| | | import deviceWindows from '../views/deviceWindows.vue' |
| | | import deviceWindows2 from '../views/deviceWindoes2.vue' |
| | | import test from '../views/test.vue'; // 搜索结果页,接收查询参数 |
| | | import registerForNutrition from '../views/register/index.vue' |
| | | import registerSuu from '../views/registerSuu/index.vue' |
| | | |
| | | // 定义路由规则,并为每个路由指定类型安全的 props |
| | | const routes: Array<RouteRecordRaw> = [ |
| | |
| | | component: test, |
| | | props: true, // 路径参数将作为 props 传递给组件 |
| | | }, |
| | | // { |
| | | // path: '/search', |
| | | // name: 'Search', |
| | | // component: Search, |
| | | // props: (route) => ({ query: route.query.q as string }), // 将查询参数 q 作为 prop 传递给组件 |
| | | // } |
| | | { |
| | | path: '/registerForNutrition', |
| | | name: 'registerForNutrition', |
| | | component: registerForNutrition |
| | | }, |
| | | { |
| | | path: '/register-success', |
| | | name: 'registerSuu', |
| | | component: registerSuu |
| | | } |
| | | ]; |
| | | |
| | | // 创建路由器实例,并指定类型 |
| | |
| | | console.error('Error setting timeout alert:', error); |
| | | throw error; |
| | | } |
| | | }; |
| | | |
| | | export const sendValidateCode = async (requestData): Promise<ApiResponse> => { |
| | | try { |
| | | const response = await axios.post(`${apiBaseUrl}/user/info/sendValidateCodeForRegister`, requestData, { |
| | | headers: { |
| | | 'Content-Type': 'application/x-www-form-urlencoded' |
| | | } |
| | | }); |
| | | return response.data; |
| | | } catch (error) { |
| | | console.error('Error setting timeout alert:', error); |
| | | throw error; |
| | | } |
| | | }; |
| | | |
| | | export const registerForNutrition = async (requestData): Promise<ApiResponse> => { |
| | | try { |
| | | const response = await axios.post(`${apiBaseUrl}/user/info/registerForNutrition`, requestData, { |
| | | headers: { |
| | | 'Content-Type': 'application/json' |
| | | } |
| | | }); |
| | | return response.data; |
| | | } catch (error) { |
| | | console.error('Error setting timeout alert:', error); |
| | | throw error; |
| | | } |
| | | }; |
| New file |
| | |
| | | <template> |
| | | <div class="register-form"> |
| | | <van-image width="100" height="100" :src="logo" /> |
| | | <h1>用户注册</h1> |
| | | <p>创建您的账户,开始使用我们的服务</p> |
| | | |
| | | <van-form @submit="onSubmit"> |
| | | <!-- 用户名 --> |
| | | <van-field |
| | | v-model="formData.username" |
| | | name="用户名" |
| | | label="用户姓名*" |
| | | placeholder="请输入您的姓名" |
| | | :rules="[{ required: true, message: '请填写用户名' }]" |
| | | /> |
| | | |
| | | <!-- 手机号 --> |
| | | <van-field |
| | | v-model="formData.phone" |
| | | type="tel" |
| | | name="手机号" |
| | | label="手机号*" |
| | | placeholder="请输入您的手机号" |
| | | :rules="[ |
| | | { required: true, message: '请填写手机号' }, |
| | | { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码'} |
| | | ]" |
| | | /> |
| | | |
| | | <!-- 验证码 --> |
| | | <van-field |
| | | v-model="formData.code" |
| | | center |
| | | clearable |
| | | name="验证码" |
| | | label="手机验证码*" |
| | | placeholder="请输入验证码" |
| | | :rules="[{ required: true, message: '请填写验证码' }]" |
| | | > |
| | | <template #button> |
| | | <van-button size="small" type="primary" @click="sendCode" :disabled="isSendingCode">{{ sendButtonText }}</van-button> |
| | | </template> |
| | | </van-field> |
| | | |
| | | <!-- 邮箱地址 --> |
| | | <van-field |
| | | v-model="formData.email" |
| | | type="email" |
| | | name="邮箱地址" |
| | | label="邮箱地址*" |
| | | placeholder="请输入您的邮箱地址" |
| | | :rules="[ |
| | | { pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/, message: '请输入正确的邮箱格式'} |
| | | ]" |
| | | /> |
| | | |
| | | <!-- 密码 --> |
| | | <van-field |
| | | v-model="formData.password" |
| | | type="password" |
| | | name="密码" |
| | | label="密码*" |
| | | placeholder="请输入您的密码" |
| | | :rules="[ |
| | | { required: true, message: '请填写密码' }, |
| | | { min: 6, message: '密码长度不能少于6位'} |
| | | ]" |
| | | /> |
| | | |
| | | <!-- 确认密码 --> |
| | | <van-field |
| | | v-model="formData.confirmPassword" |
| | | type="password" |
| | | name="确认密码" |
| | | label="确认密码*" |
| | | placeholder="请确认您的密码" |
| | | :rules="[ |
| | | { validator: validatePass, message: '两次输入密码不一致' }, |
| | | { required: true, message: '请确认密码' } |
| | | ]" |
| | | /> |
| | | |
| | | <!-- 提交按钮 --> |
| | | <div style="margin: 16px;"> |
| | | <van-button round block type="primary" native-type="submit">立即注册</van-button> |
| | | </div> |
| | | </van-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue'; |
| | | import { Toast } from 'vant'; |
| | | import logo from '@/assets/logo.png' |
| | | import { useRouter } from 'vue-router'; |
| | | import { sendValidateCode,registerForNutrition } from "@/utils/httpApi"; |
| | | |
| | | const router = useRouter(); |
| | | const formData = ref({ |
| | | username: '', |
| | | phone: '', |
| | | code: '', |
| | | email: '', |
| | | password: '', |
| | | confirmPassword: '' |
| | | }); |
| | | const submitLoadion=ref(false) |
| | | const isSendingCode = ref(false); |
| | | const sendButtonText = ref('发送验证码'); |
| | | let countdownTimer = null; |
| | | const countdown = ref(60); |
| | | |
| | | // 自定义验证手机号格式 |
| | | const isValidPhone = (phone) => { |
| | | const phoneReg = /^1[3456789]\d{9}$/; |
| | | return phoneReg.test(phone); |
| | | }; |
| | | |
| | | // 发送验证码 |
| | | const sendCode = () => { |
| | | if (!formData.value.phone) { |
| | | Toast.fail('请先填写手机号'); |
| | | return; |
| | | } |
| | | |
| | | if (!isValidPhone(formData.value.phone)) { |
| | | Toast.fail('请输入正确的手机号码'); |
| | | return; |
| | | } |
| | | |
| | | // 开始发送验证码 |
| | | isSendingCode.value = true; |
| | | // 模拟发送验证码请求 |
| | | console.log('发送验证码至:', formData.value.phone); |
| | | sendValidateCode('mobileNo='+formData.value.phone).then(re=>{ |
| | | Toast.success('验证码已发送'); |
| | | // 启动倒计时 |
| | | countdown.value = 60; |
| | | sendButtonText.value = `${countdown.value}秒后重发`; |
| | | |
| | | countdownTimer = setInterval(() => { |
| | | countdown.value--; |
| | | sendButtonText.value = `${countdown.value}秒后重发`; |
| | | if (countdown.value <= 0) { |
| | | clearInterval(countdownTimer); |
| | | isSendingCode.value = false; |
| | | sendButtonText.value = '重新发送'; |
| | | } |
| | | }, 1000); |
| | | }).finally(()=>{ |
| | | |
| | | }) |
| | | |
| | | }; |
| | | |
| | | // 验证两次输入的密码是否一致 |
| | | const validatePass = (val) => val === formData.value.password; |
| | | |
| | | // 表单提交 |
| | | const onSubmit = (values) => { |
| | | console.log('submit', values); |
| | | const mono={ |
| | | 手机验证码:values.验证码, |
| | | 用户姓名:values.用户名, |
| | | 手机号:values.手机号, |
| | | 密码:values.确认密码, |
| | | Email:values.邮箱地址 |
| | | } |
| | | console.log(mono) |
| | | Toast.loading({ |
| | | message: '加载中...', |
| | | forbidClick: true, |
| | | loadingType: 'spinner', |
| | | }); |
| | | submitLoadion.value=true |
| | | registerForNutrition(mono).then(re=>{ |
| | | console.log(re) |
| | | if(re.code===400){ |
| | | Toast(re.message); |
| | | }else if(re.code===200){ |
| | | // 跳转到注册成功页面 |
| | | Toast.success('提交成功'); |
| | | router.push('/register-success'); |
| | | } |
| | | |
| | | }).center((err)=>{ |
| | | Toast('注册失败'); |
| | | }) |
| | | .finally(()=>{ |
| | | submitLoadion.value=false |
| | | // router.push('/register-success'); |
| | | }) |
| | | |
| | | // router.push('/register-success'); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .register-form { |
| | | text-align: center; |
| | | max-width: 400px; |
| | | margin: 0 auto; |
| | | padding: 20px; |
| | | padding-top: 40px; |
| | | } |
| | | |
| | | .logo { |
| | | display: block; |
| | | margin: 0 auto 20px; |
| | | width: 100px; |
| | | } |
| | | |
| | | h1 { |
| | | text-align: center; |
| | | font-size: 20px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | p { |
| | | text-align: center; |
| | | color: #666; |
| | | margin-bottom: 20px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="success-container" style="text-align: center;margin-top: 100px;"> |
| | | <van-icon name="checked" class="success-icon" /> |
| | | <h2>注册成功!</h2> |
| | | <p>您的账户已成功创建,欢迎加入我们!</p> |
| | | <p>待审核通过后才可以登录系统!</p> |
| | | <!-- <van-button type="primary" block @click="goToLogin">前往登录</van-button> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .success-icon { |
| | | font-size: 60px; |
| | | color: #4caf50; |
| | | margin-bottom: 20px; |
| | | } |
| | | </style> |