register.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <template>
  2. <view class="w-screen h-screen flex flex-col" :style="themeColor()">
  3. <view class="mx-[60rpx]">
  4. <view class="pt-[140rpx] text-[44rpx] font-500 text-[#333]">账号注册</view>
  5. <view class="flex items-center justify-between mt-[24rpx] mb-[90rpx]">
  6. <view class="text-[26rpx] text-[#333] leading-[34rpx]" @click="toLink">
  7. <text>已有账号,</text>
  8. <text class="text-primary">去登录</text>
  9. </view>
  10. </view>
  11. <u-form labelPosition="left" :model="formData" errorType="toast" :rules="rules" ref="formRef">
  12. <view class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6]">
  13. <u-form-item label="" prop="purchaseName" :border-bottom="false">
  14. <u-input v-model="formData.purchaseName" border="none" maxlength="40" placeholder="请输入姓名"
  15. class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx"
  16. placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]" />
  17. </u-form-item>
  18. </view>
  19. <view
  20. class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6] mt-[40rpx]">
  21. <u-form-item label="" prop="customerName" :border-bottom="false">
  22. <u-input v-model="formData.customerName" border="none" maxlength="40" placeholder="请输入企业全称"
  23. class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx"
  24. placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]" />
  25. </u-form-item>
  26. </view>
  27. <view
  28. class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6] mt-[40rpx]">
  29. <u-form-item label="" prop="purchasePhone" :border-bottom="false">
  30. <u-input v-model="formData.purchasePhone" border="none" maxlength="11" placeholder="请输入手机号"
  31. class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx"
  32. placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]" />
  33. </u-form-item>
  34. </view>
  35. <view
  36. class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6] mt-[40rpx]">
  37. <u-form-item label="" prop="code" :border-bottom="false">
  38. <u-input v-model="formData.code" border="none" maxlength="40" placeholder="请输入验证码"
  39. class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx"
  40. placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
  41. <template #suffix>
  42. <up-code ref="uCodeRef" @change="codeChange" seconds="60" changeText="X秒重新获取"></up-code>
  43. <up-button class="!bg-[var(--primary-color)] !text-[#fff]" @tap="getCode" :text="tips"
  44. size="mini"></up-button>
  45. </template></u-input>
  46. </u-form-item>
  47. </view>
  48. <view
  49. class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6] mt-[40rpx]">
  50. <u-form-item label="" prop="password" :border-bottom="false">
  51. <u-input v-model="formData.password" border="none" :password="isPassword" maxlength="40"
  52. placeholder="请输入密码" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx"
  53. placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
  54. <template #suffix>
  55. <view @click="changePassword" v-if="formData.password">
  56. <u-icon :name="isPassword ? 'eye-off' : 'eye-fill'" color="#b9b9b9"
  57. size="20"></u-icon>
  58. </view>
  59. </template>
  60. </u-input>
  61. </u-form-item>
  62. </view>
  63. <view
  64. class="h-[88rpx] flex w-full items-center px-[30rpx] rounded-[40rpx] box-border bg-[#F6F6F6] mt-[40rpx]">
  65. <u-form-item label="" prop="confirmPassword" :border-bottom="false">
  66. <u-input v-model="formData.confirmPassword" border="none" :password="isConfirmPassword"
  67. maxlength="40" placeholder="请再次输入密码" class="!bg-transparent" :disabled="real_name_input"
  68. fontSize="26rpx" placeholderClass="!text-[var(--text-color-light9)] text-[26rpx]">
  69. <template #suffix>
  70. <view @click="changeConfirmPassword" v-if="formData.confirmPassword">
  71. <u-icon :name="isConfirmPassword ? 'eye-off' : 'eye-fill'" color="#b9b9b9"
  72. size="20"></u-icon>
  73. </view>
  74. </template>
  75. </u-input>
  76. </u-form-item>
  77. </view>
  78. </u-form>
  79. <view class="mt-[140rpx]">
  80. <button
  81. class="w-full h-[80rpx] !bg-[var(--primary-color)] text-[26rpx] rounded-[40rpx] leading-[80rpx] font-500 !text-[#fff]"
  82. @click="handleRegister">
  83. 注册
  84. </button>
  85. <view class="flex items-center mt-[10rpx] mb-[40rpx] py-[14rpx]" @click.stop="agreeChange">
  86. <u-checkbox-group @change="agreeChange">
  87. <u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="circle" size="24rpx" />
  88. </u-checkbox-group>
  89. <view
  90. class="text-[24rpx] -ml-[4rpx] text-[var(--text-color-light6)] flex items-center flex-wrap leading-[30rpx]">
  91. <text>我已阅读并同意</text>
  92. <text @click.stop="
  93. redirect({ url: '/app/pages/auth/agreement?key=privacy' })
  94. " class="text-primary">《用户服务协议》</text>
  95. </view>
  96. </view>
  97. </view>
  98. </view>
  99. </view>
  100. </template>
  101. <script setup lang="ts">
  102. import { ref, reactive, computed, onMounted } from "vue";
  103. import { usernameRegister, mobileRegister, registerMiniCustomer, getOpenId } from "@/app/api/auth";
  104. import useMemberStore from "@/stores/member";
  105. import useConfigStore from "@/stores/config";
  106. import { t } from "@/locale";
  107. import { redirect, getToken, pxToRpx } from "@/utils/common";
  108. import { onLoad } from "@dcloudio/uni-app";
  109. import { smsCode } from '@/app/api/system'
  110. const formData = reactive({
  111. purchaseName: "",
  112. customerName: "",
  113. purchasePhone: "",
  114. code: "",
  115. password: "",
  116. confirmPassword: "",
  117. openId: "",
  118. RegisterSource: ""
  119. });
  120. onLoad(async (option: any) => {
  121. // #ifdef MP-WEIXIN
  122. formData.RegisterSource = '2'
  123. // #endif
  124. });
  125. const loading = ref(false)
  126. const real_name_input = ref(true);
  127. onMounted(() => {
  128. // 防止浏览器自动填充
  129. setTimeout(() => {
  130. real_name_input.value = false;
  131. }, 800);
  132. });
  133. const isPassword = ref(true);
  134. const isConfirmPassword = ref(true);
  135. const changePassword = () => {
  136. isPassword.value = !isPassword.value;
  137. };
  138. const changeConfirmPassword = () => {
  139. isConfirmPassword.value = !isConfirmPassword.value;
  140. };
  141. const configStore = useConfigStore();
  142. const tips = ref('');
  143. const uCodeRef = ref<any>(null);
  144. // 获取验证码
  145. const codeChange = (text: any) => {
  146. tips.value = text;
  147. };
  148. const getCode = () => {
  149. if (uCodeRef.value.canGetCode) {
  150. // 模拟向后端请求验证码
  151. uni.showLoading({
  152. title: '正在获取验证码',
  153. });
  154. smsCode({ phonenumber: formData.purchasePhone }).then((res: any) => {
  155. if (res.code == 200) {
  156. uni.hideLoading();
  157. // 这里此提示会被start()方法中的提示覆盖
  158. uni.$u.toast('验证码已发送');
  159. // 通知验证码组件内部开始倒计时
  160. uCodeRef.value.start();
  161. }
  162. }).catch(() => {
  163. uni.hideLoading();
  164. });
  165. } else {
  166. uni.$u.toast('倒计时结束后再发送');
  167. }
  168. };
  169. const agreeChange = () => {
  170. isAgree.value = !isAgree.value;
  171. };
  172. const rules = computed(() => {
  173. return {
  174. purchaseName: [
  175. {
  176. type: "string",
  177. required: true,
  178. message: '请输入姓名',
  179. trigger: ["blur", "change"],
  180. }
  181. ],
  182. customerName: [
  183. {
  184. type: "string",
  185. required: true,
  186. message: '请输入企业全称',
  187. trigger: ["blur", "change"],
  188. }
  189. ],
  190. purchasePhone: [
  191. {
  192. type: "string",
  193. required: true,
  194. message: '请输入手机号',
  195. trigger: ["blur", "change"],
  196. },
  197. {
  198. validator(rule: any, value: any) {
  199. return uni.$u.test.mobile(value);
  200. },
  201. message: '请输入正确的手机号',
  202. trigger: ["change", "blur"],
  203. },
  204. ],
  205. password: {
  206. type: "string",
  207. required: true,
  208. message: '请输入密码',
  209. trigger: ["blur", "change"],
  210. },
  211. confirmPassword: [
  212. {
  213. type: "string",
  214. required: true,
  215. message: "请再次输入密码",
  216. trigger: ["blur", "change"],
  217. },
  218. {
  219. validator(rule: any, value: any) {
  220. return value == formData.password;
  221. },
  222. message: "两次输入的密码不一致",
  223. trigger: ["change", "blur"],
  224. },
  225. ],
  226. code: {
  227. type: "string",
  228. required: true,
  229. message: "请输入验证码",
  230. trigger: ["blur", "change"],
  231. }
  232. };
  233. });
  234. const isAgree = ref(false);
  235. const formRef: any = ref(null)
  236. const handleRegister = () => {
  237. formRef.value.validate().then(() => {
  238. if (!isAgree.value) {
  239. uni.$u.toast('请勾选并阅读用户协议');
  240. return false;
  241. }
  242. if (loading.value) return;
  243. loading.value = true;
  244. // #ifdef MP-WEIXIN
  245. uni.login({
  246. provider: 'weixin',
  247. success: function (loginRes) {
  248. getOpenId({ code: loginRes.code })
  249. .then((res1: any) => {
  250. if (res1.msg) {
  251. formData.openId = res1.msg
  252. registerMiniCustomer(formData).then((res: any) => {
  253. if (res.code == 200) {
  254. redirect({ url: '/wap/app/pages/auth/login', mode: 'redirectTo' })
  255. }
  256. }).catch(() => { loading.value = false; });
  257. }
  258. }).catch((res: any) => { });
  259. },
  260. fail: function (err) {
  261. uni.showToast({ title: '微信注册失败', icon: 'none' });
  262. }
  263. });
  264. // #endif
  265. // #ifndef MP-WEIXIN
  266. registerMiniCustomer(formData).then((res: any) => {
  267. if (res.code == 200) {
  268. redirect({ url: '/wap/app/pages/auth/login', mode: 'redirectTo' })
  269. }
  270. }).catch(() => { loading.value = false; });
  271. // #endif
  272. });
  273. };
  274. const toLink = () => {
  275. const pages = getCurrentPages(); // 获取页面栈
  276. if (pages.length > 1) {
  277. const currentPage = pages[pages.length - 2].route;
  278. if (currentPage == "app/pages/auth/login") {
  279. // 返回上一页
  280. uni.navigateBack({
  281. delta: 1, // 默认值是1,表示返回的页面层数
  282. });
  283. } else {
  284. redirect({ url: "/app/pages/auth/login", mode: "redirectTo" });
  285. }
  286. } else {
  287. redirect({ url: "/app/pages/auth/login", mode: "redirectTo" });
  288. }
  289. };
  290. </script>
  291. <style lang="scss" scoped>
  292. :deep(.u-input) {
  293. background-color: transparent !important;
  294. }
  295. :deep(.u-form-item) {
  296. flex: 1;
  297. .u-line {
  298. display: none;
  299. }
  300. .u-input__content__subfix-icon {
  301. display: flex;
  302. align-items: center;
  303. }
  304. }
  305. :deep(.u-checkbox) {
  306. margin: 0 !important;
  307. }
  308. .footer {
  309. padding-bottom: calc(151rpx + constant(safe-area-inset-bottom));
  310. padding-bottom: calc(151rpx + env(safe-area-inset-bottom));
  311. }
  312. </style>