单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
chenyc
2025-06-20 80edeb00ec5f9647b568a48503e63f485505aca8
gx语音播报
3个文件已添加
5个文件已修改
370 ■■■■■ 已修改文件
package-lock.json 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/httpApi.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/register/index.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/registerSuu/index.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -8,6 +8,7 @@
      "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",
@@ -15,6 +16,7 @@
        "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"
      },
@@ -802,6 +804,27 @@
      "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",
@@ -2076,6 +2099,26 @@
        "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",
@@ -2616,6 +2659,22 @@
      "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",
@@ -3482,6 +3541,23 @@
      "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",
package.json
@@ -10,6 +10,7 @@
    "preview": "vite preview"
  },
  "dependencies": {
    "@vant/icons": "^3.0.2",
    "@zxing/library": "^0.21.3",
    "axios": "^1.9.0",
    "echarts": "^5.6.0",
@@ -17,6 +18,7 @@
    "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"
  },
src/assets/logo.png
src/main.ts
@@ -1,8 +1,9 @@
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
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')
src/router/index.ts
@@ -4,6 +4,8 @@
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> = [
@@ -18,12 +20,16 @@
    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
  }
];
// 创建路由器实例,并指定类型
src/utils/httpApi.ts
@@ -30,3 +30,31 @@
        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;
    }
};
src/views/register/index.vue
New file
@@ -0,0 +1,224 @@
<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>
src/views/registerSuu/index.vue
New file
@@ -0,0 +1,17 @@
<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>