index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. <template>
  2. <div
  3. :class="[
  4. 'login-wrapper',
  5. ['', 'login-form-right', 'login-form-left'][direction]
  6. ]"
  7. >
  8. <el-form
  9. ref="form"
  10. size="large"
  11. :model="form"
  12. :rules="rules"
  13. class="login-form ele-bg-white"
  14. @keyup.enter.native="submit"
  15. >
  16. <h4>{{ $t('login.title') }}</h4>
  17. <el-form-item prop="loginName">
  18. <el-input
  19. clearable
  20. v-model="form.loginName"
  21. prefix-icon="el-icon-user"
  22. placeholder="请输入登录账号"
  23. />
  24. </el-form-item>
  25. <el-form-item prop="loginPwd">
  26. <el-input
  27. show-password
  28. v-model="form.loginPwd"
  29. prefix-icon="el-icon-lock"
  30. placeholder="请输入登录密码"
  31. />
  32. </el-form-item>
  33. <el-form-item prop="captcha">
  34. <div class="login-input-group">
  35. <el-input
  36. clearable
  37. v-model="form.captcha"
  38. prefix-icon="el-icon-_vercode"
  39. :placeholder="$t('login.code')"
  40. />
  41. <img
  42. alt=""
  43. :src="captcha"
  44. class="login-captcha"
  45. @click="changeCaptcha"
  46. />
  47. </div>
  48. </el-form-item>
  49. <div class="el-form-item">
  50. <el-checkbox v-model="form.remember">
  51. {{ $t('login.remember') }}
  52. </el-checkbox>
  53. <el-link
  54. type="primary"
  55. :underline="false"
  56. class="ele-pull-right"
  57. @click="$router.push('/forget')"
  58. >
  59. 忘记密码
  60. </el-link>
  61. </div>
  62. <div class="el-form-item">
  63. <el-button
  64. size="large"
  65. type="primary"
  66. class="login-btn"
  67. :loading="loading"
  68. @click="submit"
  69. >
  70. {{ loading ? $t('login.loading') : $t('login.login') }}
  71. </el-button>
  72. </div>
  73. <div class="ele-text-center" style="margin-bottom: 10px">
  74. <!-- <i class="login-oauth-icon el-icon-_qq" style="background: #3492ed"></i>
  75. <i
  76. class="login-oauth-icon el-icon-_wechat"
  77. style="background: #4daf29"
  78. ></i>
  79. <i
  80. class="login-oauth-icon el-icon-_weibo"
  81. style="background: #cf1900"
  82. ></i> -->
  83. </div>
  84. </el-form>
  85. <div class="login-copyright">
  86. <!-- copyright © 2022 eleadmin.com all rights reserved. -->
  87. </div>
  88. <!-- 多语言切换 -->
  89. <div style="position: absolute; right: 30px; top: 20px">
  90. <i18n-icon
  91. :icon-style="{ fontSize: '22px', color: '#fff', cursor: 'pointer' }"
  92. />
  93. </div>
  94. <!-- 实际项目去掉这段 -->
  95. <!-- <div
  96. class="hidden-xs-only"
  97. style="position: absolute; right: 30px; bottom: 20px; z-index: 9"
  98. >
  99. <el-radio-group v-model="direction" size="mini">
  100. <el-radio-button label="2">居左</el-radio-button>
  101. <el-radio-button label="0">居中</el-radio-button>
  102. <el-radio-button label="1">居右</el-radio-button>
  103. </el-radio-group>
  104. </div> -->
  105. <el-dialog
  106. title="用户信息"
  107. :visible.sync="isInfo"
  108. v-if="isInfo"
  109. append-to-body
  110. width="30%"
  111. center
  112. :close-on-click-modal="false"
  113. @close="closeInfo"
  114. >
  115. <el-form :model="infoForm" label-position="right" label-width="100px">
  116. <el-form-item prop="factory" label="所属工厂">
  117. <el-input
  118. v-model="infoForm.factoryName"
  119. disabled
  120. placeholder="所属工厂"
  121. style="width: 240px"
  122. />
  123. </el-form-item>
  124. <el-form-item prop="team" label="班组">
  125. <el-select
  126. style="width: 240px"
  127. clearable
  128. v-model="infoForm.teamId"
  129. filterable
  130. placeholder="请选择班组"
  131. @change="changeTeam(infoForm.teamId)"
  132. >
  133. <el-option
  134. v-for="item in teamList"
  135. :label="item.teamName"
  136. :value="item.teamId"
  137. :key="item.teamId"
  138. ></el-option>
  139. </el-select>
  140. </el-form-item>
  141. <el-form-item prop="workCenter" label="工作中心">
  142. <el-select
  143. style="width: 240px"
  144. clearable
  145. v-model="infoForm.workCenterId"
  146. filterable
  147. placeholder="请选择工作中心"
  148. @change="changeWorlCenter(infoForm.workCenterId)"
  149. >
  150. <el-option
  151. v-for="item in workCenterList"
  152. :label="item.centerName"
  153. :value="item.centerId"
  154. :key="item.centerId"
  155. ></el-option>
  156. </el-select>
  157. <!-- <el-input
  158. v-model="infoForm.workCenter"
  159. disabled
  160. placeholder="所属工作中心"
  161. style="width: 240px"
  162. /> -->
  163. </el-form-item>
  164. <el-form-item prop="desk" label="工位">
  165. <!-- <el-input
  166. v-model="infoForm.desk"
  167. disabled
  168. placeholder="工位"
  169. style="width: 240px"
  170. /> -->
  171. <el-select
  172. style="width: 240px"
  173. clearable
  174. v-model="infoForm.workStationId"
  175. filterable
  176. placeholder="请选择工位"
  177. >
  178. <el-option
  179. v-for="item in workStationList"
  180. :label="item.workStationName"
  181. :value="item.workStationId"
  182. :key="item.workStationId"
  183. ></el-option>
  184. </el-select>
  185. </el-form-item>
  186. <el-form-item prop="device" label="设备">
  187. <!-- <el-input
  188. v-model="infoForm.device"
  189. disabled
  190. placeholder="设备"
  191. style="width: 240px"
  192. /> -->
  193. <el-select
  194. style="width: 240px"
  195. clearable
  196. v-model="infoForm.deviceId"
  197. filterable
  198. placeholder="请选择设备"
  199. >
  200. <el-option
  201. v-for="item in deviceList"
  202. :label="item.deviceName"
  203. :value="item.deviceId"
  204. :key="item.deviceId"
  205. ></el-option>
  206. </el-select>
  207. </el-form-item>
  208. </el-form>
  209. <div slot="footer" class="dialog-footer">
  210. <el-button @click="isInfo = false">取 消</el-button>
  211. <el-button type="primary" @click="infoClick">确 定</el-button>
  212. </div>
  213. </el-dialog>
  214. </div>
  215. </template>
  216. <script>
  217. import I18nIcon from '@/layout/components/i18n-icon.vue';
  218. import { getToken } from '@/utils/token-util';
  219. import { login, getCaptcha, getUserInfo, getFactoryarea } from '@/api/login';
  220. import xyy from '@/assets/xyy.jpg';
  221. import { getPathAddress } from '@/api/system/file';
  222. import { setCurrentUser } from '@/utils/token-util';
  223. import { factoryareaId } from '@/api/system/user';
  224. export default {
  225. // eslint-disable-next-line vue/multi-word-component-names
  226. name: 'Login',
  227. components: { I18nIcon },
  228. data() {
  229. return {
  230. // 登录框方向, 0居中, 1居右, 2居左
  231. xyy,
  232. direction: 1,
  233. // 加载状态
  234. loading: false,
  235. // 表单数据
  236. form: {
  237. loginName: localStorage.getItem('accountInfo')
  238. ? JSON.parse(localStorage.getItem('accountInfo')).loginName
  239. : '',
  240. loginPwd: localStorage.getItem('accountInfo')
  241. ? JSON.parse(localStorage.getItem('accountInfo')).loginPwd
  242. : '',
  243. remember: localStorage.getItem('accountInfo')
  244. ? JSON.parse(localStorage.getItem('accountInfo')).remember
  245. : false,
  246. captcha: '',
  247. uuid: '',
  248. factory: '',
  249. device: '',
  250. team: '',
  251. workCenter: '',
  252. desk: ''
  253. },
  254. infoForm: {
  255. factoryId: '',
  256. workCenterId: '',
  257. teamId: '',
  258. workStationId: '',
  259. deviceId: '',
  260. factoryName: ''
  261. },
  262. // 验证码base64数据
  263. captcha: '',
  264. // 验证码内容, 实际项目去掉
  265. text: '',
  266. isInfo: false,
  267. factoryList: [],
  268. workCenterList: [],
  269. teamList: [],
  270. deviceList: [],
  271. workStationList: [],
  272. userData: null
  273. };
  274. },
  275. computed: {
  276. // 表单验证规则
  277. rules() {
  278. return {
  279. loginName: [
  280. {
  281. required: true,
  282. message: this.$t('请输入登录账号'),
  283. type: 'string',
  284. trigger: 'blur'
  285. }
  286. ],
  287. loginPwd: [
  288. {
  289. required: true,
  290. message: this.$t('请输入登录密码'),
  291. type: 'string',
  292. trigger: 'blur'
  293. }
  294. ],
  295. captcha: [
  296. {
  297. required: true,
  298. message: '验证码不能为空',
  299. type: 'string',
  300. trigger: 'blur'
  301. }
  302. ]
  303. };
  304. }
  305. },
  306. created() {
  307. this.changeCaptcha();
  308. if (getToken()) {
  309. this.goHome();
  310. } else {
  311. // 重置菜单权限
  312. this.$store.commit('user/setMenus', null);
  313. }
  314. },
  315. methods: {
  316. /* 提交 */
  317. submit() {
  318. this.$refs.form.validate((valid) => {
  319. if (!valid) {
  320. return false;
  321. }
  322. this.loading = true;
  323. login(this.form)
  324. .then(async (res) => {
  325. localStorage.setItem('userId', res.data.userId);
  326. // 用户信息
  327. if (res.data?.loginChangeGroupVOList.length > 0) {
  328. setCurrentUser(
  329. {
  330. currentGroupId: res.data.loginChangeGroupVOList[0].groupId,
  331. currentRoleId:
  332. res.data.loginChangeGroupVOList[0]
  333. .loginChangeRoleVOList[0].roleId
  334. },
  335. this.form.remember
  336. );
  337. }
  338. const filePath = await getPathAddress();
  339. res.data.avatarAddress =
  340. res.data.avatar && res.data.avatar.length
  341. ? filePath + res.data.avatar[0].storePath
  342. : xyy;
  343. if (res.data.factoryId) {
  344. let factoryareaData = await factoryareaId(res.data.factoryId);
  345. res.data['factoryName'] = factoryareaData.name;
  346. }
  347. this.$store.commit('user/setUserInfo', res.data);
  348. this.loading = false;
  349. this.$message.success(res.message);
  350. if (this.form.remember) {
  351. localStorage.setItem('accountInfo', JSON.stringify(this.form));
  352. } else {
  353. localStorage.removeItem('accountInfo');
  354. }
  355. await this.$store.dispatch('user/getCurrentUserAuthorityDept');
  356. await this.$store.dispatch('paramsSetData/setParamsDataInfo');
  357. this.goHome();
  358. })
  359. .catch((e) => {
  360. this.changeCaptcha();
  361. this.loading = false;
  362. // this.$message.error(e.message);
  363. });
  364. });
  365. },
  366. /* 跳转到首页 */
  367. goHome() {
  368. localStorage.setItem('singleUserInfo', '1');
  369. if (this.$store.state.user.info.teamId) {
  370. this.getFactoryareaList();
  371. this.getUserAllInfo();
  372. this.isInfo = true;
  373. } else {
  374. this.$message.warning('请先给该员工配置班组!!');
  375. }
  376. // this.getFactoryList()
  377. // this.$router.push(this.$route?.query?.from ?? '/').catch(() => {});
  378. },
  379. async getFactoryareaList() {
  380. await getFactoryarea({
  381. type: 1,
  382. size: 9999
  383. }).then((res) => {
  384. this.factoryList = res.list;
  385. });
  386. },
  387. async getUserAllInfo() {
  388. this.infoForm.factoryId = '';
  389. this.infoForm.workCenterId = '';
  390. this.infoForm.teamId = '';
  391. this.infoForm.workStationId = '';
  392. this.infoForm.deviceId = '';
  393. this.infoForm.factoryName = '';
  394. await getUserInfo(this.$store.state.user.info.userId).then((res) => {
  395. // this.infoForm.factoryName = res.factoryName;
  396. // if (res.factoryName) {
  397. // this.infoForm.factoryName = res.factoryName;
  398. // } else {
  399. const data = this.factoryList.find((it) => it.id == res.factoryId);
  400. // }
  401. this.infoForm.factoryId = res.factoryId;
  402. this.infoForm.factoryName = res.factoryName;
  403. this.teamList = res.teamList;
  404. this.userData = res;
  405. });
  406. },
  407. changeWorlCenter(centerId) {
  408. this.infoForm.workCenterId = centerId;
  409. this.infoForm.workStationId = '';
  410. const workCenterData = this.workCenterList.find(
  411. (item) => item.centerId == centerId
  412. );
  413. if (workCenterData) {
  414. if (this.userData.workStationList.length != 0) {
  415. this.workStationList = this.userData.workStationList.filter(
  416. (item) => item.centerId == centerId
  417. );
  418. }
  419. }
  420. },
  421. changeTeam(teamId) {
  422. this.infoForm.teamId = teamId;
  423. this.infoForm.deviceId = '';
  424. this.infoForm.workCenterId = '';
  425. console.log(this.userData, teamId, '111');
  426. // const teamData = this.teamList.find((item) => item.teamId == teamId);
  427. this.workCenterList = this.userData.centerList.filter(
  428. (it) => it.teamId == teamId
  429. );
  430. if (this.userData.deviceList.length != 0) {
  431. this.deviceList = this.userData.deviceList.filter(
  432. (it) => it.teamId == teamId
  433. );
  434. }
  435. },
  436. infoClick() {
  437. if (!this.infoForm.workCenterId) {
  438. return this.$message.warning('请选择工作中心');
  439. }
  440. if (!this.infoForm.teamId) {
  441. return this.$message.warning('请选择班组');
  442. }
  443. this.isInfo = false;
  444. // console.log(this.infoForm, 'this.infoForm');
  445. // this.$store.commit('user/setAllUserInfo', this.infoForm);
  446. localStorage.setItem('chooseUserInfo', JSON.stringify(this.infoForm));
  447. // console.log(this.$store.state.user, 'this.$store.state.user');
  448. this.$router.push(this.$route?.query?.from ?? '/').catch(() => {});
  449. },
  450. closeInfo() {
  451. this.isInfo = false;
  452. },
  453. /* 更换图形验证码 */
  454. changeCaptcha() {
  455. this.form.uuid = this.generateUUID();
  456. // 这里演示的验证码是后端返回base64格式的形式, 如果后端地址直接是图片请参考忘记密码页面
  457. getCaptcha({ uuid: this.form.uuid })
  458. .then((data) => {
  459. this.captcha = URL.createObjectURL(data.data);
  460. this.$refs?.form?.clearValidate();
  461. })
  462. .catch((e) => {
  463. // this.$message.error(e.message);
  464. });
  465. },
  466. generateUUID() {
  467. var d = new Date().getTime(); //Timestamp
  468. var d2 =
  469. (performance && performance.now && performance.now() * 1000) || 0; //Time in microseconds since page-load or 0 if unsupported
  470. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
  471. /[xy]/g,
  472. function (c) {
  473. var r = Math.random() * 16; //random number between 0 and 16
  474. if (d > 0) {
  475. //Use timestamp until depleted
  476. r = (d + r) % 16 | 0;
  477. d = Math.floor(d / 16);
  478. } else {
  479. //Use microseconds since page-load if supported
  480. r = (d2 + r) % 16 | 0;
  481. d2 = Math.floor(d2 / 16);
  482. }
  483. return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
  484. }
  485. );
  486. }
  487. }
  488. };
  489. </script>
  490. <style lang="scss" scoped>
  491. /* 背景 */
  492. .login-wrapper {
  493. padding: 50px 20px;
  494. position: relative;
  495. box-sizing: border-box;
  496. background-image: url('@/assets/bg-login.jpg');
  497. background-repeat: no-repeat;
  498. background-size: cover;
  499. min-height: 100vh;
  500. &:before {
  501. content: '';
  502. background-color: rgba(0, 0, 0, 0.2);
  503. position: absolute;
  504. top: 0;
  505. left: 0;
  506. right: 0;
  507. bottom: 0;
  508. }
  509. }
  510. /* 卡片 */
  511. .login-form {
  512. margin: 0 auto;
  513. width: 360px;
  514. max-width: 100%;
  515. padding: 25px 30px;
  516. position: relative;
  517. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
  518. box-sizing: border-box;
  519. border-radius: 4px;
  520. z-index: 2;
  521. h4 {
  522. text-align: center;
  523. margin: 0 0 25px 0;
  524. }
  525. & > .el-form-item {
  526. margin-bottom: 25px;
  527. }
  528. }
  529. .login-form-right .login-form {
  530. margin: 0 15% 0 auto;
  531. }
  532. .login-form-left .login-form {
  533. margin: 0 auto 0 15%;
  534. }
  535. /* 验证码 */
  536. .login-input-group {
  537. display: flex;
  538. align-items: center;
  539. :deep(.el-input) {
  540. flex: 1;
  541. }
  542. }
  543. .login-captcha {
  544. height: 38px;
  545. width: 102px;
  546. margin-left: 10px;
  547. border-radius: 4px;
  548. border: 1px solid #dcdfe6;
  549. text-align: center;
  550. cursor: pointer;
  551. &:hover {
  552. opacity: 0.75;
  553. }
  554. }
  555. .login-btn {
  556. display: block;
  557. width: 100%;
  558. }
  559. /* 第三方登录图标 */
  560. .login-oauth-icon {
  561. color: #fff;
  562. padding: 5px;
  563. margin: 0 10px;
  564. font-size: 18px;
  565. border-radius: 50%;
  566. cursor: pointer;
  567. }
  568. /* 底部版权 */
  569. .login-copyright {
  570. color: #eee;
  571. padding-top: 20px;
  572. text-align: center;
  573. position: relative;
  574. z-index: 1;
  575. }
  576. /* 响应式 */
  577. @media screen and (min-height: 550px) {
  578. .login-form {
  579. position: absolute;
  580. top: 50%;
  581. left: 50%;
  582. transform: translateX(-50%);
  583. margin-top: -220px;
  584. }
  585. .login-form-right .login-form,
  586. .login-form-left .login-form {
  587. left: auto;
  588. right: 15%;
  589. transform: translateX(0);
  590. margin: -220px auto auto auto;
  591. }
  592. .login-form-left .login-form {
  593. right: auto;
  594. left: 15%;
  595. }
  596. .login-copyright {
  597. position: absolute;
  598. bottom: 20px;
  599. right: 0;
  600. left: 0;
  601. }
  602. }
  603. @media screen and (max-width: 768px) {
  604. .login-form-right .login-form,
  605. .login-form-left .login-form {
  606. left: 50%;
  607. right: auto;
  608. transform: translateX(-50%);
  609. margin-right: auto;
  610. }
  611. }
  612. </style>