login.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <template>
  2. <div class="login_page" >
  3. <div class="login_header">
  4. <div class="header_left">
  5. <img src="../../assets/login/logo.png" alt="">
  6. <span style="margin-left: 10px;">客户管理系统</span>
  7. </div>
  8. <div class="header_right">
  9. <div class="right_button" @click="GoWebsite">官方网站 </div>
  10. </div>
  11. </div>
  12. <div class="login_content" id="particles">
  13. <div class="login_info">
  14. <div class="login_info_title">
  15. <p>HI~欢迎使用</p>
  16. <p>客户管理系统平台</p>
  17. </div>
  18. <div class="input_tips">请输入账号密码</div>
  19. <!-- <div class="login_info_message">校本选课系统登录</div> -->
  20. <!--
  21. <div class="tab">
  22. <span :class="!isStudentLogin ? 'selected': 'un_selected' " @click="HandleLoginChange(false)">教师</span>
  23. <span :class="isStudentLogin ? 'selected': 'un_selected' " @click="HandleLoginChange(true)">学生</span>
  24. </div> -->
  25. <div class="login_info_input">
  26. <el-form ref="userInfoForm" @submit.prevent="SubmitLogin">
  27. <el-form-item prop="userName">
  28. <el-input v-model="userName" placeholder="请输入账号" @keyup.enter="SubmitLogin">
  29. <template #prefix>
  30. <i class="iconfont icon_zhanghao" />
  31. </template>
  32. <template #suffix>
  33. <img @click.stop="ClearInput" :src="lineCloseIcon" alt="Clear Icon" style="width: 18px;height: 18px;cursor: pointer;">
  34. </template>
  35. </el-input>
  36. </el-form-item>
  37. <el-form-item prop="passWord">
  38. <el-input v-model="passWord" :type="!showPass ? 'password' : 'text'" placeholder="请输入密码" @keyup.enter="SubmitLogin">
  39. <template #prefix>
  40. <img :src="passwordIcon" alt="" style="width: 16px;">
  41. </template>
  42. <template #suffix>
  43. <span style="z-index: 10 !important;" >
  44. <i @click.down="showPass = !showPass" :class="['iconfont', {'icon_xianshimima':showPass},{'icon_buxianshimima':!showPass}]"></i>
  45. </span>
  46. </template>
  47. </el-input>
  48. <!-- <el-input v-model="passWord" placeholder="请输入密码" :type="!showPass ? 'password' : 'text'">
  49. <template #prefix>
  50. <i class="iconfont icon_mima" />
  51. </template>
  52. </el-input> -->
  53. </el-form-item>
  54. </el-form>
  55. </div>
  56. <div class="login_info_item">
  57. <div class="item_left">
  58. <el-checkbox v-model="remeberPassWord">记住密码</el-checkbox>
  59. </div>
  60. <div class="item_right">忘记密码</div>
  61. </div>
  62. <div class="login_info_button">
  63. <el-button style="width:100%;" @click="SubmitLogin()" :loading="loadingLogin">登 录</el-button>
  64. </div>
  65. <!-- <div class="login_other_type"> -->
  66. <!-- <div class="other_login_line">
  67. <span class="line"></span>
  68. <span class="text">其他登录方式</span>
  69. <span class="line"></span>
  70. </div> -->
  71. <!-- <div class="other_login_icon"> -->
  72. <!-- <div class="icon_item">
  73. <img src="../../assets/login/login_wechat.webp" alt=""></img>
  74. <p>微信</p>
  75. </div> -->
  76. <!--
  77. <div class="icon_item">
  78. <img src="../../assets/login/login_feishu.webp" alt=""></img>
  79. <p>钉钉</p>
  80. </div>
  81. <div class="icon_item">
  82. <img src="../../assets/login/login_email.webp" alt=""></img>
  83. <p>邮箱</p>
  84. </div>
  85. -->
  86. <!-- </div> -->
  87. <!-- </div> -->
  88. </div>
  89. </div>
  90. </div>
  91. </template>
  92. <script setup>
  93. import { ref, onMounted, computed, watch } from 'vue'
  94. // import particles from 'particles.js'
  95. import { login,getUserInfo} from '@/api/login.ts'
  96. import { ElMessage } from 'element-plus' //
  97. import { useRouter } from 'vue-router'
  98. import { encrypt } from "@/utils/jsencrypt";
  99. import passwordIcon from '@/assets/icon/password.svg'
  100. import lineCloseIcon from '@/assets/icon/line_close_icon.webp'
  101. const router = useRouter() // 获取路由实例
  102. // 响应式数据
  103. const userName = ref('')
  104. const passWord = ref('')
  105. const remeberPassWord = ref(false)
  106. const loadingLogin = ref(false)
  107. const showPass = ref(false)
  108. const isStudentLogin = ref(true)
  109. const userInfoForm = ref()
  110. // 粒子动画初始化
  111. const InitParticles = () => {
  112. const particlesConfig = {
  113. particles: {
  114. number: {
  115. value: 60,
  116. density: {
  117. enable: true,
  118. value_area: 800
  119. }
  120. },
  121. color: {
  122. value: '#ffffff'
  123. },
  124. shape: {
  125. type: ['circle'],
  126. stroke: {
  127. width: 0,
  128. color: '#000000'
  129. },
  130. polygon: {
  131. nb_sides: 5
  132. },
  133. image: {
  134. src: 'img/github.svg',
  135. width: 100,
  136. height: 100
  137. }
  138. },
  139. opacity: {
  140. value: 0.5,
  141. random: false,
  142. anim: {
  143. enable: false,
  144. speed: 1,
  145. opacity_min: 0.1,
  146. sync: false
  147. }
  148. },
  149. size: {
  150. value: 3,
  151. random: false,
  152. anim: {
  153. enable: true,
  154. speed: 40,
  155. size_min: 0.1,
  156. sync: false
  157. }
  158. },
  159. line_linked: {
  160. enable: true,
  161. distance: 150,
  162. color: '#ffffff',
  163. opacity: 0.4,
  164. width: 1
  165. },
  166. move: {
  167. enable: true,
  168. speed: 6,
  169. direction: 'none',
  170. random: false,
  171. straight: false,
  172. out_mode: 'out',
  173. bounce: false,
  174. attract: {
  175. enable: false,
  176. rotateX: 600,
  177. rotateY: 1200
  178. }
  179. }
  180. },
  181. interactivity: {
  182. detect_on: 'canvas',
  183. events: {
  184. onhover: {
  185. enable: true,
  186. mode: 'grab'
  187. },
  188. onclick: {
  189. enable: true,
  190. mode: 'push'
  191. },
  192. resize: true
  193. },
  194. modes: {
  195. grab: {
  196. distance: 140,
  197. line_linked: {
  198. opacity: 1
  199. }
  200. },
  201. bubble: {
  202. distance: 400,
  203. size: 40,
  204. duration: 2,
  205. opacity: 8,
  206. speed: 3
  207. },
  208. repulse: {
  209. distance: 200,
  210. duration: 0.4
  211. },
  212. push: {
  213. particles_nb: 4
  214. },
  215. remove: {
  216. particles_nb: 2
  217. }
  218. }
  219. },
  220. retina_detect: true
  221. }
  222. particlesJS('particles', particlesConfig, () => {
  223. console.log('粒子动画特效加载成功')
  224. })
  225. }
  226. onMounted(() => {
  227. // InitParticles()
  228. const storedUsername = localStorage.getItem('userName')
  229. const storedPassword = localStorage.getItem('passWord')
  230. const storedRememberMe = localStorage.getItem('rememberMe')
  231. if (storedRememberMe === 'true') {
  232. userName.value = storedUsername
  233. passWord.value = storedPassword
  234. remeberPassWord.value = true
  235. }
  236. })
  237. const HandleLoginChange = (val)=>{
  238. isStudentLogin.value = val
  239. }
  240. // 清空输入框
  241. const ClearInput = (event) => {
  242. userName.value = ''
  243. }
  244. const menuList = ref([])
  245. // 登录提交
  246. const SubmitLogin = async () => {
  247. if(!userName.value || !passWord.value) {
  248. return
  249. }
  250. if (remeberPassWord.value) {
  251. localStorage.setItem('userName', userName.value)
  252. localStorage.setItem('passWord', passWord.value)
  253. localStorage.setItem('rememberMe', 'true')
  254. } else {
  255. localStorage.removeItem('userName')
  256. localStorage.removeItem('passWord')
  257. localStorage.setItem('rememberMe', 'false')
  258. }
  259. const params = {
  260. username: userName.value.trim(),
  261. password: encrypt(passWord.value.trim()),
  262. deviceType:'PC',
  263. }
  264. loadingLogin.value = true
  265. router.push('/phoneLogin')
  266. /*
  267. let res = undefined
  268. try{
  269. res = await login(params)
  270. loadingLogin.value = false
  271. if (res.code === 200) {
  272. console.log("登录成功返回",res)
  273. localStorage.setItem('token', res.data.tokenValue)
  274. menuList.value = res.data.pcMenuVOS
  275. localStorage.setItem('menuList', JSON.stringify(res.data.pcMenuVOS))
  276. localStorage.setItem('permissions', JSON.stringify(res.data.permissions))
  277. // 登录成功后调用获取用户信息接口
  278. let userInfoRes = undefined
  279. userInfoRes = await getUserInfo(res.data.token)
  280. console.log("获取用户信息返回",userInfoRes)
  281. if (userInfoRes?.code === 200) {
  282. // 存储用户信息到 localStorage 或 Pinia
  283. localStorage.setItem('userInfo', JSON.stringify(userInfoRes.data))
  284. ElMessage.success('登录成功');
  285. //根据不同的角色跳转不同的页面
  286. // 管理员跳转
  287. if(userInfoRes.data?.roleCodes?.includes('SCHOOL_MANAGER')){
  288. router.push('/main')
  289. }else{
  290. router.push('/main/personalCenter')
  291. }
  292. }
  293. }
  294. }catch(err){
  295. loadingLogin.value = false
  296. console.error(err)
  297. }
  298. */
  299. }
  300. // 去往官网
  301. const GoWebsite = () => {
  302. window.open('https://www.k12100.com/website')
  303. }
  304. </script>
  305. <style lang="scss" scoped>
  306. @use "../../styles/login.scss" as *;
  307. .tab {
  308. display: flex;
  309. flex-direction: row;
  310. margin:0 0 10px;
  311. gap: 20px;
  312. font-weight: bold;
  313. line-height: 48px;
  314. span{
  315. padding:0 0 4px;
  316. &:hover{
  317. cursor: pointer;
  318. }
  319. }
  320. .selected{
  321. position: relative;
  322. color: #2e64fa;
  323. &::after{
  324. position: absolute;
  325. content: "";
  326. left: 0;
  327. right: 0;
  328. top: 70%;
  329. height: 2px;
  330. background-color: #2e64fa;
  331. }
  332. }
  333. }
  334. .login_info{
  335. .login_info_title{
  336. margin-bottom: 32px !important;
  337. }
  338. .input_tips{
  339. font-weight: 600;
  340. font-size: 14px;
  341. color: #333;
  342. margin-bottom: 26px;
  343. }
  344. }
  345. .login_info_input{
  346. // border:solid red 1px;
  347. .iconfont{
  348. color:#c0c4cc;
  349. }
  350. .el-form{
  351. .el-form-item{
  352. // border:solid red 1px !important;
  353. :deep(.el-form-item__content){
  354. .el-input{
  355. .el-input__wrapper{
  356. border: none;
  357. box-shadow: none;
  358. padding: 0;
  359. &::hover{
  360. border:none;
  361. box-shadow: none;
  362. }
  363. .el-input__prefix{
  364. position: absolute;
  365. left: 17px;
  366. }
  367. .el-input__suffix{
  368. position: absolute;
  369. right: 17px;
  370. }
  371. .el-input__inner{
  372. text-indent: 43px;
  373. border:solid #dcdfe6 1px;
  374. height: 100%;
  375. border-radius: 4px;
  376. &:hover{
  377. border-color: #c0c4cc;
  378. }
  379. &:focus{
  380. border-color: #2e64fa;
  381. }
  382. }
  383. }
  384. }
  385. }
  386. }
  387. }
  388. }
  389. </style>