index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. <template>
  2. <div class="login-container" v-if="!isWechatEnv">
  3. <div class="login-form-main">
  4. <el-form
  5. ref="loginForm"
  6. :model="loginForm"
  7. :rules="loginRules"
  8. class="login-form"
  9. autocomplete="on"
  10. label-position="left"
  11. >
  12. <div class="title-container">
  13. <h3 class="title">
  14. 采销365
  15. <div style="font-size: 20px; margin-top: 5px">{{ ver }}</div>
  16. </h3>
  17. </div>
  18. <el-form-item prop="username">
  19. <span class="svg-container">
  20. <i class="el-icon-user" />
  21. </span>
  22. <el-input
  23. ref="username"
  24. v-model="loginForm.username"
  25. placeholder="手机号"
  26. name="username"
  27. type="text"
  28. tabindex="1"
  29. maxlength="11"
  30. autocomplete="on"
  31. />
  32. </el-form-item>
  33. <el-tooltip
  34. v-model="capsTooltip"
  35. content="Caps lock is On"
  36. placement="right"
  37. manual
  38. >
  39. <el-form-item prop="password">
  40. <span class="svg-container">
  41. <i class="el-icon-unlock" />
  42. </span>
  43. <el-input
  44. :key="passwordType"
  45. ref="password"
  46. v-model="loginForm.password"
  47. :type="passwordType"
  48. placeholder="密码"
  49. name="password"
  50. tabindex="2"
  51. autocomplete="on"
  52. maxlength="16"
  53. @keyup.native="checkCapslock"
  54. @blur="capsTooltip = false"
  55. @keyup.enter.native="handleLogin"
  56. />
  57. <span class="show-pwd" @click="showPwd">
  58. <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
  59. </span>
  60. </el-form-item>
  61. </el-tooltip>
  62. <el-form-item prop="code">
  63. <div style="display: flex">
  64. <span class="svg-container" style="margin-left: 10px">
  65. <i class="el-icon-key" />
  66. </span>
  67. <el-input
  68. v-model="loginForm.code"
  69. placeholder="验证码"
  70. style="line-height: 54px"
  71. />
  72. <div @click="refreshCode">
  73. <Identify
  74. content-height="52"
  75. :identify-code="identifyCode"
  76. style="cursor: pointer"
  77. />
  78. </div>
  79. </div>
  80. </el-form-item>
  81. <el-button
  82. :loading="loading"
  83. :disabled="loading"
  84. type="primary"
  85. style="width: 100%; margin-top: 5px"
  86. @click.native.prevent="handleLogin()"
  87. >登&nbsp;&nbsp;录</el-button>
  88. <!-- <div style="position: relative; padding: 12px 0 0 0"> -->
  89. <!-- <div class="tips" style="float: left">
  90. <el-popover
  91. placement="top"
  92. title="初始密码:"
  93. width="200"
  94. trigger="click"
  95. content="dingding123"
  96. >
  97. <i slot="reference" class="el-icon-info" />
  98. </el-popover>
  99. </div> -->
  100. <!-- <router-link to="/forget-password">
  101. <div class="tips" style="float: right">
  102. <span>忘记密码</span>
  103. </div>
  104. </router-link> -->
  105. <!-- </div> -->
  106. </el-form>
  107. </div>
  108. <div v-if="loginBeian !== ''" class="beian"> <div v-if="loginBeian !== ''" class="beian"> <span>{{ loginTitle }}</span>
  109. <a target="_blank" :href="loginBeianUrl">{{ loginBeian }}</a>
  110. <span />
  111. </div>
  112. </div>
  113. </div></template>
  114. <script>
  115. import { isnumber, isAlphanumeric, validAlphabets, isMobile } from '@/utils/validate'
  116. import asyncRequest from '@/apis/service/user'
  117. import Identify from '@/components/identify'
  118. import urlConfig from '@/apis/url-config'
  119. import resToken from '@/mixins/resToken'
  120. import config from '@/config'
  121. export default {
  122. name: 'Login',
  123. components: { Identify },
  124. mixins: [resToken],
  125. data() {
  126. const validateUsername = (rule, value, callback) => {
  127. if (value === '') {
  128. callback(new Error('手机号不能为空!'))
  129. } else {
  130. if (!isMobile(value)) {
  131. callback(new Error('请输入正确的手机号'))
  132. } else {
  133. callback()
  134. }
  135. }
  136. }
  137. const validatePassword = (rule, value, callback) => {
  138. if (value === '') {
  139. callback(new Error('密码不能为空!'))
  140. } else {
  141. if (!isAlphanumeric(value)) {
  142. callback(new Error('密码为6-18位数字字母组合!'))
  143. } else if (value.length < 6 || value.length > 18) {
  144. callback(new Error('密码为6-18位数字字母组合!'))
  145. } else if (isnumber(value)) {
  146. callback(new Error('密码不能为纯数字!'))
  147. } else if (validAlphabets(value)) {
  148. callback(new Error('密码不能为纯字母!'))
  149. } else {
  150. callback()
  151. }
  152. }
  153. }
  154. const validateCode = (rule, value, callback) => {
  155. if (value === '') {
  156. callback(new Error('验证码不能为空!'))
  157. } else {
  158. if (value !== this.identifyCode) {
  159. callback(new Error('请输入正确的验证码'))
  160. } else {
  161. callback()
  162. }
  163. }
  164. }
  165. return {
  166. ver: '',
  167. show: false,
  168. isWechatEnv:false,
  169. loginTitle: urlConfig.loginTitle,
  170. loginBeian: urlConfig.loginBeian,
  171. loginBeianUrl: urlConfig.loginBeianUrl,
  172. loginForm: {
  173. username: '',
  174. password: '',
  175. code: ''
  176. },
  177. loginRules: {
  178. username: [{ required: true, trigger: 'blur', validator: validateUsername }],
  179. password: [{ required: true, trigger: 'blur', validator: validatePassword }],
  180. code: [{ required: true, trigger: 'blur', validator: validateCode }]
  181. },
  182. identifyCode: '',
  183. identifyCodes: [
  184. '0',
  185. '1',
  186. '2',
  187. '3',
  188. '4',
  189. '5',
  190. '6',
  191. '7',
  192. '8',
  193. '9'
  194. ],
  195. passwordType: 'password',
  196. capsTooltip: false,
  197. loading: false,
  198. showDialog: false,
  199. redirect: undefined,
  200. otherQuery: {}
  201. }
  202. },
  203. watch: {
  204. $route: {
  205. handler: function(route) {
  206. const query = route.query
  207. if (query) {
  208. this.redirect = query.redirect
  209. this.otherQuery = this.getOtherQuery(query)
  210. }
  211. },
  212. immediate: true
  213. }
  214. },
  215. mounted() {
  216. this.refreshCode()
  217. this.bindEnterEvent()
  218. // this.getversion();
  219. if (this.loginForm.username === '') {
  220. this.$refs.username.focus()
  221. } else if (this.loginForm.password === '') {
  222. this.$refs.password.focus()
  223. }
  224. },
  225. beforeDestroy() {
  226. this.removeEnterEvent()
  227. },
  228. methods: {
  229. bindEnterEvent() {
  230. window.addEventListener('keydown', this.listener)
  231. },
  232. removeEnterEvent() {
  233. window.removeEventListener('keydown', this.listener)
  234. },
  235. listener(e) {
  236. e.keyCode === 13 && this.handleLogin()
  237. },
  238. async getversion() {
  239. const { code, data } = await asyncRequest.version({})
  240. if (code === 0) {
  241. const { version } = data
  242. this.ver = version
  243. } else {
  244. this.ver = ''
  245. }
  246. },
  247. setVisible(val) {
  248. this.show = val
  249. },
  250. handleClick() {
  251. this.show = true
  252. },
  253. handleSuccess() {
  254. this.show = false
  255. this.handleLogin()
  256. },
  257. checkCapslock(e) {
  258. const { key } = e
  259. this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z'
  260. },
  261. showPwd() {
  262. if (this.passwordType === 'password') {
  263. this.passwordType = ''
  264. } else {
  265. this.passwordType = 'password'
  266. }
  267. this.$nextTick(() => {
  268. this.$refs.password.focus()
  269. })
  270. },
  271. // 生成随机数
  272. randomNum(min, max) {
  273. max = max + 1
  274. return Math.floor(Math.random() * (max - min) + min)
  275. },
  276. // 更新验证码
  277. refreshCode() {
  278. this.identifyCode = ''
  279. this.makeCode(this.identifyCodes, 4)
  280. },
  281. makeCode(data, len) {
  282. for (let i = 0; i < len; i++) {
  283. this.identifyCode += this.identifyCodes[
  284. this.randomNum(0, this.identifyCodes.length - 1)
  285. ]
  286. }
  287. },
  288. handleLogin() {
  289. this.$refs.loginForm.validate((valid) => {
  290. if (valid) {
  291. this.loading = true
  292. this.$store
  293. .dispatch('user/login', this.loginForm)
  294. .then((res) => {
  295. console.log(res)
  296. if (res.code === 0) {
  297. this.getMenu()
  298. } else {
  299. this.$message.warning(res.message)
  300. this.loading = false
  301. }
  302. })
  303. .catch((err) => {
  304. console.log(err)
  305. this.loading = false
  306. })
  307. } else {
  308. console.log('error submit!!')
  309. return false
  310. }
  311. })
  312. },
  313. getMenu() {
  314. this.$store
  315. .dispatch('user/getMenuList', this)
  316. .then((res) => {
  317. window.vm.$router.push({
  318. path: '/welcome/dashboard/',
  319. query: this.otherQuery
  320. })
  321. this.loading = false
  322. })
  323. .catch((err) => {
  324. this.loading = false
  325. })
  326. },
  327. getOtherQuery(query) {
  328. return Object.keys(query).reduce((acc, cur) => {
  329. if (cur !== 'redirect') {
  330. acc[cur] = query[cur]
  331. }
  332. return acc
  333. }, {})
  334. }
  335. }
  336. }
  337. </script>
  338. <style lang="scss">
  339. /* 修复input 背景不协调 和光标变色 */
  340. /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
  341. $bg: #283443;
  342. $light_gray: #fff;
  343. $cursor: #fff;
  344. @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  345. .login-container .el-input input {
  346. color: $cursor;
  347. }
  348. }
  349. /* reset element-ui css */
  350. .login-container {
  351. .el-input {
  352. display: inline-block;
  353. height: 47px;
  354. width: 85%;
  355. input {
  356. background: transparent;
  357. border: 0px;
  358. -webkit-appearance: none;
  359. border-radius: 0px;
  360. padding: 12px 5px 12px 15px;
  361. color: #232323;
  362. height: 47px;
  363. // caret-color: $cursor;
  364. &:-webkit-autofill {
  365. // box-shadow: 0 0 0px 1000px $bg inset !important;
  366. // -webkit-text-fill-color: $cursor !important;
  367. }
  368. }
  369. }
  370. .el-form-item {
  371. border: 1px solid #e9e9e9;
  372. // background: rgba(0, 0, 0, 0.1);
  373. border-radius: 5px;
  374. color: #232323;
  375. }
  376. }
  377. </style>
  378. <style lang="scss" scoped>
  379. $bg: #2d3a4b;
  380. $dark_gray: #38c1e7;
  381. $light_gray: #f2f2f2;
  382. .login-container {
  383. top: 0;
  384. left: 0;
  385. width: 100%;
  386. height: 100%;
  387. transition: all 0.20s cubic-bezier(0.4, 0, 0.2, 1);
  388. background-image: url("~@/assets/design/bg-pc.jpg");
  389. zoom: 1;
  390. background-repeat: no-repeat;
  391. background-size: 100% 100%;
  392. // background-position: center 0;
  393. text-align: center;
  394. .login-form-main {
  395. height: 500px;
  396. position: absolute;
  397. right: 200px;
  398. top: 50%;
  399. transform: translateY(-50%);
  400. transition: all 0.20s cubic-bezier(0.4, 0, 0.2, 1);
  401. img {
  402. width: 400px;
  403. height: 350px;
  404. }
  405. .main-title {
  406. position: absolute;
  407. top: 0;
  408. left: 0;
  409. z-index: 2;
  410. left: 170px;
  411. top: 125px;
  412. text-align: left;
  413. color: #fff;
  414. h1 {
  415. padding: 0 0 13px 0;
  416. }
  417. h3 {
  418. font-size: 22px;
  419. }
  420. }
  421. .login-form {
  422. width: 400px;
  423. top: -40px;
  424. right: 100px;
  425. z-index: 3;
  426. max-width: 100%;
  427. padding: 50px 28px 35px 28px;
  428. margin: 0 auto;
  429. overflow: hidden;
  430. border-radius: 20px;
  431. .el-form-item{
  432. border: 1px solid transparent;
  433. border-bottom: 1px solid #e1e1e1;
  434. border-radius: 0px;
  435. }
  436. .el-button--primary {
  437. background-color: #087af5;
  438. border-color: #087af5;
  439. height: 46px;
  440. font-size: 16px;
  441. text-align: center;
  442. border-radius: 15px;
  443. }
  444. }
  445. }
  446. // min-height: 100%;
  447. // width: 100%;
  448. // background-color: $bg;
  449. // overflow: hidden;
  450. .beian {
  451. position: absolute;
  452. width: 100%;
  453. bottom: 30px;
  454. color: #343434;
  455. font-size: 12px;
  456. left: 50%;
  457. transform: translateX(-50%);
  458. span {
  459. padding: 0 10px;
  460. }
  461. a {
  462. display: inline-block;
  463. color: #343434;
  464. vertical-align: top;
  465. font-size: 12px;
  466. &:hover {
  467. text-decoration: underline;
  468. text-decoration-color: #343434;
  469. }
  470. }
  471. }
  472. .tips {
  473. font-size: 14px;
  474. color: #04a2ce;
  475. margin-bottom: 10px;
  476. span {
  477. &:first-of-type {
  478. margin-right: 8px;
  479. }
  480. }
  481. i {
  482. font-size: 20px;
  483. margin: 0 0 0 7px;
  484. }
  485. }
  486. .puzzle-box {
  487. position: absolute;
  488. top: 200px;
  489. }
  490. .svg-container {
  491. padding: 6px 5px 6px 6px;
  492. color: #38c1e7;
  493. vertical-align: middle;
  494. width: 30px;
  495. display: inline-block;
  496. }
  497. .title-container {
  498. position: relative;
  499. .title {
  500. font-size: 26px;
  501. color: #087af5;
  502. margin: 0px auto 30px auto;
  503. text-align: center;
  504. font-weight: bold;
  505. span {
  506. display: inline-block;
  507. font-size: 18px;
  508. vertical-align: top;
  509. padding: 10px 0 0 4px;
  510. }
  511. }
  512. }
  513. .show-pwd {
  514. position: absolute;
  515. right: 10px;
  516. top: 7px;
  517. font-size: 16px;
  518. color: $dark_gray;
  519. cursor: pointer;
  520. user-select: none;
  521. }
  522. .thirdparty-button {
  523. position: absolute;
  524. right: 0;
  525. bottom: 6px;
  526. }
  527. @media only screen and (max-width: 470px) {
  528. .thirdparty-button {
  529. display: none;
  530. }
  531. }
  532. }
  533. .s-canvas {
  534. margin: 0px;
  535. height: 38px;
  536. }
  537. .el-icon-key,.el-icon-user,.el-icon-unlock{
  538. color:#087af5 !important;
  539. font-weight: 700;
  540. }
  541. @media screen and (max-width: 1800px) {
  542. .login-container{
  543. .login-form-main {
  544. right: 100px;
  545. }
  546. }
  547. }
  548. @media screen and (max-width: 1200px) {
  549. .login-container{
  550. .login-form-main {
  551. right: 50px;
  552. }
  553. }
  554. }
  555. @media screen and (max-width: 1024px) {
  556. .login-container{
  557. background-image: url("~@/assets/design/bg-pad.jpg");
  558. .login-form-main {
  559. right: 50px;
  560. width: 300px;
  561. }
  562. }
  563. }
  564. @media screen and (max-width: 992px) {
  565. .login-container{
  566. background-image: url("~@/assets/design/bg-pad.jpg");
  567. .login-form-main {
  568. right: 20px;
  569. width: 360px;
  570. }
  571. }
  572. }
  573. @media screen and (max-width: 840px) {
  574. .login-container{
  575. background-image: url("~@/assets/design/bg-pad.jpg");
  576. .login-form-main {
  577. right: 5px;
  578. }
  579. }
  580. }
  581. @media screen and (max-width: 768px) {
  582. .login-container{
  583. background-image: url("~@/assets/design/bg-phone.jpg");
  584. .login-form-main {
  585. right: 20px;
  586. width: 95%;
  587. background: #fff;
  588. left: 50%;
  589. transform: translate(-50%,-50%);
  590. border-radius: 20px;
  591. height: auto;
  592. }
  593. }
  594. .beian{
  595. position: fixed;
  596. left: 50%;
  597. transform: translateX(-50%);
  598. padding: 0px !important;
  599. a{
  600. color: #fff !important;
  601. }
  602. }
  603. }
  604. </style>