login.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <template>
  2. <view class="login">
  3. <!-- 主要内容区域 -->
  4. <view class="content">
  5. <!-- Logo和标题区域 -->
  6. <view class="header">
  7. <view class="title">欢迎登录</view>
  8. <view class="subtitle">登录您的账号,开启聊天之旅</view>
  9. </view>
  10. <!-- 表单区域 -->
  11. <view class="form-container">
  12. <view class="form">
  13. <view class="form-item" :class="{'focused': userNameFocused}">
  14. <view class="icon-wrapper">
  15. <view class="icon iconfont icon-username"></view>
  16. </view>
  17. <input class="input" type="text" v-model="dataForm.userName" placeholder="用户名"
  18. @focus="userNameFocused = true" @blur="userNameFocused = false" />
  19. </view>
  20. <view class="form-item" :class="{'focused': passwordFocused}">
  21. <view class="icon-wrapper">
  22. <view class="icon iconfont icon-pwd"></view>
  23. </view>
  24. <input class="input" :type="isShowPwd?'text':'password'" v-model="dataForm.password"
  25. placeholder="密码" @focus="passwordFocused = true" @blur="passwordFocused = false" />
  26. <view class="icon-suffix iconfont" :class="isShowPwd?'icon-pwd-show':'icon-pwd-hide'"
  27. @click="onSwitchShowPwd"></view>
  28. </view>
  29. </view>
  30. <!-- 登录按钮 -->
  31. <button class="submit-btn" @click="submit" type="primary">
  32. <view class="btn-content">
  33. <text class="btn-text">立即登录</text>
  34. </view>
  35. </button>
  36. <!-- 底部导航 -->
  37. <view class="nav-tool-bar">
  38. <view class="nav-register">
  39. <navigator url="/pages/register/register" class="register-link">
  40. <text class="register-text">没有账号?</text>
  41. <text class="register-highlight">立即注册</text>
  42. </navigator>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. </template>
  49. <script>
  50. import UNI_APP from '@/.env.js';
  51. export default {
  52. data() {
  53. return {
  54. isShowPwd: false,
  55. userNameFocused: false,
  56. passwordFocused: false,
  57. dataForm: {
  58. terminal: 1, // APP终端
  59. userName: '',
  60. password: ''
  61. }
  62. }
  63. },
  64. methods: {
  65. submit() {
  66. if (!this.dataForm.userName) {
  67. return uni.showToast({
  68. title: "请输入您的账号",
  69. icon: "none"
  70. })
  71. }
  72. if (!this.dataForm.password) {
  73. return uni.showToast({
  74. title: "请输入您的密码",
  75. icon: "none"
  76. })
  77. }
  78. this.$http({
  79. url: '/login',
  80. data: this.dataForm,
  81. method: 'POST'
  82. }).then(loginInfo => {
  83. console.log("登录成功,自动跳转到聊天页面...")
  84. uni.setStorageSync("userName", this.dataForm.userName);
  85. uni.setStorageSync("password", this.dataForm.password);
  86. uni.setStorageSync("isAgree", this.isAgree);
  87. uni.setStorageSync("loginInfo", loginInfo);
  88. // 调用App.vue的初始化方法
  89. getApp().$vm.init()
  90. // 跳转到聊天页面
  91. uni.switchTab({
  92. url: "/pages/chat/chat"
  93. })
  94. }).catch((e) => {
  95. console.log("登录失败:", e);
  96. })
  97. // 清理数据,防止缓存未失效
  98. getApp().$vm.unloadStore();
  99. },
  100. onSwitchShowPwd() {
  101. this.isShowPwd = !this.isShowPwd;
  102. },
  103. },
  104. onLoad() {
  105. this.dataForm.userName = uni.getStorageSync("userName");
  106. this.dataForm.password = uni.getStorageSync("password");
  107. }
  108. }
  109. </script>
  110. <style lang="scss" scoped>
  111. .login {
  112. position: relative;
  113. display: flex;
  114. flex-direction: column;
  115. overflow: hidden;
  116. // 主要内容区域
  117. .content {
  118. position: relative;
  119. display: flex;
  120. flex-direction: column;
  121. margin-top: 120rpx;
  122. // #ifdef APP-PLUS
  123. margin-top: calc(120rpx + var(--status-bar-height));
  124. // #endif
  125. padding: 0 60rpx;
  126. }
  127. // 头部区域
  128. .header {
  129. text-align: center;
  130. padding: 80rpx 0;
  131. .title {
  132. color: $im-color-primary;
  133. font-size: 48rpx;
  134. font-weight: 700;
  135. margin-bottom: 20rpx;
  136. letter-spacing: 2rpx;
  137. }
  138. .subtitle {
  139. color: $im-text-color-light;
  140. font-size: 28rpx;
  141. opacity: 0.8;
  142. }
  143. }
  144. // 表单容器
  145. .form-container {
  146. display: flex;
  147. flex-direction: column;
  148. }
  149. // 表单样式
  150. .form {
  151. margin-bottom: 20rpx;
  152. .form-item {
  153. position: relative;
  154. display: flex;
  155. align-items: center;
  156. padding: 0 30rpx;
  157. height: 100rpx;
  158. margin: 24rpx 0;
  159. border-radius: 25rpx;
  160. background: rgba(255, 255, 255, 0.9);
  161. border: 2rpx solid transparent;
  162. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
  163. transition: all 0.3s ease;
  164. &.focused {
  165. border-color: $im-color-primary;
  166. box-shadow: 0 8rpx 32rpx rgba($im-color-primary, 0.15);
  167. transform: translateY(-2rpx);
  168. }
  169. .icon-wrapper {
  170. display: flex;
  171. align-items: center;
  172. justify-content: center;
  173. width: 60rpx;
  174. height: 60rpx;
  175. margin-right: 30rpx;
  176. border-radius: 50%;
  177. background: $im-bg-active;
  178. transition: all 0.3s ease;
  179. .icon {
  180. font-size: 32rpx;
  181. color: $im-color-primary;
  182. font-weight: bold;
  183. }
  184. }
  185. &.focused .icon-wrapper {
  186. transform: scale(1.1);
  187. }
  188. .input {
  189. flex: 1;
  190. font-size: 32rpx;
  191. color: #333;
  192. background: transparent;
  193. border: none;
  194. outline: none;
  195. &::placeholder {
  196. color: $im-text-color-light;
  197. font-size: 30rpx;
  198. }
  199. }
  200. .icon-suffix {
  201. font-size: 36rpx;
  202. padding: 10rpx;
  203. }
  204. }
  205. }
  206. // 登录按钮
  207. .submit-btn {
  208. height: 100rpx;
  209. border-radius: 50rpx;
  210. border: none;
  211. transition: all 0.3s ease;
  212. overflow: hidden;
  213. position: relative;
  214. width: 100%;
  215. &:active {
  216. transform: translateY(2rpx);
  217. &::before {
  218. left: 100%;
  219. }
  220. }
  221. .btn-content {
  222. display: flex;
  223. align-items: center;
  224. justify-content: center;
  225. height: 100%;
  226. color: white;
  227. font-size: $im-font-size-large;
  228. font-weight: 600;
  229. .btn-text {
  230. margin-right: 10rpx;
  231. }
  232. }
  233. &:active .btn-icon {
  234. transform: translateX(4rpx);
  235. }
  236. }
  237. // 底部导航
  238. .nav-tool-bar {
  239. padding: 40rpx 0 60rpx;
  240. display: flex;
  241. align-items: center;
  242. justify-content: space-between;
  243. .nav-register {
  244. .register-link {
  245. display: flex;
  246. align-items: center;
  247. text-decoration: none;
  248. .register-text {
  249. color: $im-text-color-light;
  250. font-size: $im-font-size-small;
  251. margin-right: 8rpx;
  252. }
  253. .register-highlight {
  254. color: $im-color-primary;
  255. font-size: $im-font-size-small;
  256. font-weight: 600;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. </style>