login.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <route lang="json5">
  2. {
  3. style: {
  4. navigationStyle: 'custom',
  5. navigationBarTitleText: '登录',
  6. },
  7. }
  8. </route>
  9. <template>
  10. <view class="login-container">
  11. <view class="login-box">
  12. <view class="login_title">
  13. <view class="title-en">Hello!</view>
  14. <view class="title-en">欢迎登录橙宝日志</view>
  15. </view>
  16. <!-- 输入框-->
  17. <view class="input-wrapper">
  18. <!-- 账号 -->
  19. <view class="country-code">
  20. <view class="country-phone">
  21. <image class="imgIcon" src="@/static/icon/phone.svg"></image>
  22. <view class="login-text">手机号</view>
  23. </view>
  24. <view class="phone-input">
  25. <view @click="replacePhone">{{ replacePoneValue }}</view>
  26. <image class="w-[32rpx] h-[32rpx]" src="@/static/icon/chevron-right.svg"></image>
  27. <view>
  28. <input v-model="account" type="text" placeholder="请输入手机号" />
  29. </view>
  30. </view>
  31. </view>
  32. <!-- 验证码 -->
  33. <view class="country-password">
  34. <view class="country-phone">
  35. <image class="imgIcon" src="@/static/icon/Verification.svg"></image>
  36. <view class="login-text">验证码</view>
  37. </view>
  38. <view class="phone-input">
  39. <view class="verification-input">
  40. <input v-model="verification" type="text" placeholder="请输入验证码" />
  41. </view>
  42. <image
  43. style="width: 2rpx; height: 32rpx; background: #e7e7e7"
  44. src="@/static/icon/textBor.svg"
  45. ></image>
  46. <view class="send-btn" :disabled="isCountingDown" @click="sendVerificationCode">
  47. {{ buttonText }}
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. <wd-button @click="loginBtn" class="login-button">登录</wd-button>
  53. <!-- 手机 -->
  54. <view @click.stop="showArea = false" v-if="showArea" class="wrap">
  55. <view class="wrap-content">
  56. <wd-index-bar sticky>
  57. <view v-for="item in areaData" :key="item.index">
  58. <wd-index-anchor :index="item.index" />
  59. <wd-cell
  60. border
  61. clickable
  62. v-for="city in item.data"
  63. :key="city"
  64. :title="city"
  65. @click="handleClick(item.index, city)"
  66. ></wd-cell>
  67. </view>
  68. </wd-index-bar>
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. </template>
  74. <script setup>
  75. import { ref, computed } from 'vue'
  76. const account = ref('') // 账号
  77. const verification = ref('') // 验证码
  78. const countdown = ref(0) // 发送验证码
  79. const replacePoneValue = ref('+86')
  80. const isCountingDown = ref(false)
  81. const showArea = ref(false)
  82. const areaData = ref([
  83. {
  84. index: 'A',
  85. data: ['阿坝', '阿拉善', '阿里', '安康', '安庆', '鞍山', '安顺', '安阳', '澳门'],
  86. },
  87. {
  88. index: 'B',
  89. data: [
  90. '北京',
  91. '白银',
  92. '保定',
  93. '宝鸡',
  94. '保山',
  95. '包头',
  96. '巴中',
  97. '北海',
  98. '蚌埠',
  99. '本溪',
  100. '毕节',
  101. '滨州',
  102. '百色',
  103. '亳州',
  104. ],
  105. },
  106. {
  107. index: 'C',
  108. data: [
  109. '重庆',
  110. '成都',
  111. '长沙',
  112. '长春',
  113. '沧州',
  114. '常德',
  115. '昌都',
  116. '长治',
  117. '常州',
  118. '巢湖',
  119. '潮州',
  120. '承德',
  121. '郴州',
  122. '赤峰',
  123. '池州',
  124. '崇左',
  125. '楚雄',
  126. '滁州',
  127. '朝阳',
  128. ],
  129. },
  130. {
  131. index: 'D',
  132. data: [
  133. '大连',
  134. '东莞',
  135. '大理',
  136. '丹东',
  137. '大庆',
  138. '大同',
  139. '大兴安岭',
  140. '德宏',
  141. '德阳',
  142. '德州',
  143. '定西',
  144. '迪庆',
  145. '东营',
  146. ],
  147. },
  148. {
  149. index: 'E',
  150. data: ['鄂尔多斯', '恩施', '鄂州'],
  151. },
  152. {
  153. index: 'F',
  154. data: ['福州', '防城港', '佛山', '抚顺', '抚州', '阜新', '阜阳'],
  155. },
  156. {
  157. index: 'G',
  158. data: ['广州', '桂林', '贵阳', '甘南', '赣州', '甘孜', '广安', '广元', '贵港', '果洛'],
  159. },
  160. {
  161. index: 'H',
  162. data: [
  163. '杭州',
  164. '哈尔滨',
  165. '合肥',
  166. '海口',
  167. '呼和浩特',
  168. '海北',
  169. '海东',
  170. '海南',
  171. '海西',
  172. '邯郸',
  173. '汉中',
  174. '鹤壁',
  175. '河池',
  176. '鹤岗',
  177. '黑河',
  178. '衡水',
  179. '衡阳',
  180. '河源',
  181. '贺州',
  182. '红河',
  183. '淮安',
  184. '淮北',
  185. '怀化',
  186. '淮南',
  187. '黄冈',
  188. '黄南',
  189. '黄山',
  190. '黄石',
  191. '惠州',
  192. '葫芦岛',
  193. '呼伦贝尔',
  194. '湖州',
  195. '菏泽',
  196. ],
  197. },
  198. ])
  199. const buttonText = computed(() => {
  200. return isCountingDown.value ? `${countdown.value}秒后重新发送` : '发送验证码'
  201. })
  202. // 发验证码
  203. const sendVerificationCode = () => {
  204. if (isCountingDown.value) return
  205. countdown.value = 60
  206. isCountingDown.value = true
  207. const timer = setInterval(() => {
  208. countdown.value--
  209. if (countdown.value <= 0) {
  210. clearInterval(timer)
  211. isCountingDown.value = false
  212. }
  213. }, 1000)
  214. }
  215. // 更换手机
  216. const replacePhone = () => {
  217. showArea.value = true
  218. }
  219. // 选取手机地区区号
  220. const handleClick = (item, area) => {
  221. replacePoneValue.value = area
  222. }
  223. // 点击登录
  224. const loginBtn = () => {
  225. console.log(account.value, verification.value, replacePoneValue.value)
  226. console.log(2222)
  227. }
  228. </script>
  229. <style scoped lang="scss">
  230. .login-container {
  231. display: flex;
  232. justify-content: center;
  233. min-height: 100vh;
  234. // background: linear-gradient(0deg, #fff 0%, #ffac78 100%);
  235. background-image: url('@/static/icon/loginGg.svg');
  236. background-repeat: no-repeat;
  237. background-position: center;
  238. background-size: cover;
  239. }
  240. .login-box {
  241. width: 90%;
  242. }
  243. .login_title {
  244. width: 100%;
  245. height: 144rpx;
  246. margin: 200rpx 0 40rpx 0;
  247. .title-en {
  248. margin: 0 0 16rpx 0;
  249. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  250. font-size: 48rpx;
  251. font-weight: 600;
  252. color: #333333;
  253. }
  254. }
  255. .input-wrapper {
  256. position: relative;
  257. width: 100%;
  258. height: 360rpx;
  259. margin: 20rpx 0 40rpx 0;
  260. }
  261. .country-code {
  262. width: 100%;
  263. height: 160rpx;
  264. padding: 32rpx 0;
  265. }
  266. .phone-input {
  267. display: flex;
  268. gap: 20rpx;
  269. align-items: center;
  270. height: 56px; /* 3.5rem = 56px */
  271. border-bottom: 0.5px solid var(--Gray-Gray3, #e7e7e7);
  272. }
  273. .country-phone {
  274. display: flex;
  275. align-items: center;
  276. }
  277. .login-text {
  278. margin-left: 20rpx;
  279. }
  280. .phone-input input {
  281. flex: 1;
  282. padding: 0 32rpx;
  283. font-size: 28rpx;
  284. }
  285. .verification-input {
  286. width: 27.75rem; /* 27.75rem = 444px */
  287. }
  288. .send-btn {
  289. width: 440rpx;
  290. overflow: hidden;
  291. font-size: 28rpx;
  292. color: #f88842;
  293. text-overflow: ellipsis;
  294. white-space: nowrap;
  295. background: transparent;
  296. }
  297. .login-button {
  298. width: 100%;
  299. height: 96rpx;
  300. margin: 160rpx 0 40rpx 0;
  301. font-size: 32rpx;
  302. color: white;
  303. background: #f88842 !important;
  304. border-radius: 16rpx;
  305. }
  306. .wrap {
  307. position: fixed;
  308. top: 0;
  309. left: 0;
  310. z-index: 9999;
  311. width: 100vw;
  312. height: 100vh;
  313. background: rgba(3, 3, 3, 0.2);
  314. }
  315. .wrap-content {
  316. position: relative;
  317. top: 176rpx;
  318. display: flex;
  319. flex-direction: column;
  320. height: calc(100vh - var(--window-top) - env(safe-area-inset-bottom));
  321. }
  322. .imgIcon {
  323. width: 48rpx;
  324. height: 48rpx;
  325. }
  326. </style>