login.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. <template>
  2. <view class="login-page">
  3. <!-- 顶部插画区 -->
  4. <view class="login-header">
  5. <image
  6. class="header-bg"
  7. src="/static/desk-img/1-2.png"
  8. mode="aspectFill"
  9. ></image>
  10. <view class="header-mask"></view>
  11. <view class="header-content">
  12. <view class="header-top">
  13. <!-- 国能logo -->
  14. <image
  15. class="logo"
  16. src="/static/desk-img/logo.png"
  17. mode="aspectFit"
  18. ></image>
  19. <!-- 乌兰logo -->
  20. <!-- <image src="/static/desk-img/logo-lblt.png" mode='aspectFit' class="zai-logo "></image> -->
  21. <!-- 默认logo -->
  22. <!-- <image
  23. src="/static/desk-img/1-1.png"
  24. mode="aspectFit"
  25. class="zai-logo"
  26. ></image> -->
  27. <!-- 大海则logo -->
  28. <!-- <image
  29. src="/static/desk-img/dhz-logo.png"
  30. mode="aspectFit"
  31. class="zai-logo"
  32. ></image> -->
  33. <u-icon
  34. name="setting-fill"
  35. color="#2979ff"
  36. size="22"
  37. @click="setIp"
  38. ></u-icon>
  39. </view>
  40. <view class="welcome-text">您好,欢迎使用</view>
  41. <view class="platform-name">“一通三防”智能管控平台</view>
  42. </view>
  43. </view>
  44. <!-- 登录表单 -->
  45. <view class="login-body" v-if="!ipShow">
  46. <view class="form-area">
  47. <view class="input-item">
  48. <u-icon name="account-fill" color="#2979ff" size="22"></u-icon>
  49. <input
  50. class="input-field"
  51. placeholder="账号"
  52. placeholder-class="input-placeholder"
  53. v-model="userName"
  54. />
  55. </view>
  56. <view class="input-item">
  57. <u-icon name="lock-fill" color="#2979ff" size="22"></u-icon>
  58. <input
  59. class="input-field"
  60. placeholder="密码"
  61. placeholder-class="input-placeholder"
  62. :password="!showPassword"
  63. v-model="password"
  64. />
  65. <u-icon
  66. :name="showPassword ? 'eye-fill' : 'eye-off'"
  67. color="#2979ff"
  68. size="22"
  69. @click="changePassword"
  70. ></u-icon>
  71. </view>
  72. <view class="sso-link" @click="changeloginType">切换单点登录</view>
  73. </view>
  74. <view class="footer-area">
  75. <button
  76. class="login-btn"
  77. :loading="loading"
  78. :disabled="loading"
  79. @tap="onLogin"
  80. >
  81. {{ loading ? "登录中..." : "登录" }}
  82. </button>
  83. <!-- #ifdef APP-PLUS -->
  84. <view class="version-text">当前版本:{{ version }}</view>
  85. <!-- #endif -->
  86. </view>
  87. </view>
  88. <!-- 登录加载弹窗 -->
  89. <view class="cu-load load-modal" v-if="loading">
  90. <image
  91. src="/static/desk-img/144.png"
  92. mode="aspectFit"
  93. class="round"
  94. ></image>
  95. <view class="gray-text">登录中...</view>
  96. </view>
  97. <!-- IP 配置 -->
  98. <view class="ip-panel" v-if="ipShow">
  99. <view class="IPSet">
  100. <span class="text-style">
  101. <u-button
  102. :plain="true"
  103. color="#18a5ff"
  104. size="small"
  105. :text="IPSet ? IPSet : '选择IP地址'"
  106. @tap="changeIP()"
  107. ></u-button>
  108. </span>
  109. <u-picker
  110. :show="ipShow1"
  111. :columns="IpConfig"
  112. @cancel="ipShow = false"
  113. @confirm="selectIpAddr"
  114. keyName="label"
  115. ></u-picker>
  116. </view>
  117. </view>
  118. </view>
  119. </template>
  120. <script>
  121. import { ACCESS_TOKEN, USER_NAME, USER_INFO } from "@/common/util/constants";
  122. import { mapActions } from "vuex";
  123. import configService from "@/common/service/config.service.js";
  124. import { AesEncryption, getLoginCipher } from "@/common/util/cipher.js";
  125. import api from "@/api/api";
  126. export default {
  127. data() {
  128. return {
  129. ipShow: false,
  130. ipShow1: false,
  131. shape: "", //round 圆形
  132. loading: false,
  133. userName: "",
  134. password: "",
  135. phoneNo: "",
  136. smsCode: "",
  137. showPassword: false, //是否显示明文
  138. smsCountDown: 0,
  139. smsCountInterval: null,
  140. toggleDelay: false,
  141. version: "",
  142. //第三方登录相关信息
  143. thirdType: "",
  144. thirdLoginInfo: "",
  145. thirdLoginState: false,
  146. bindingPhoneModal: false,
  147. thirdUserUuid: "",
  148. IPValue: "",
  149. PortValue: "",
  150. fullIPVal: "", //完整IP地址
  151. IPSet: "",
  152. IpConfig: [
  153. [
  154. {
  155. label: "大柳塔井",
  156. value: "http://10.248.135.10:9999",
  157. code: "dlt",
  158. },
  159. {
  160. label: "活鸡兔井",
  161. value: "http://10.248.135.121:9999",
  162. code: "hjt",
  163. },
  164. {
  165. label: "寸草塔二矿",
  166. value: "http://10.246.63.5:9999",
  167. code: "cctr",
  168. },
  169. {
  170. label: "乌兰木伦",
  171. value: "http://10.246.183.35:9999",
  172. code: "wlml",
  173. },
  174. {
  175. label: "哈拉沟煤矿",
  176. value: "http://10.248.223.12:9999",
  177. code: "hlg",
  178. },
  179. { label: "布尔台", value: "http://10.246.95.4:9999", code: "brt" },
  180. { label: "上湾", value: "http://10.246.167.205:9999", code: "sw" },
  181. { label: "锦界", value: "http://10.248.151.42:9999", code: "jj" },
  182. { label: "补连塔", value: "http://10.246.175.16:9999", code: "blt" },
  183. { label: "寸草塔", value: "http://10.246.23.171:9999", code: "cct" },
  184. { label: "柳塔", value: "http://10.246.87.121:9999", code: "lt" },
  185. { label: "石圪台", value: "http://10.246.191.13:9999", code: "sgt" },
  186. { label: "榆家梁", value: "http://10.248.143.211:9999", code: "yjl" },
  187. { label: "保德", value: "http://10.248.210.152:9999", code: "bd" },
  188. ],
  189. ],
  190. };
  191. },
  192. onLoad: function (option) {
  193. console.log("=======option.ticket======" + JSON.stringify(option.ticket));
  194. if (option.ticket) {
  195. this.loginCas(option.ticket);
  196. }
  197. // #ifdef APP-PLUS
  198. var that = this;
  199. plus.runtime.getProperty(plus.runtime.appid, function (wgtinfo) {
  200. that.version = wgtinfo.version;
  201. });
  202. // #endif
  203. },
  204. computed: {
  205. hasBaseUrl() {
  206. return configService.hasBaseUrl;
  207. },
  208. isSendSMSEnable() {
  209. return this.smsCountDown <= 0 && this.phoneNo.length > 4;
  210. },
  211. getSendBtnText() {
  212. if (this.smsCountDown > 0) {
  213. return this.smsCountDown + "秒后发送";
  214. } else {
  215. return "发送验证码";
  216. }
  217. },
  218. canSMSLogin() {
  219. return this.userName.length > 4 && this.smsCode.length > 4;
  220. },
  221. canPwdLogin() {
  222. return this.userName.length > 4 && this.password.length > 4;
  223. },
  224. },
  225. methods: {
  226. ...mapActions(["mLogin", "PhoneLogin", "ThirdLogin"]),
  227. // 判断是否在APP环境中
  228. isApp() {
  229. return typeof plus !== "undefined";
  230. },
  231. onLogin: function () {
  232. if (!this.userName || this.userName.length == 0) {
  233. this.$tip.toast("请填写用户名");
  234. return;
  235. }
  236. if (!this.password || this.password.length == 0) {
  237. this.$tip.toast("请填写密码");
  238. return;
  239. }
  240. let loginParams = {
  241. username: this.userName,
  242. password: this.password,
  243. clientId: uni.getStorageSync("push_cid"),
  244. };
  245. // 加密
  246. const loginCipher = getLoginCipher();
  247. const encryption = new AesEncryption({
  248. key: loginCipher.key,
  249. iv: loginCipher.iv,
  250. });
  251. loginParams.password = encryption.encryptByAES(loginParams.password);
  252. this.loading = true;
  253. this.mLogin(loginParams)
  254. .then((res) => {
  255. this.loading = false;
  256. if (res.data.success) {
  257. if (this.isApp()) {
  258. // console.log('当前是APP环境');
  259. this.saveClientId();
  260. } else {
  261. this.getPermissionList();
  262. }
  263. // #ifdef APP-PLUS
  264. // #endif
  265. // #ifndef APP-PLUS
  266. // #endif
  267. } else {
  268. this.$tip.alert(res.data.message);
  269. }
  270. })
  271. .catch((err) => {
  272. let msg = err.data.message || "请求出现错误,请稍后再试";
  273. this.loading = false;
  274. this.$tip.alert(msg);
  275. })
  276. .finally(() => {
  277. this.loading = false;
  278. });
  279. },
  280. loginCas(value) {
  281. if (!value) {
  282. return;
  283. }
  284. const serviceUrl = configService.apiUrl.replace(9999, 8092);
  285. api
  286. .validateCasLogin(
  287. "",
  288. "?ticket=" + value + "&service=" + encodeURIComponent(serviceUrl)
  289. )
  290. .then((response) => {
  291. const result = response.data && response.data.result;
  292. if (!result || !result.token || !result.userInfo) {
  293. this.$tip.error(
  294. (response.data && response.data.message) || "单点登录验证失败"
  295. );
  296. return;
  297. }
  298. const userInfo = result.userInfo;
  299. uni.setStorageSync(ACCESS_TOKEN, result.token);
  300. uni.setStorageSync(USER_INFO, userInfo);
  301. this.$store.commit("SET_TOKEN", result.token);
  302. this.$store.commit("SET_DICT", result.sysAllDictItems);
  303. this.$store.commit("SET_AVATAR", userInfo.avatar);
  304. this.$store.commit("SET_NAME", {
  305. username: userInfo.username,
  306. realname: userInfo.realname,
  307. });
  308. this.getPermissionList();
  309. })
  310. .catch((error) => {
  311. console.log("CAS login validation failed", error);
  312. const message =
  313. (error && error.data && error.data.message) ||
  314. (error && error.message) ||
  315. "单点登录验证失败,请检查服务器地址后重试";
  316. this.$tip.error(message);
  317. });
  318. },
  319. //获取权限菜单
  320. getPermissionList() {
  321. new Promise((resolve, reject) => {
  322. api
  323. .getPermission({})
  324. .then((response) => {
  325. console.log(response, "权限菜单----------------");
  326. if (response.statusCode == 200) {
  327. let data = response.data.result.menuApp;
  328. let dataBtn = response.data.result.appauth;
  329. uni.setStorageSync("menuPermission", data);
  330. uni.setStorageSync("btnPermission", dataBtn);
  331. this.$tip.success("登录成功!");
  332. uni.navigateTo({
  333. url: "/pages/index/index",
  334. });
  335. } else {
  336. reject(response);
  337. }
  338. })
  339. .catch((error) => {
  340. console.log("catch===>response", response);
  341. reject(error);
  342. });
  343. });
  344. },
  345. saveClientId() {
  346. this.getPermissionList();
  347. // var info = plus.push.getClientInfo();
  348. // var cid = info.clientid;
  349. // this.$http
  350. // .get("/sys/user/saveClientId", { params: { clientId: cid } })
  351. // .then((res) => {
  352. // console.log("res::saveClientId>", res);
  353. // //获取权限菜单
  354. // this.getPermissionList();
  355. // });
  356. },
  357. changePassword() {
  358. this.showPassword = !this.showPassword;
  359. },
  360. onSMSSend() {
  361. let smsParams = {};
  362. smsParams.mobile = this.phoneNo;
  363. smsParams.smsmode = "0";
  364. let checkPhone = new RegExp(/^[1]([3-9])[0-9]{9}$/);
  365. if (!smsParams.mobile || smsParams.mobile.length == 0) {
  366. this.$tip.toast("请输入手机号");
  367. return false;
  368. }
  369. if (!checkPhone.test(smsParams.mobile)) {
  370. this.$tip.toast("请输入正确的手机号");
  371. return false;
  372. }
  373. this.$http.post("/sys/sms", smsParams).then((res) => {
  374. if (res.data.success) {
  375. this.smsCountDown = 60;
  376. this.startSMSTimer();
  377. } else {
  378. this.smsCountDown = 0;
  379. this.$tip.toast(res.data.message);
  380. }
  381. });
  382. },
  383. startSMSTimer() {
  384. this.smsCountInterval = setInterval(() => {
  385. this.smsCountDown--;
  386. if (this.smsCountDown <= 0) {
  387. clearInterval(this.smsCountInterval);
  388. }
  389. }, 1000);
  390. },
  391. onSMSLogin() {
  392. let checkPhone = new RegExp(/^[1]([3-9])[0-9]{9}$/);
  393. if (!this.phoneNo || this.phoneNo.length == 0) {
  394. this.$tip.toast("请填写手机号");
  395. return;
  396. }
  397. if (!checkPhone.test(this.phoneNo)) {
  398. this.$tip.toast("请输入正确的手机号");
  399. return false;
  400. }
  401. if (!this.smsCode || this.smsCode.length == 0) {
  402. this.$tip.toast("请填短信验证码");
  403. return;
  404. }
  405. let loginParams = {
  406. mobile: this.phoneNo,
  407. captcha: this.smsCode,
  408. };
  409. this.PhoneLogin(loginParams)
  410. .then((res) => {
  411. console.log("res====》", res);
  412. if (res.data.success) {
  413. this.$tip.success("登录成功!");
  414. uni.navigateTo({
  415. url: "/pages/inedx/inedx",
  416. });
  417. } else {
  418. this.$tip.error(res.data.message);
  419. }
  420. })
  421. .catch((err) => {
  422. let msg =
  423. ((err.response || {}).data || {}).message ||
  424. err.data.message ||
  425. "请求出现错误,请稍后再试";
  426. this.$tip.error(msg);
  427. });
  428. },
  429. loginSuccess() {
  430. // 登陆成功,重定向到主页
  431. this.$Router.replace({ name: "index" });
  432. },
  433. requestFailed(err) {
  434. this.$message.warning("登录失败");
  435. },
  436. changeloginType() {
  437. console.log("changeloginType====");
  438. console.log(configService, "changeloginType====");
  439. var tourl = configService.apiUrl;
  440. tourl = tourl.replace(9999, 8092);
  441. // this.$tip.success("tourl="+tourl);
  442. var rastourl =
  443. "https://id.shendong.com.cn/default" + "/login?service=" + tourl;
  444. // rastourl ="http://182.92.126.35:8092/?ticket=234";
  445. console.log("===========" + rastourl);
  446. this.openBrowser(rastourl);
  447. // window.location.href='/pages/index/index?ticket=123'
  448. // this.$router.push({ path: '/pages/index/index?ticket=123',query:"2w354" })
  449. },
  450. openBrowser(url) {
  451. // 使用uni.navigateTo打开内置浏览器
  452. console.log("----url---------------" + url);
  453. // this.$tip.success("url="+url);
  454. uni.navigateTo({
  455. url: "/pages/webview/webview?url=" + encodeURIComponent(url),
  456. });
  457. },
  458. setIp() {
  459. console.log("点击成功");
  460. this.ipShow = !this.ipShow;
  461. },
  462. changeIP() {
  463. this.ipShow1 = true;
  464. },
  465. selectIpAddr(e) {
  466. this.ipShow1 = false;
  467. const fullURL = e.value[0].value;
  468. this.IPSet = e.value[0].label;
  469. const apiCode = e.value[0].code;
  470. configService.apiUrl = fullURL;
  471. uni.setStorageSync("apiUrl", configService.apiUrl);
  472. uni.setStorageSync("apiCode", apiCode);
  473. setTimeout(() => {
  474. uni.getStorageSync("apiUrl");
  475. }, 100);
  476. uni.navigateTo({ url: "/pages/login/login" });
  477. },
  478. },
  479. beforeDestroy() {
  480. if (this.smsCountInterval) {
  481. clearInterval(this.smsCountInterval);
  482. }
  483. },
  484. };
  485. </script>
  486. <style scoped>
  487. .login-page {
  488. min-height: 100vh;
  489. background: #ffffff;
  490. display: flex;
  491. flex-direction: column;
  492. position: relative;
  493. overflow: hidden;
  494. }
  495. /* ===== 顶部插画 ===== */
  496. .login-header {
  497. position: relative;
  498. width: 100%;
  499. height: 520rpx;
  500. flex-shrink: 0;
  501. }
  502. .header-bg {
  503. position: absolute;
  504. left: 0;
  505. top: 0;
  506. width: 100%;
  507. height: 100%;
  508. z-index: 0;
  509. }
  510. .header-mask {
  511. position: absolute;
  512. left: 0;
  513. bottom: 0;
  514. width: 100%;
  515. height: 160rpx;
  516. background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #ffffff);
  517. z-index: 1;
  518. }
  519. .header-content {
  520. position: relative;
  521. z-index: 2;
  522. padding: 88rpx 48rpx 0;
  523. box-sizing: border-box;
  524. }
  525. .header-top {
  526. display: flex;
  527. flex-direction: row;
  528. align-items: center;
  529. justify-content: space-between;
  530. margin-bottom: 36rpx;
  531. }
  532. .logo {
  533. width: 72rpx;
  534. height: 84rpx;
  535. }
  536. .welcome-text {
  537. font-size: 36rpx;
  538. color: #1a1a1a;
  539. font-weight: 500;
  540. line-height: 1.4;
  541. margin-bottom: 12rpx;
  542. }
  543. .platform-name {
  544. font-size: 40rpx;
  545. color: #111111;
  546. font-weight: 700;
  547. line-height: 1.4;
  548. letter-spacing: 1rpx;
  549. }
  550. /* ===== 表单区 ===== */
  551. .login-body {
  552. flex: 1;
  553. display: flex;
  554. flex-direction: column;
  555. justify-content: space-between;
  556. padding: 40rpx 48rpx 80rpx;
  557. box-sizing: border-box;
  558. background: #ffffff;
  559. }
  560. .form-area {
  561. width: 100%;
  562. }
  563. .input-item {
  564. display: flex;
  565. flex-direction: row;
  566. align-items: center;
  567. height: 96rpx;
  568. padding: 0 28rpx;
  569. margin-bottom: 28rpx;
  570. background: #eff3ff;
  571. border-radius: 16rpx;
  572. box-sizing: border-box;
  573. }
  574. .input-field {
  575. flex: 1;
  576. height: 96rpx;
  577. margin-left: 20rpx;
  578. font-size: 30rpx;
  579. color: #333333;
  580. }
  581. .input-placeholder {
  582. color: #9aa3b5;
  583. font-size: 30rpx;
  584. }
  585. .sso-link {
  586. margin-top: 8rpx;
  587. text-align: right;
  588. font-size: 26rpx;
  589. color: #2979ff;
  590. }
  591. /* ===== 底部登录 ===== */
  592. .footer-area {
  593. width: 100%;
  594. padding-bottom: env(safe-area-inset-bottom);
  595. }
  596. .login-btn {
  597. width: 100%;
  598. height: 96rpx;
  599. line-height: 96rpx;
  600. background: #007aff;
  601. color: #ffffff;
  602. font-size: 34rpx;
  603. font-weight: 600;
  604. border-radius: 48rpx;
  605. border: none;
  606. text-align: center;
  607. padding: 0;
  608. }
  609. .login-btn::after {
  610. border: none;
  611. }
  612. .login-btn[disabled] {
  613. opacity: 0.75;
  614. }
  615. .version-text {
  616. margin-top: 24rpx;
  617. text-align: center;
  618. font-size: 24rpx;
  619. color: #999999;
  620. }
  621. /* ===== IP 配置 ===== */
  622. .ip-panel {
  623. flex: 1;
  624. background: #ffffff;
  625. padding: 40rpx 48rpx;
  626. }
  627. .IPSet {
  628. display: flex;
  629. flex-direction: column;
  630. }
  631. .text-style {
  632. margin: 20px;
  633. }
  634. </style>