From ce5e84197b43dec8c01717b116cb77535ad3c91e Mon Sep 17 00:00:00 2001
From: zhangwei <1504152376@qq.com>
Date: 星期三, 25 六月 2025 16:21:42 +0800
Subject: [PATCH] '登录注册'

---
 src/views/register/index.vue |  433 +++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 299 insertions(+), 134 deletions(-)

diff --git a/src/views/register/index.vue b/src/views/register/index.vue
index d92a8dc..ba4182c 100644
--- a/src/views/register/index.vue
+++ b/src/views/register/index.vue
@@ -18,18 +18,22 @@
           <el-form
             ref="ruleFormRef"
             style="max-width: 600px"
-            :model="ruleForm"
-            :rules="rules"
+            :model="state.ruleForm"
+            :rules="state.rules"
             label-width="auto"
+            size="large"
           >
-            <el-form-item label="娉ㄥ唽韬唤" prop="resource">
-              <el-radio-group v-model="ruleForm.resource">
-                <el-radio value="Sponsorship">渚涘簲鍟�</el-radio>
-                <el-radio value="Venue">浠g悊鏈烘瀯</el-radio>
-                <el-radio value="cgr">閲囪喘浜�</el-radio>
+            <el-form-item label="娉ㄥ唽韬唤" prop="exRoleCode">
+              <el-radio-group v-model="state.ruleForm.exRoleCode">
+                <el-radio
+                  v-for="item in state.roleList"
+                  :key="item.id"
+                  :value="item.code"
+                  >{{ item.name }}</el-radio
+                >
               </el-radio-group>
             </el-form-item>
-            <el-form-item label="浼佷笟鍚嶇О" prop="name">
+            <!-- <el-form-item label="浼佷笟鍚嶇О" prop="name">
               <el-input
                 v-model="ruleForm.name"
                 placeholder="璇疯緭鍏ヨ惀涓氭墽鐓т笂鐨勪紒涓氬悕绉�"
@@ -37,8 +41,20 @@
             </el-form-item>
             <el-form-item label="鐢ㄦ埛鍚�" prop="region">
               <el-input v-model="ruleForm.region" placeholder="璇疯緭鍏ョ敤鎴峰悕" />
+            </el-form-item> -->
+            <el-form-item label="濮撳悕" prop="nickName">
+              <el-input
+                v-model="state.ruleForm.nickName"
+                placeholder="璇疯緭鍏ュ鍚�"
+              />
             </el-form-item>
-            <el-form-item label="鐧诲綍瀵嗙爜" prop="password">
+            <el-form-item label="鎵嬫満鍙风爜" prop="phone">
+              <el-input
+                v-model="state.ruleForm.phone"
+                placeholder="璇疯緭鍏ユ偍鐨勬墜鏈哄彿鐮�"
+              />
+            </el-form-item>
+            <!-- <el-form-item label="鐧诲綍瀵嗙爜" prop="password">
               <el-input
                 v-model="ruleForm.password"
                 placeholder="8-20浣嶆暟瀛�+澶у皬鍐欏瓧姣�+鐗规畩瀛楃鐨勭粍鍚�"
@@ -55,48 +71,74 @@
                 v-model="ruleForm.repassword"
                 placeholder="璇疯緭鍏ヨ仈绯讳汉濮撳悕"
               />
-            </el-form-item>
-            <el-form-item label="閭" prop="repassword">
+            </el-form-item> -->
+            <el-form-item label="閭" prop="email">
               <el-input
-                v-model="ruleForm.repassword"
+                v-model="state.ruleForm.email"
                 placeholder="璇疯緭鍏ヨ仈绯婚偖绠�"
               />
             </el-form-item>
-            <el-form-item label="鎵嬫満鍙风爜" prop="repassword">
-              <el-input
-                v-model="ruleForm.repassword"
-                placeholder="璇疯緭鍏ユ偍鐨勬墜鏈哄彿鐮�"
-              />
+            <el-form-item label="楠岃瘉鐮�" class="login-animation3" prop="code">
+              <el-col :span="15">
+                <el-input
+                  ref="codeRef"
+                  v-model="state.ruleForm.code"
+                  text
+                  maxlength="4"
+                  placeholder="璇疯緭鍏ラ獙璇佺爜"
+                  clearable
+                  autocomplete="off"
+                />
+              </el-col>
+              <el-col :span="1" />
+              <el-col :span="8">
+                <div
+                  :class="[
+                    state.expirySeconds > 0
+                      ? 'login-content-code'
+                      : 'login-content-code-expired'
+                  ]"
+                  @click="getCaptcha"
+                >
+                  <img
+                    class="login-content-code-img"
+                    width="130px"
+                    height="38px"
+                    :src="state.captchaImage"
+                    style="cursor: pointer"
+                  />
+                </div>
+              </el-col>
             </el-form-item>
-            <el-form-item label="鎵嬫満鍙风爜" prop="repassword">
+            <el-form-item prop="phoneVCode" label="鎵嬫満楠岃瘉鐮�">
               <el-input
-                v-model="ruleForm.repassword"
-                placeholder="璇疯緭鍏ユ偍鐨勬墜鏈哄彿鐮�"
-              />
-            </el-form-item>
-            <el-form-item prop="validationCode" label="鎵嬫満楠岃瘉鐮�">
-              <el-input
-                v-model.number="ruleForm.validationCode"
+                v-model.number="state.ruleForm.phoneVCode"
                 class="form-input"
                 placeholder="璇疯緭鍏ラ獙璇佺爜"
               >
                 <template #suffix>
-                  <span id="suffix-span">
+                  <span v-if="state.phoneSeconds == 0" id="suffix-span">
                     <span
                       id="suffix-span-2"
                       ref="spanRef"
-                      @click="sendValidationCode(ruleForm.repassword)"
+                      @click="sendValidationCode(state.ruleForm.phone)"
                     >
-                      {{ isSendValidationCode }}
+                      鑾峰彇楠岃瘉鐮�
+                    </span>
+                  </span>
+                  <span v-else id="suffix-span">
+                    <span id="suffix-span-2" ref="spanRef">
+                      {{ state.phoneSeconds }}绉掑悗閲嶆柊鑾峰彇
                     </span>
                   </span>
                 </template>
               </el-input>
             </el-form-item>
-            <el-form-item prop="repassword" label=" ">
-              <el-checkbox value="Online activities" name="type">
-                鎴戝凡闃呰骞跺悓鎰� 銆婇潪鏀块噰鎷涙爣閲囪喘浜ゆ槗骞冲彴鐢ㄦ埛鍗忚銆�
-              </el-checkbox>
+            <el-form-item label=" ">
+              <el-checkbox v-model="checked1" name="type" />鎴戝凡闃呰骞跺悓鎰�
+              <el-link type="primary" :underline="false"
+                >銆婇潪鏀块噰鎷涙爣閲囪喘浜ゆ槗骞冲彴鐢ㄦ埛鍗忚銆�</el-link
+              >
             </el-form-item>
             <el-form-item label=" ">
               <el-button type="primary" @click="submitForm(ruleFormRef)">
@@ -104,7 +146,8 @@
               </el-button>
             </el-form-item>
             <el-form-item label=" ">
-              <span>宸叉湁璐﹀彿锛熺珛鍗崇櫥褰�</span>
+              <span>宸叉湁璐﹀彿锛�</span>
+              <el-link type="primary" :underline="false">绔嬪嵆鐧诲綍</el-link>
             </el-form-item>
           </el-form>
         </div>
@@ -114,120 +157,197 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from "vue";
+import {
+  reactive,
+  computed,
+  ref,
+  onMounted,
+  defineAsyncComponent,
+  onUnmounted,
+  watch
+} from "vue";
 import type { FormInstance, FormRules } from "element-plus";
-
-interface RuleForm {
-  name: string;
-  region: string;
-  count: string;
-  password: string;
-  repassword: string;
-  validationCode: string;
-  date1: string;
-  date2: string;
-  delivery: boolean;
-  location: string;
-  type: string[];
-  resource: string;
-  desc: string;
-}
-
-const ruleFormRef = ref<FormInstance>();
-const ruleForm = reactive<RuleForm>({
-  name: "",
-  region: "",
-  password: "",
-  validationCode: "",
-  repassword: "",
-  count: "",
-  date1: "",
-  date2: "",
-  delivery: false,
-  location: "",
-  type: [],
-  resource: "",
-  desc: ""
+import {
+  captcha,
+  phoneNumberCode,
+  register,
+  exRole
+} from "@/api/register/index.ts";
+import { useRoute, useRouter } from "vue-router";
+import { message } from "@/utils/message";
+defineOptions({
+  name: "Register"
 });
+
+const route = useRoute();
+const router = useRouter();
+const checked1 = ref(false);
+const state = reactive({
+  isShowPassword: false,
+  ruleForm: {
+    account: "",
+    nickName: "",
+    phone: "",
+    phoneVCode: "",
+    // tenantId: props.tenantInfo.id,
+    code: "",
+    codeId: 0,
+    email: "",
+    exRoleCode: ""
+  },
+  rules: {
+    phoneVCode: [
+      {
+        required: true,
+        message: "璇疯緭鍏ユ墜鏈洪獙璇佺爜",
+        trigger: "blur"
+      }
+    ],
+    nickName: [
+      {
+        required: true,
+        message: "璇疯緭鍏ュ鍚�",
+        trigger: "blur"
+      }
+    ],
+    phone: [
+      {
+        required: true,
+        message: "璇疯緭鍏ユ偍鐨勬墜鏈哄彿鐮�",
+        trigger: "blur"
+      }
+    ],
+    exRoleCode: [
+      {
+        required: true,
+        message: "璇烽�夋嫨瑙掕壊",
+        trigger: "blur"
+      }
+    ]
+    // code: [{ required: true, message: t('message.account.placeholder4'), trigger: 'blur' }],
+  },
+  loading: {
+    signIn: false
+  },
+  captchaImage: "",
+  rotateVerifyVisible: false,
+  // rotateVerifyImg: verifyImg,
+  // rotateVerifyImg: themeConfig.value.logoUrl,
+  secondVerEnabled: false,
+  // captchaEnabled: false,
+  isPassRotate: false,
+  capsLockVisible: false,
+  hideTenantForLogin: false,
+  expirySeconds: 60, // 楠岃瘉鐮佽繃鏈熸椂闂�
+  phoneSeconds: 0, // 鎵嬫満楠岃瘉鐮佸�掕鏃�
+  roleList: []
+});
+// 楠岃瘉鐮佽繃鏈熻鏃跺櫒
+let timer: any = null;
+let phonetimer: any = null;
+
+// 椤甸潰鍒濆鍖�
+onMounted(async () => {
+  // 鑻RL甯︽湁Token鍙傛暟锛堢涓夋柟鐧诲綍锛�
+  const accessToken = route.query.token;
+  // if (accessToken) await saveTokenAndInitRoutes(accessToken);
+  // watch(
+  //   () => themeConfig.value.isLoaded,
+  //   isLoaded => {
+  //     if (isLoaded) {
+  // 鑾峰彇鐧诲綍閰嶇疆
+  // state.hideTenantForLogin = themeConfig.value.hideTenantForLogin ?? true;
+  // state.secondVerEnabled = themeConfig.value.secondVer ?? true;
+  // state.captchaEnabled = themeConfig.value.captcha ?? true;
+
+  // 鑾峰彇楠岃瘉鐮�
+  getCaptcha();
+  exRole().then(res => {
+    state.roleList = res.result;
+  });
+  // 娉ㄥ唽楠岃瘉鐮佽繃鏈熻鏃跺櫒
+  // if (state.captchaEnabled) {
+  timer = setInterval(() => {
+    if (state.expirySeconds > 0) state.expirySeconds -= 1;
+  }, 1000);
+
+  // }
+  // }
+  // },
+  // { immediate: true }
+  // );
+
+  // 妫�娴嬪ぇ灏忓啓鎸夐敭/CapsLK
+  document.addEventListener("keyup", handleKeyPress);
+});
+
+// 椤甸潰鍗歌浇
+onUnmounted(() => {
+  // 閿�姣侀獙璇佺爜杩囨湡璁℃椂鍣�
+  clearInterval(timer);
+  timer = null;
+  clearInterval(phonetimer);
+  phonetimer = null;
+
+  document.removeEventListener("keyup", handleKeyPress);
+});
+
+// 妫�娴嬪ぇ灏忓啓鎸夐敭
+const handleKeyPress = (e: KeyboardEvent) => {
+  if (e.getModifierState != undefined)
+    state.capsLockVisible = e.getModifierState("CapsLock");
+};
+// 鑾峰彇楠岃瘉鐮�
+const getCaptcha = async () => {
+  // if (!state.captchaEnabled) return;
+
+  state.ruleForm.code = "";
+  const res = await captcha();
+  console.log(res);
+
+  state.captchaImage = "data:text/html;base64," + res.result?.img;
+  state.expirySeconds = res.result?.expirySeconds;
+  state.ruleForm.codeId = res.result?.id;
+};
+const ruleFormRef = ref<FormInstance>();
 
 const locationOptions = ["Home", "Company", "School"];
-
-const rules = reactive<FormRules<RuleForm>>({
-  name: [
-    { required: true, message: "Please input Activity name", trigger: "blur" },
-    { min: 3, max: 5, message: "Length should be 3 to 5", trigger: "blur" }
-  ],
-  region: [
-    {
-      required: true,
-      message: "Please select Activity zone",
-      trigger: "change"
-    }
-  ],
-  count: [
-    {
-      required: true,
-      message: "Please select Activity count",
-      trigger: "change"
-    }
-  ],
-  date1: [
-    {
-      type: "date",
-      required: true,
-      message: "Please pick a date",
-      trigger: "change"
-    }
-  ],
-  date2: [
-    {
-      type: "date",
-      required: true,
-      message: "Please pick a time",
-      trigger: "change"
-    }
-  ],
-  location: [
-    {
-      required: true,
-      message: "Please select a location",
-      trigger: "change"
-    }
-  ],
-  type: [
-    {
-      type: "array",
-      required: true,
-      message: "Please select at least one activity type",
-      trigger: "change"
-    }
-  ],
-  resource: [
-    {
-      required: true,
-      message: "Please select activity resource",
-      trigger: "change"
-    }
-  ],
-  desc: [
-    { required: true, message: "Please input activity form", trigger: "blur" }
-  ]
-});
 // 楠岃瘉鐮佸尯鍩熸枃瀛楄鏄�
 const spanRef = ref();
-const isSendValidationCode = ref<string>("鑾峰彇楠岃瘉鐮�");
 const submitForm = async (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   await formEl.validate((valid, fields) => {
     if (valid) {
-      console.log("submit!");
-    } else {
-      console.log("error submit!", fields);
-    }
+      state.ruleForm.account = state.ruleForm.phone;
+      register(state.ruleForm).then(res => {
+        if (res?.code == 200) {
+          router.replace("/RegisterSucess");
+          return message("娉ㄥ唽鎴愬姛锛�", { type: "success" });
+        } else {
+          return message(res?.message, { type: "warning" });
+        }
+      });
+    } else if (!checked1.value)
+      return message("璇峰嬀閫夌敤鎴峰崗璁�", { type: "warning" });
   });
 };
 
-const sendValidationCode = () => {};
+const sendValidationCode = async () => {
+  if (!state.ruleForm.phone) {
+    return message("璇峰厛杈撳叆鎵嬫満鍙�", { type: "warning" });
+  }
+  if (!state.ruleForm.code) {
+    return message("璇峰厛杈撳叆楠岃瘉鐮�", { type: "warning" });
+  }
+  const res = await phoneNumberCode(state.ruleForm);
+  if (res?.code != 200) {
+    return message(res?.message, { type: "warning" });
+  }
+  state.phoneSeconds = 60;
+  phonetimer = setInterval(() => {
+    if (state.phoneSeconds > 0) state.phoneSeconds -= 1;
+  }, 1000);
+};
 
 const resetForm = (formEl: FormInstance | undefined) => {
   if (!formEl) return;
@@ -296,4 +416,49 @@
     }
   }
 }
+.el-form-item {
+  align-items: center;
+}
+#suffix-span {
+  cursor: pointer;
+}
+.login-content-code {
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+  position: relative;
+
+  .login-content-code-img {
+    width: 100%;
+    height: 40px;
+    line-height: 40px;
+    background-color: #ffffff;
+    border: 1px solid rgb(220, 223, 230);
+    cursor: pointer;
+    transition: all ease 0.2s;
+    border-radius: 4px;
+    user-select: none;
+
+    &:hover {
+      border-color: #c0c4cc;
+      transition: all ease 0.2s;
+    }
+  }
+}
+
+.login-content-code-expired {
+  @extend .login-content-code;
+  &::before {
+    content: "楠岃瘉鐮佸凡杩囨湡";
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    border-radius: 4px;
+    background-color: rgba(0, 0, 0, 0.5);
+    color: #ffffff;
+    text-align: center;
+  }
+}
 </style>

--
Gitblit v1.9.1