You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

465 lines
9.2 KiB

1 month ago
  1. <template>
  2. <view class="login-registration-container">
  3. <!-- 自定义导航栏 -->
  4. <view
  5. class="custom-navbar"
  6. :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
  7. >
  8. <view class="nav-left">
  9. <text class="back-btn" @click="goToIndex"></text>
  10. </view>
  11. <view class="nav-right">
  12. <text class="headphone-btn">🎧</text>
  13. </view>
  14. </view>
  15. <!-- Logo -->
  16. <image class="logo" src="/static/logo.png" mode="aspectFit"></image>
  17. <!-- 欢迎语 -->
  18. <text class="welcome-text">登录</text>
  19. <!-- 邮箱/手机号切换 -->
  20. <view class="switch-container">
  21. <text
  22. class="switch-item"
  23. :class="{ active: switchType === 'Email' }"
  24. @click="switchEmail"
  25. >邮箱/用户名</text
  26. >
  27. <text
  28. class="switch-item"
  29. :class="{ active: switchType === 'Phone' }"
  30. @click="switchPhone"
  31. >手机号</text
  32. >
  33. </view>
  34. <!-- 输入框 -->
  35. <view class="input-container">
  36. <input
  37. v-if="switchType === 'Email'"
  38. class="input-field"
  39. type="text"
  40. placeholder="输入邮箱/用户名"
  41. v-model="email"
  42. />
  43. <view v-else class="phone-input-container">
  44. <view class="country-code-selector" @click="showCountryPicker">
  45. <text class="country-flag">{{ selectedCountry.flag }}</text>
  46. <text class="country-code">{{ selectedCountry.code }}</text>
  47. <text class="arrow-down"></text>
  48. </view>
  49. <input
  50. class="input-field phone-input"
  51. type="number"
  52. placeholder="输入手机号"
  53. v-model="phone"
  54. @input="onPhoneInput"
  55. />
  56. </view>
  57. </view>
  58. <!-- 注册按钮 -->
  59. <button class="register-btn" @click="register">下一步</button>
  60. <!-- 或者 -->
  61. <text class="or-text">或者</text>
  62. <!-- 第三方登录 -->
  63. <view class="third-party-login">
  64. <view class="third-party-btn" @click="loginWithApple">
  65. <image
  66. class="apple-icon"
  67. src="/static/apple-icon.png"
  68. mode="aspectFit"
  69. ></image>
  70. <text class="third-party-text">通过 Apple 继续</text>
  71. </view>
  72. <view class="third-party-btn" @click="loginWithGoogle">
  73. <image
  74. class="google-icon"
  75. src="/static/google-icon.png"
  76. mode="aspectFit"
  77. ></image>
  78. <text class="third-party-text">通过 Google 继续</text>
  79. </view>
  80. </view>
  81. <!-- 已有账号 -->
  82. <view class="existing-account">
  83. <text class="account-text">未注册账号</text>
  84. <text class="login-link" @click="goToRegistration">注册</text>
  85. </view>
  86. </view>
  87. </template>
  88. <script setup>
  89. import { ref } from "vue";
  90. const email = ref("");
  91. const phone = ref("");
  92. const agreed = ref(false);
  93. const switchType = ref("Email"); // 默认是邮箱注册
  94. const { safeAreaInsets } = uni.getSystemInfoSync();
  95. // 国家前缀数据(添加国旗)
  96. const countries = ref([
  97. { name: '中国', code: '+86', flag: '🇨🇳' },
  98. { name: '美国', code: '+1', flag: '🇺🇸' },
  99. { name: '英国', code: '+44', flag: '🇬🇧' },
  100. { name: '日本', code: '+81', flag: '🇯🇵' },
  101. { name: '韩国', code: '+82', flag: '🇰🇷' },
  102. { name: '德国', code: '+49', flag: '🇩🇪' },
  103. { name: '法国', code: '+33', flag: '🇫🇷' },
  104. { name: '加拿大', code: '+1', flag: '🇨🇦' },
  105. { name: '澳大利亚', code: '+61', flag: '🇦🇺' },
  106. { name: '俄罗斯', code: '+7', flag: '🇷🇺' },
  107. { name: '印度', code: '+91', flag: '🇮🇳' },
  108. { name: '巴西', code: '+55', flag: '🇧🇷' },
  109. ]);
  110. // 默认选中的国家
  111. const selectedCountry = ref(countries.value[0]);
  112. // 显示国家选择器
  113. function showCountryPicker() {
  114. uni.showActionSheet({
  115. itemList: countries.value.map(country => `${country.flag} ${country.name} ${country.code}`),
  116. success: function (res) {
  117. selectedCountry.value = countries.value[res.tapIndex];
  118. }
  119. });
  120. }
  121. function goToIndex() {
  122. // 返回上一页
  123. uni.navigateTo({ url: "/pages/start/index/index" });
  124. }
  125. function switchEmail() {
  126. // 切换到邮箱注册
  127. switchType.value = "Email";
  128. }
  129. function switchPhone() {
  130. // 切换到手机注册
  131. switchType.value = "Phone";
  132. }
  133. function register() {
  134. if (switchType.value === "Email") {
  135. // 登录逻辑
  136. if (!email.value) {
  137. uni.showToast({
  138. title: "请输入邮箱地址",
  139. icon: "none",
  140. });
  141. return;
  142. }
  143. // 发送登录请求
  144. console.log("登录:", email.value);
  145. }
  146. if(switchType.value === "Phone"){
  147. // 登录逻辑
  148. if (!phone.value) {
  149. uni.showToast({
  150. title: "请输入手机号码",
  151. icon: "none",
  152. });
  153. return;
  154. }
  155. // 发送登录请求
  156. console.log("登录:", phone.value);
  157. }
  158. }
  159. function loginWithApple() {
  160. // Apple登录逻辑
  161. console.log("通过Apple登录");
  162. }
  163. function loginWithGoogle() {
  164. // Google登录逻辑
  165. console.log("通过Google登录");
  166. }
  167. function goToRegistration() {
  168. // 跳转到登录页
  169. uni.navigateTo({
  170. url: "/pages/start/Registration/Registration",
  171. });
  172. }
  173. function onPhoneInput(e) {
  174. // 确保只允许输入数字
  175. const value = e.detail.value;
  176. // 使用 isNaN 检查是否为有效数字
  177. if (isNaN(value)) {
  178. phone.value = '';
  179. } else {
  180. phone.value = value;
  181. }
  182. }
  183. </script>
  184. <style scoped>
  185. .login-registration-container {
  186. display: flex;
  187. flex-direction: column;
  188. align-items: center;
  189. justify-content: center;
  190. padding: 0 40rpx;
  191. height: 100vh;
  192. background-color: #ffffff;
  193. }
  194. /* 自定义导航栏样式 */
  195. .custom-navbar {
  196. position: absolute;
  197. top: 0;
  198. left: 0;
  199. /* z-index: 999; */
  200. width: 90%;
  201. height: 80rpx;
  202. display: flex;
  203. justify-content: space-between;
  204. align-items: center;
  205. padding: 10rpx 40rpx;
  206. margin-bottom: 20rpx;
  207. }
  208. .nav-left,
  209. .nav-right {
  210. flex: 1;
  211. }
  212. .nav-right {
  213. display: flex;
  214. justify-content: flex-end;
  215. }
  216. .back-btn,
  217. .headphone-btn {
  218. font-size: 36rpx;
  219. font-weight: bold;
  220. color: #333333;
  221. padding: 10rpx;
  222. }
  223. .logo {
  224. width: 120rpx;
  225. height: 120rpx;
  226. margin-bottom: 60rpx;
  227. border-radius: 20%;
  228. }
  229. .welcome-text {
  230. font-size: 48rpx;
  231. font-weight: bold;
  232. color: #333333;
  233. margin-bottom: 60rpx;
  234. text-align: left;
  235. align-self: flex-start;
  236. }
  237. .switch-container {
  238. display: flex;
  239. margin-bottom: 40rpx;
  240. align-self: flex-start;
  241. }
  242. .switch-item {
  243. font-size: 28rpx;
  244. color: #999999;
  245. padding: 10rpx 20rpx;
  246. position: relative;
  247. }
  248. .switch-item::after {
  249. content: "";
  250. position: absolute;
  251. bottom: 0;
  252. left: 50%;
  253. transform: translateX(-50%);
  254. width: 60%; /* 控制边框宽度 */
  255. height: 2rpx;
  256. background-color: transparent;
  257. }
  258. .switch-item.active {
  259. color: #333333;
  260. font-weight: 700;
  261. }
  262. .switch-item.active::after {
  263. content: "";
  264. position: absolute;
  265. top: 60rpx;
  266. bottom: 0;
  267. left: 50%;
  268. transform: translateX(-50%);
  269. width: 30%; /* 控制边框宽度 */
  270. height: 7rpx;
  271. background-color: #333333;
  272. }
  273. .input-container {
  274. width: 100%;
  275. margin-bottom: 40rpx;
  276. }
  277. .input-field {
  278. width: 90%;
  279. height: 80rpx;
  280. border-radius: 20rpx;
  281. border: 2rpx solid #e5e5e5;
  282. padding: 0 30rpx;
  283. font-size: 28rpx;
  284. color: #333333;
  285. background-color: #f5f5f5;
  286. }
  287. .phone-input-container {
  288. display: flex;
  289. align-items: center;
  290. width: 90%;
  291. height: 80rpx;
  292. border-radius: 20rpx;
  293. border: 2rpx solid #e5e5e5;
  294. background-color: #f5f5f5;
  295. padding: 0 10rpx;
  296. }
  297. .country-code-selector {
  298. display: flex;
  299. align-items: center;
  300. padding: 0 20rpx;
  301. height: 100%;
  302. border-right: 2rpx solid #e5e5e5;
  303. background-color: #f0f0f0;
  304. border-radius: 20rpx 0 0 20rpx;
  305. }
  306. .country-code {
  307. font-size: 28rpx;
  308. color: #333333;
  309. margin-right: 10rpx;
  310. }
  311. .country-flag {
  312. font-size: 32rpx;
  313. margin-right: 10rpx;
  314. }
  315. .arrow-down {
  316. font-size: 20rpx;
  317. color: #999999;
  318. }
  319. .phone-input {
  320. flex: 1;
  321. width: auto;
  322. height: 100%;
  323. border: none;
  324. background-color: transparent;
  325. padding: 0 20rpx;
  326. }
  327. .agreement-container {
  328. /* display: flex; */
  329. align-items: center;
  330. margin-bottom: 40rpx;
  331. align-self: flex-start;
  332. }
  333. .checkbox {
  334. width: 10rpx;
  335. height: 10rpx;
  336. margin-right: 30rpx;
  337. /* flex: content; */
  338. }
  339. .agreement-text {
  340. margin-left: 20rpx;
  341. font-size: 24rpx;
  342. color: #666666;
  343. }
  344. .link {
  345. color: #333333;
  346. font-weight: bold;
  347. text-decoration: underline;
  348. }
  349. .register-btn {
  350. width: 100%;
  351. height: 80rpx;
  352. background-color: #333333;
  353. color: white;
  354. font-size: 32rpx;
  355. font-weight: bold;
  356. border-radius: 40rpx;
  357. margin-bottom: 40rpx;
  358. }
  359. .or-text {
  360. font-size: 24rpx;
  361. color: #999999;
  362. margin-bottom: 40rpx;
  363. }
  364. .third-party-login {
  365. width: 100%;
  366. margin-bottom: 60rpx;
  367. }
  368. .third-party-text {
  369. font-weight: bold;
  370. }
  371. .third-party-btn {
  372. width: 100%;
  373. height: 80rpx;
  374. background-color: white;
  375. border: 2rpx solid #e5e5e5;
  376. border-radius: 40rpx;
  377. display: flex;
  378. align-items: center;
  379. justify-content: center;
  380. margin-bottom: 20rpx;
  381. font-size: 28rpx;
  382. color: #333333;
  383. }
  384. .apple-icon {
  385. width: 30rpx;
  386. height: 30rpx;
  387. margin-right: 20rpx;
  388. }
  389. .google-icon {
  390. width: 30rpx;
  391. height: 30rpx;
  392. margin-right: 20rpx;
  393. }
  394. .existing-account {
  395. display: flex;
  396. align-items: center;
  397. }
  398. .account-text {
  399. font-size: 24rpx;
  400. color: #666666;
  401. }
  402. .login-link {
  403. font-size: 24rpx;
  404. font-weight: bold;
  405. color: #333333;
  406. margin-left: 10rpx;
  407. text-decoration: underline;
  408. }
  409. </style>