login.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <template>
  2. <div class="login_page" >
  3. <div class="login_header">
  4. <div class="header_left">
  5. <img src="../../assets/login/login_logo.webp" alt="">
  6. <span style="margin-left: 10px;"> 大数据精准教学诊断平台</span>
  7. </div>
  8. <div class="header_right">
  9. <div class="right_button" @click="GoWebsite" >
  10. 官方网站
  11. </div>
  12. </div>
  13. </div>
  14. <div class="login_content" id="particles">
  15. <div class="login_info">
  16. <div class="login_info_title">
  17. <p>HI~欢迎使用</p>
  18. <p>大数据精准教学诊断平台
  19. </p>
  20. </div>
  21. <div class="login_info_message">
  22. 后台管理系统登录
  23. </div>
  24. <div class="login_info_input">
  25. <el-input
  26. v-model="userName"
  27. placeholder="请输入账号"
  28. >
  29. <template #prefix>
  30. <span>
  31. <img
  32. src="../../assets/login/input_user.webp"
  33. alt="User Icon"
  34. style="width: 18px; height: 18px"
  35. />
  36. </span>
  37. </template>
  38. <template #suffix v-if="userName != ''">
  39. <span @click="ClearInput" style="cursor: pointer">
  40. <img
  41. src="../../assets/login/input_clear.webp"
  42. alt="Clear Icon"
  43. style="width: 18px; height: 18px"
  44. />
  45. </span>
  46. </template>
  47. </el-input>
  48. </div>
  49. <div class="login_info_input">
  50. <el-input
  51. v-model="passWord"
  52. show-password
  53. placeholder="请输入密码"
  54. >
  55. <template #prefix>
  56. <span>
  57. <img
  58. src="../../assets/login/input_pass.webp"
  59. alt="User Icon"
  60. style="width: 18px; height: 18px"
  61. />
  62. </span>
  63. </template>
  64. <template #suffix>
  65. <i
  66. class="iconfont icon-ttubiao_hide"
  67. ></i>
  68. </template>
  69. </el-input>
  70. </div>
  71. <div class="login_info_item">
  72. <div class="item_left">
  73. <el-checkbox v-model="remeberPassWord">记住密码</el-checkbox>
  74. </div>
  75. <div class="item_right">忘记密码</div>
  76. </div>
  77. <div class="login_info_button">
  78. <el-button style="width:100%;" @click="SubmitLogin()" :loading="loadingLogin">登 录</el-button>
  79. </div>
  80. <div class="login_other_type">
  81. <div class="other_login_line">
  82. <span class="line"></span>
  83. <span class="text">其他登录方式</span>
  84. <span class="line"></span>
  85. </div>
  86. <div class="other_login_icon">
  87. <div class="icon_item">
  88. <img src="../../assets/login/login_wechat.webp" alt=""></img>
  89. <p>微信</p>
  90. </div>
  91. <div class="icon_item">
  92. <img src="../../assets/login/login_feishu.webp" alt=""></img>
  93. <p>钉钉</p>
  94. </div>
  95. <div class="icon_item">
  96. <img src="../../assets/login/login_email.webp" alt=""></img>
  97. <p>邮箱</p>
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. </div>
  103. </div>
  104. </template>
  105. <script setup>
  106. import { ref, onMounted } from 'vue'
  107. // import particles from 'particles.js'
  108. import { login, getUserInfo } from '@/api/login'
  109. import { ElMessage } from 'element-plus' //
  110. import { useRouter } from 'vue-router'
  111. const router = useRouter() // 获取路由实例
  112. // 响应式数据
  113. const userName = ref('')
  114. const passWord = ref('')
  115. const remeberPassWord = ref(false)
  116. const loadingLogin = ref(false)
  117. // 粒子动画初始化
  118. const InitParticles = () => {
  119. const particlesConfig = {
  120. particles: {
  121. number: {
  122. value: 60,
  123. density: {
  124. enable: true,
  125. value_area: 800
  126. }
  127. },
  128. color: {
  129. value: '#ffffff'
  130. },
  131. shape: {
  132. type: ['circle'],
  133. stroke: {
  134. width: 0,
  135. color: '#000000'
  136. },
  137. polygon: {
  138. nb_sides: 5
  139. },
  140. image: {
  141. src: 'img/github.svg',
  142. width: 100,
  143. height: 100
  144. }
  145. },
  146. opacity: {
  147. value: 0.5,
  148. random: false,
  149. anim: {
  150. enable: false,
  151. speed: 1,
  152. opacity_min: 0.1,
  153. sync: false
  154. }
  155. },
  156. size: {
  157. value: 3,
  158. random: false,
  159. anim: {
  160. enable: true,
  161. speed: 40,
  162. size_min: 0.1,
  163. sync: false
  164. }
  165. },
  166. line_linked: {
  167. enable: true,
  168. distance: 150,
  169. color: '#ffffff',
  170. opacity: 0.4,
  171. width: 1
  172. },
  173. move: {
  174. enable: true,
  175. speed: 6,
  176. direction: 'none',
  177. random: false,
  178. straight: false,
  179. out_mode: 'out',
  180. bounce: false,
  181. attract: {
  182. enable: false,
  183. rotateX: 600,
  184. rotateY: 1200
  185. }
  186. }
  187. },
  188. interactivity: {
  189. detect_on: 'canvas',
  190. events: {
  191. onhover: {
  192. enable: true,
  193. mode: 'grab'
  194. },
  195. onclick: {
  196. enable: true,
  197. mode: 'push'
  198. },
  199. resize: true
  200. },
  201. modes: {
  202. grab: {
  203. distance: 140,
  204. line_linked: {
  205. opacity: 1
  206. }
  207. },
  208. bubble: {
  209. distance: 400,
  210. size: 40,
  211. duration: 2,
  212. opacity: 8,
  213. speed: 3
  214. },
  215. repulse: {
  216. distance: 200,
  217. duration: 0.4
  218. },
  219. push: {
  220. particles_nb: 4
  221. },
  222. remove: {
  223. particles_nb: 2
  224. }
  225. }
  226. },
  227. retina_detect: true
  228. }
  229. particlesJS('particles', particlesConfig, () => {
  230. console.log('粒子动画特效加载成功')
  231. })
  232. }
  233. onMounted(() => {
  234. // InitParticles()
  235. })
  236. // 清空输入框
  237. const ClearInput = () => {
  238. userName.value = ''
  239. }
  240. // 登录提交
  241. const SubmitLogin = () => {
  242. const params = {
  243. username: userName.value.trim(),
  244. password: passWord.value.trim()
  245. }
  246. loadingLogin.value = true
  247. login(params).then((res) => {
  248. loadingLogin.value = false
  249. if (res.code === 200) {
  250. console.log("登录成功返回",res)
  251. localStorage.setItem('token', res.data.tokenValue)
  252. // 登录成功后调用获取用户信息接口
  253. return getUserInfo(res.data.token)
  254. }
  255. }).then((userInfoRes)=>{
  256. console.log("获取用户信息返回",userInfoRes)
  257. if (userInfoRes && userInfoRes.code === 200) {
  258. // 存储用户信息到 localStorage 或 Pinia
  259. localStorage.setItem('userInfo', JSON.stringify(userInfoRes.data))
  260. ElMessage.success('登录成功');
  261. // 跳转到主页
  262. router.push('/main/school')
  263. }
  264. }).catch((err) => {
  265. loadingLogin.value = false
  266. ElMessage.error('登录失败!'+err);
  267. console.error(err)
  268. })
  269. }
  270. // 去往官网
  271. const GoWebsite = () => {
  272. window.open('https://www.k12100.com/')
  273. }
  274. </script>
  275. <style lang="scss">
  276. @use "../../styles/login.scss" as *;
  277. </style>