login.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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/logo.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. // 登录页禁用系统返回,避免回到系统内部页面(真正退出请用退出登录)
  193. onBackPress() {
  194. return true;
  195. },
  196. onLoad: function (option) {
  197. console.log("=======option.ticket======" + JSON.stringify(option.ticket));
  198. if (option.ticket) {
  199. this.loginCas(option.ticket);
  200. }
  201. // 回填上次选择的服务器地址,避免看起来像是要重新选择 IP
  202. const savedCode = uni.getStorageSync("apiCode");
  203. const savedUrl = uni.getStorageSync("apiUrl");
  204. if (savedCode || savedUrl) {
  205. const ipList = (this.IpConfig && this.IpConfig[0]) || [];
  206. const matched = ipList.filter((item) => item.code === savedCode)[0];
  207. this.IPSet = matched ? matched.label : savedUrl || "";
  208. }
  209. // #ifdef APP-PLUS
  210. var that = this;
  211. plus.runtime.getProperty(plus.runtime.appid, function (wgtinfo) {
  212. that.version = wgtinfo.version;
  213. });
  214. // #endif
  215. },
  216. computed: {
  217. hasBaseUrl() {
  218. return configService.hasBaseUrl;
  219. },
  220. isSendSMSEnable() {
  221. return this.smsCountDown <= 0 && this.phoneNo.length > 4;
  222. },
  223. getSendBtnText() {
  224. if (this.smsCountDown > 0) {
  225. return this.smsCountDown + "秒后发送";
  226. } else {
  227. return "发送验证码";
  228. }
  229. },
  230. canSMSLogin() {
  231. return this.userName.length > 4 && this.smsCode.length > 4;
  232. },
  233. canPwdLogin() {
  234. return this.userName.length > 4 && this.password.length > 4;
  235. },
  236. },
  237. methods: {
  238. ...mapActions(["mLogin", "PhoneLogin", "ThirdLogin"]),
  239. // 判断是否在APP环境中
  240. isApp() {
  241. return typeof plus !== "undefined";
  242. },
  243. onLogin: function () {
  244. if (!this.userName || this.userName.length == 0) {
  245. this.$tip.toast("请填写用户名");
  246. return;
  247. }
  248. if (!this.password || this.password.length == 0) {
  249. this.$tip.toast("请填写密码");
  250. return;
  251. }
  252. let loginParams = {
  253. username: this.userName,
  254. password: this.password,
  255. clientId: uni.getStorageSync("push_cid"),
  256. };
  257. // 加密
  258. const loginCipher = getLoginCipher();
  259. const encryption = new AesEncryption({
  260. key: loginCipher.key,
  261. iv: loginCipher.iv,
  262. });
  263. loginParams.password = encryption.encryptByAES(loginParams.password);
  264. this.loading = true;
  265. this.mLogin(loginParams)
  266. .then((res) => {
  267. this.loading = false;
  268. if (res.data.success) {
  269. if (this.isApp()) {
  270. // console.log('当前是APP环境');
  271. this.saveClientId();
  272. } else {
  273. this.getPermissionList();
  274. }
  275. // #ifdef APP-PLUS
  276. // #endif
  277. // #ifndef APP-PLUS
  278. // #endif
  279. console.log(res.data);
  280. } else {
  281. this.$tip.alert(res.data.message);
  282. }
  283. })
  284. .catch((err) => {
  285. let msg = err.data.message || "请求出现错误,请稍后再试";
  286. this.loading = false;
  287. this.$tip.alert(msg);
  288. })
  289. .finally(() => {
  290. this.loading = false;
  291. });
  292. },
  293. loginCas(value) {
  294. if (!value) {
  295. return;
  296. }
  297. const serviceUrl = configService.apiUrl.replace(9999, 8092);
  298. api
  299. .validateCasLogin(
  300. "",
  301. "?ticket=" + value + "&service=" + encodeURIComponent(serviceUrl)
  302. )
  303. .then((response) => {
  304. const result = response.data && response.data.result;
  305. if (!result || !result.token || !result.userInfo) {
  306. this.$tip.error(
  307. (response.data && response.data.message) || "单点登录验证失败"
  308. );
  309. return;
  310. }
  311. const userInfo = result.userInfo;
  312. uni.setStorageSync(ACCESS_TOKEN, result.token);
  313. uni.setStorageSync(USER_INFO, userInfo);
  314. this.$store.commit("SET_TOKEN", result.token);
  315. this.$store.commit("SET_DICT", result.sysAllDictItems);
  316. this.$store.commit("SET_AVATAR", userInfo.avatar);
  317. this.$store.commit("SET_NAME", {
  318. username: userInfo.username,
  319. realname: userInfo.realname,
  320. });
  321. this.getPermissionList();
  322. })
  323. .catch((error) => {
  324. console.log("CAS login validation failed", error);
  325. const message =
  326. (error && error.data && error.data.message) ||
  327. (error && error.message) ||
  328. "单点登录验证失败,请检查服务器地址后重试";
  329. this.$tip.error(message);
  330. });
  331. },
  332. //获取权限菜单
  333. getPermissionList() {
  334. new Promise((resolve, reject) => {
  335. api
  336. .getPermission({})
  337. .then((response) => {
  338. console.log(response, "权限菜单----------------");
  339. if (response.statusCode == 200) {
  340. let data = response.data.result.menuApp;
  341. let dataBtn = response.data.result.appauth;
  342. uni.setStorageSync("menuPermission", data);
  343. uni.setStorageSync("btnPermission", dataBtn);
  344. this.$tip.success("登录成功!");
  345. // 登录成功后清空页面栈,防止从系统内页面返回又回到登录页
  346. uni.reLaunch({
  347. url: "/pages/index/index",
  348. });
  349. } else {
  350. reject(response);
  351. }
  352. })
  353. .catch((error) => {
  354. console.log("catch===>response", response);
  355. reject(error);
  356. });
  357. });
  358. },
  359. saveClientId() {
  360. this.getPermissionList();
  361. // var info = plus.push.getClientInfo();
  362. // var cid = info.clientid;
  363. // this.$http
  364. // .get("/sys/user/saveClientId", { params: { clientId: cid } })
  365. // .then((res) => {
  366. // console.log("res::saveClientId>", res);
  367. // //获取权限菜单
  368. // this.getPermissionList();
  369. // });
  370. },
  371. changePassword() {
  372. this.showPassword = !this.showPassword;
  373. },
  374. onSMSSend() {
  375. let smsParams = {};
  376. smsParams.mobile = this.phoneNo;
  377. smsParams.smsmode = "0";
  378. let checkPhone = new RegExp(/^[1]([3-9])[0-9]{9}$/);
  379. if (!smsParams.mobile || smsParams.mobile.length == 0) {
  380. this.$tip.toast("请输入手机号");
  381. return false;
  382. }
  383. if (!checkPhone.test(smsParams.mobile)) {
  384. this.$tip.toast("请输入正确的手机号");
  385. return false;
  386. }
  387. this.$http.post("/sys/sms", smsParams).then((res) => {
  388. if (res.data.success) {
  389. this.smsCountDown = 60;
  390. this.startSMSTimer();
  391. } else {
  392. this.smsCountDown = 0;
  393. this.$tip.toast(res.data.message);
  394. }
  395. });
  396. },
  397. startSMSTimer() {
  398. this.smsCountInterval = setInterval(() => {
  399. this.smsCountDown--;
  400. if (this.smsCountDown <= 0) {
  401. clearInterval(this.smsCountInterval);
  402. }
  403. }, 1000);
  404. },
  405. onSMSLogin() {
  406. let checkPhone = new RegExp(/^[1]([3-9])[0-9]{9}$/);
  407. if (!this.phoneNo || this.phoneNo.length == 0) {
  408. this.$tip.toast("请填写手机号");
  409. return;
  410. }
  411. if (!checkPhone.test(this.phoneNo)) {
  412. this.$tip.toast("请输入正确的手机号");
  413. return false;
  414. }
  415. if (!this.smsCode || this.smsCode.length == 0) {
  416. this.$tip.toast("请填短信验证码");
  417. return;
  418. }
  419. let loginParams = {
  420. mobile: this.phoneNo,
  421. captcha: this.smsCode,
  422. };
  423. this.PhoneLogin(loginParams)
  424. .then((res) => {
  425. console.log("res====》", res);
  426. if (res.data.success) {
  427. this.$tip.success("登录成功!");
  428. uni.navigateTo({
  429. url: "/pages/inedx/inedx",
  430. });
  431. } else {
  432. this.$tip.error(res.data.message);
  433. }
  434. })
  435. .catch((err) => {
  436. let msg =
  437. ((err.response || {}).data || {}).message ||
  438. err.data.message ||
  439. "请求出现错误,请稍后再试";
  440. this.$tip.error(msg);
  441. });
  442. },
  443. loginSuccess() {
  444. // 登陆成功,重定向到主页
  445. this.$Router.replace({ name: "index" });
  446. },
  447. requestFailed(err) {
  448. this.$message.warning("登录失败");
  449. },
  450. changeloginType() {
  451. console.log("changeloginType====");
  452. console.log(configService, "changeloginType====");
  453. var tourl = configService.apiUrl;
  454. tourl = tourl.replace(9999, 8092);
  455. // this.$tip.success("tourl="+tourl);
  456. var rastourl =
  457. "https://id.shendong.com.cn/default" +
  458. "/login?service=" +
  459. encodeURIComponent(tourl) +
  460. "&renew=true";
  461. // rastourl ="http://182.92.126.35:8092/?ticket=234";
  462. console.log("===========" + rastourl);
  463. this.openBrowser(rastourl);
  464. // window.location.href='/pages/index/index?ticket=123'
  465. // this.$router.push({ path: '/pages/index/index?ticket=123',query:"2w354" })
  466. },
  467. openBrowser(url) {
  468. // 使用uni.navigateTo打开内置浏览器
  469. console.log("----url---------------" + url);
  470. // this.$tip.success("url="+url);
  471. uni.navigateTo({
  472. url: "/pages/webview/webview?url=" + encodeURIComponent(url),
  473. });
  474. },
  475. setIp() {
  476. console.log("点击成功");
  477. this.ipShow = !this.ipShow;
  478. },
  479. changeIP() {
  480. this.ipShow1 = true;
  481. },
  482. selectIpAddr(e) {
  483. this.ipShow1 = false;
  484. const fullURL = e.value[0].value;
  485. this.IPSet = e.value[0].label;
  486. const apiCode = e.value[0].code;
  487. configService.apiUrl = fullURL;
  488. uni.setStorageSync("apiUrl", configService.apiUrl);
  489. uni.setStorageSync("apiCode", apiCode);
  490. setTimeout(() => {
  491. uni.getStorageSync("apiUrl");
  492. }, 100);
  493. // 切换 IP 后重新进入登录页,清空页面栈,避免侧滑回退到旧页面
  494. uni.reLaunch({ url: "/pages/login/login" });
  495. },
  496. },
  497. beforeDestroy() {
  498. if (this.smsCountInterval) {
  499. clearInterval(this.smsCountInterval);
  500. }
  501. },
  502. };
  503. </script>
  504. <style scoped>
  505. .login-page {
  506. min-height: 100vh;
  507. background: #ffffff;
  508. display: flex;
  509. flex-direction: column;
  510. position: relative;
  511. overflow: hidden;
  512. }
  513. /* ===== 顶部插画 ===== */
  514. .login-header {
  515. position: relative;
  516. width: 100%;
  517. height: 520rpx;
  518. flex-shrink: 0;
  519. }
  520. .header-bg {
  521. position: absolute;
  522. left: 0;
  523. top: 0;
  524. width: 100%;
  525. height: 100%;
  526. z-index: 0;
  527. }
  528. .header-mask {
  529. position: absolute;
  530. left: 0;
  531. bottom: 0;
  532. width: 100%;
  533. height: 160rpx;
  534. background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #ffffff);
  535. z-index: 1;
  536. }
  537. .header-content {
  538. position: relative;
  539. z-index: 2;
  540. padding: 88rpx 48rpx 0;
  541. box-sizing: border-box;
  542. }
  543. .header-top {
  544. display: flex;
  545. flex-direction: row;
  546. align-items: center;
  547. justify-content: space-between;
  548. margin-bottom: 36rpx;
  549. }
  550. .logo {
  551. width: 72rpx;
  552. height: 84rpx;
  553. }
  554. .welcome-text {
  555. font-size: 36rpx;
  556. color: #1a1a1a;
  557. font-weight: 500;
  558. line-height: 1.4;
  559. margin-bottom: 12rpx;
  560. }
  561. .platform-name {
  562. font-size: 40rpx;
  563. color: #111111;
  564. font-weight: 700;
  565. line-height: 1.4;
  566. letter-spacing: 1rpx;
  567. }
  568. /* ===== 表单区 ===== */
  569. .login-body {
  570. flex: 1;
  571. display: flex;
  572. flex-direction: column;
  573. justify-content: space-between;
  574. padding: 40rpx 48rpx 80rpx;
  575. box-sizing: border-box;
  576. background: #ffffff;
  577. }
  578. .form-area {
  579. width: 100%;
  580. }
  581. .input-item {
  582. display: flex;
  583. flex-direction: row;
  584. align-items: center;
  585. height: 96rpx;
  586. padding: 0 28rpx;
  587. margin-bottom: 28rpx;
  588. background: #eff3ff;
  589. border-radius: 16rpx;
  590. box-sizing: border-box;
  591. }
  592. .input-field {
  593. flex: 1;
  594. height: 96rpx;
  595. margin-left: 20rpx;
  596. font-size: 30rpx;
  597. color: #333333;
  598. }
  599. .input-placeholder {
  600. color: #9aa3b5;
  601. font-size: 30rpx;
  602. }
  603. .sso-link {
  604. margin-top: 8rpx;
  605. text-align: right;
  606. font-size: 26rpx;
  607. color: #2979ff;
  608. }
  609. /* ===== 底部登录 ===== */
  610. .footer-area {
  611. width: 100%;
  612. padding-bottom: env(safe-area-inset-bottom);
  613. }
  614. .login-btn {
  615. width: 100%;
  616. height: 96rpx;
  617. line-height: 96rpx;
  618. background: #007aff;
  619. color: #ffffff;
  620. font-size: 34rpx;
  621. font-weight: 600;
  622. border-radius: 48rpx;
  623. border: none;
  624. text-align: center;
  625. padding: 0;
  626. }
  627. .login-btn::after {
  628. border: none;
  629. }
  630. .login-btn[disabled] {
  631. opacity: 0.75;
  632. }
  633. .version-text {
  634. margin-top: 24rpx;
  635. text-align: center;
  636. font-size: 24rpx;
  637. color: #999999;
  638. }
  639. /* ===== IP 配置 ===== */
  640. .ip-panel {
  641. flex: 1;
  642. background: #ffffff;
  643. padding: 40rpx 48rpx;
  644. }
  645. .IPSet {
  646. display: flex;
  647. flex-direction: column;
  648. }
  649. .text-style {
  650. margin: 20px;
  651. }
  652. </style>