index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <template>
  2. <view class="container">
  3. <view class="title-content">
  4. <image src="../../static/emblem-icon.png" mode=""></image>
  5. <view class="text-layer">
  6. <!-- <text class="title">哈密市项目</text> -->
  7. <text class="sub-title">哈密市项目管理智慧平台</text>
  8. </view>
  9. </view>
  10. <view class="login-form-content">
  11. <view class="input-box">
  12. <view class="input-item flex align-center">
  13. <input v-model="loginForm.userName" style="font-size: 14px;" class="input" type="text" placeholder="请输入您现有的账号" maxlength="30" />
  14. </view>
  15. <view class="input-item flex align-center">
  16. <input v-model="loginForm.password" @keyup.enter="handleLogin" :type="passType" class="input"
  17. placeholder="请输入您的密码" maxlength="20" />
  18. <view class="pass-item-icon" :class="passType === 'text' ? 'pass-item-hide' :''">
  19. <image :src="passIcon" @click="changeInputType()"></image>
  20. </view>
  21. </view>
  22. </view>
  23. <view class="forget-pass-item">
  24. <text class="forget-pass" @click="goToForgetPass()">忘记密码</text>
  25. </view>
  26. <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round"
  27. :class="{ 'color-bg': colorCheck }">登录</button>
  28. <view class="change-ip">
  29. <text class="forget-pass" @click="goToChangeIP()">更换服务地址</text>
  30. </view>
  31. </view>
  32. <u-overlay :show="isDownload">
  33. <view class="download-box">
  34. <view class="loading-box">
  35. <view class="loading-icon">
  36. <u-loading-icon v-if="downloadPrecent !== '100'" size="40"></u-loading-icon>
  37. <u-icon v-else name="checkmark" size="40"></u-icon>
  38. </view>
  39. <view class="loading-text">{{downloadText}}</view>
  40. <view class="loading-progress">
  41. <u-line-progress :percentage="downloadPrecent" activeColor="#1869F6"></u-line-progress>
  42. </view>
  43. </view>
  44. </view>
  45. </u-overlay>
  46. </view>
  47. </template>
  48. <script setup>
  49. import {
  50. ref,
  51. computed,
  52. onMounted,
  53. watch
  54. } from "vue";
  55. import {
  56. onLoad,
  57. onShow
  58. } from "@dcloudio/uni-app"
  59. import {
  60. getNewestVersion
  61. } from '@/api/login.js'
  62. import {
  63. validateVersion
  64. } from "@/utils/validateVersion.js"
  65. import user from '@/store/modules/user'
  66. import config from '@/config.js'
  67. import store from '@/store'
  68. import passSee from "@/static/pass-see.svg"
  69. import passHide from "@/static/pass-hide.svg"
  70. // 登录信息
  71. const loginForm = ref({
  72. userName: "",
  73. password: ""
  74. });
  75. let passType = ref("password")
  76. let passIcon = ref(passHide)
  77. function changeInputType() {
  78. passType.value = passType.value === "password" ? "text" : "password"
  79. passIcon.value = passType.value === "password" ? passHide : passSee
  80. }
  81. // 登录
  82. async function handleLogin() {
  83. if (functionBan) {
  84. return uni.showToast({
  85. title: '请更新至最新版本后操作。',
  86. icon: 'none',
  87. mask: false,
  88. duration: 1000
  89. });
  90. }
  91. if (loginForm.value.userName === "") {
  92. uni.showToast({
  93. title: '请输入您的账号',
  94. icon: 'error',
  95. mask: false,
  96. duration: 1000
  97. });
  98. } else if (loginForm.value.password === "") {
  99. uni.showToast({
  100. title: '请输入您的密码',
  101. icon: 'error',
  102. mask: false,
  103. duration: 1000
  104. });
  105. } else {
  106. uni.getNetworkType({
  107. success: function(res) {
  108. if (res.networkType === "none") {
  109. // console.log('injudge');
  110. // uni.showToast({
  111. // title: '请输入您的账号',
  112. // icon: 'error',
  113. // mask: false,
  114. // duration: 1000
  115. // });
  116. // console.log('beforeJudge');
  117. // return
  118. const serverAddress = uni.getStorageSync('serverAddress')
  119. const baseUrlIp = serverAddress ? serverAddress : config.baseUrl
  120. let titleText = `服务器ip:${baseUrlIp} 连接不上,请检查网络`
  121. uni.showModal({
  122. // title: '网络不通,请检查网络情况',
  123. title: '提示',
  124. content: titleText,
  125. icon: 'none',
  126. mask: false,
  127. duration: 3000,
  128. showCancel: false,
  129. success: function(res) {
  130. if (res.confirm) {
  131. console.log('用户点击确定');
  132. } else if (res.cancel) {
  133. console.log('用户点击取消');
  134. }
  135. }
  136. });
  137. } else {
  138. uni.showToast({
  139. title: '登录中,请耐心等待...',
  140. icon: 'loading',
  141. mask: false,
  142. duration: 1000
  143. });
  144. store.dispatch('Login', loginForm.value).then(() => {
  145. loginSuccess()
  146. }).catch(err => {
  147. console.log(err);
  148. })
  149. }
  150. },
  151. fail: function(err) {
  152. return uni.showToast({
  153. title: '获取手机网络状态失败。',
  154. icon: 'error',
  155. mask: false,
  156. duration: 1000
  157. });
  158. }
  159. })
  160. }
  161. };
  162. // 设置用户信息
  163. function loginSuccess(result) {
  164. store.dispatch('GetInfo').then(res => {
  165. uni.switchTab({
  166. url: '/pages/home/headHome'
  167. });
  168. })
  169. }
  170. // 忘记密码
  171. function goToForgetPass() {
  172. if (functionBan) {
  173. return uni.showToast({
  174. title: '请更新至最新版本后操作。',
  175. icon: 'none',
  176. mask: false,
  177. duration: 1000
  178. });
  179. }
  180. uni.navigateTo({
  181. url: '/pages/login/forgetPass/index'
  182. })
  183. }
  184. // 更换服务地址
  185. function goToChangeIP() {
  186. if (functionBan) {
  187. return uni.showToast({
  188. title: '请更新至最新版本后操作。',
  189. icon: 'none',
  190. mask: false,
  191. duration: 1000
  192. });
  193. }
  194. uni.navigateTo({
  195. url: '/pages/login/changeIP/index'
  196. })
  197. }
  198. // 禁止功能使用
  199. let functionBan = false
  200. // 是否正在下载新版本
  201. let isDownload = ref(false)
  202. // 下载进度
  203. let downloadPrecent = ref(0)
  204. // 下载文件
  205. let downloadFilePath = null;
  206. // 下载提示文字
  207. let downloadText = ref("下载中,请勿关闭软件。")
  208. // 判断是否最新版本
  209. function judgeIsNewest() {
  210. //#ifdef APP-PLUS
  211. // 获取系统信息
  212. uni.getSystemInfo({
  213. // 成功则进行对比
  214. success: async (res) => {
  215. // 获取最新版本
  216. const newsetVersionRes = await getNewestVersion().catch(() => {
  217. uni.showModal({
  218. title: '错误',
  219. content: '获取最新系统版本失败。'
  220. });
  221. });
  222. let newsetVersion = newsetVersionRes.data.version;
  223. let higherThanNewest = validateVersion(res.appWgtVersion, newsetVersion)
  224. // 如果版本低于服务上的最新版
  225. if (!higherThanNewest) {
  226. // 禁用功能
  227. functionBan = true;
  228. // 最新版本下载链接
  229. const serverAddress = uni.getStorageSync('serverAddress');
  230. const baseUrlIp = serverAddress ? serverAddress : config.baseUrl;
  231. const downloadUrl = baseUrlIp + '/projects/outApi/version/download';
  232. // 展示下载提示
  233. uni.showModal({
  234. title: '新版本提醒',
  235. content: `检测到新版本“${newsetVersion}”,请下载更新。`,
  236. confirmText: '去下载',
  237. cancelText: '退出软件',
  238. cancelColor: '#808080',
  239. success: async (modelRes) => {
  240. // 确认选择
  241. if (modelRes.confirm) {
  242. if (plus.os.name == "Android") {
  243. isDownload.value = true
  244. let downloadTask = uni.downloadFile({
  245. url: downloadUrl,
  246. success: (successRes => {
  247. downloadFilePath = successRes
  248. .tempFilePath;
  249. uni.hideLoading();
  250. plus.runtime.install(successRes
  251. .tempFilePath);
  252. isDownload.value = false;
  253. downloadPrecent.value = 0;
  254. }),
  255. fail: (failRes) => {
  256. uni.hideLoading();
  257. uni.showModal({
  258. title: '错误',
  259. content: '下载最新版本失败。'
  260. });
  261. isDownload.value = false;
  262. downloadPrecent.value = 0;
  263. }
  264. })
  265. downloadTask.onProgressUpdate(res => {
  266. downloadPrecent.value = res.progress
  267. if (res.progress == 100) {
  268. downloadText = "下载完成,即将安装最新版本"
  269. }
  270. })
  271. };
  272. } else {
  273. // 退出软件
  274. plus.runtime.quit();
  275. }
  276. },
  277. })
  278. }
  279. },
  280. // 失败禁用功能并弹窗
  281. fail: () => {
  282. functionBan = true;
  283. uni.showModal({
  284. title: '错误',
  285. content: '获取当前系统版本失败。'
  286. })
  287. }
  288. })
  289. //#endif
  290. }
  291. // 判断是否已经下载了最新版
  292. const judgeIsDownloadNewest = () => {
  293. if (downloadFilePath) {
  294. uni.showModal({
  295. title: '新版本已下载',
  296. content: '最新版本已下载完毕,请点击安装。',
  297. confirmText: '去安装',
  298. showCancel: false,
  299. success: async (modelRes) => {
  300. if (modelRes.confirm) {
  301. if (plus.os.name == "Android") {
  302. plus.runtime.install(downloadFilePath);
  303. }
  304. }
  305. }
  306. })
  307. }
  308. }
  309. let colorCheck = ref(false)
  310. watch(() => {
  311. if (loginForm.value.userName !== '' && loginForm.value.password !== '') {
  312. colorCheck.value = true
  313. } else {
  314. colorCheck.value = false
  315. }
  316. })
  317. onLoad(() => {
  318. judgeIsNewest()
  319. })
  320. onShow(() => {
  321. judgeIsDownloadNewest()
  322. })
  323. </script>
  324. <style lang="scss">
  325. page {
  326. height: 100%;
  327. background-color: #fff !important;
  328. }
  329. .color-bg {
  330. background: #002F69 !important;
  331. }
  332. .container {
  333. position: relative;
  334. width: 100%;
  335. height: 100%;
  336. background-color: #002F69;
  337. overflow: hidden;
  338. .title-content {
  339. position: absolute;
  340. top: 0;
  341. display: flex;
  342. justify-content: center;
  343. align-items: center;
  344. gap: 20rpx;
  345. width: 100%;
  346. height: calc(310rpx + var(--status-bar-height));
  347. z-index: 1;
  348. background-size: 100% 100%;
  349. background-color: #002F69;
  350. image {
  351. width: 144rpx;
  352. height: 144rpx;
  353. }
  354. .text-layer {
  355. display: flex;
  356. flex-direction: column;
  357. justify-content: center;
  358. align-items: flex-start;
  359. .title {
  360. font-size: 40rpx;
  361. font-weight: 700;
  362. color: #FFFFFF;
  363. line-height: 60rpx;
  364. }
  365. .sub-title {
  366. font-size: 46rpx;
  367. font-weight: 700;
  368. color: #FFFFFF;
  369. line-height: 60rpx;
  370. }
  371. }
  372. }
  373. .login-form-content {
  374. position: absolute;
  375. top: calc(310rpx + var(--status-bar-height));
  376. left: 0;
  377. z-index: 100;
  378. width: 100%;
  379. height: 2000rpx;
  380. background-color: #fff;
  381. border-radius: 60rpx 60rpx 0rpx 0rpx;
  382. .welcome-text {
  383. margin: 0 0 60rpx;
  384. font-size: 44rpx;
  385. font-weight: 700;
  386. color: #C6C6CD;
  387. }
  388. .item-text {
  389. font-size: 36rpx;
  390. font-weight: 400;
  391. font-family: Source Han Sans CN-Regular, Source Han Sans CN;
  392. color: #343437;
  393. }
  394. .input-box {
  395. margin: auto;
  396. width: 556rpx;
  397. margin-top: 132rpx;
  398. display: flex;
  399. flex-direction: column;
  400. border: 2rpx solid #DDDDDD;
  401. border-radius: 16rpx;
  402. .input-item {
  403. margin: auto;
  404. height: 90rpx;
  405. width: 558rpx;
  406. font-size: 28rpx;
  407. // background-color: #f5f6f7;
  408. border-radius: 16rpx;
  409. .input {
  410. width: 100%;
  411. font-size: 14px;
  412. line-height: 20px;
  413. text-align: left;
  414. padding-left: 15px;
  415. }
  416. }
  417. }
  418. .pass-item-icon {
  419. flex: 1;
  420. height: 100%;
  421. line-height: 80rpx;
  422. text-align: right;
  423. padding-right: 15px;
  424. image {
  425. width: 36rpx;
  426. height: 18rpx;
  427. }
  428. }
  429. .pass-item-hide {
  430. image {
  431. width: 36rpx;
  432. height: 28rpx;
  433. }
  434. }
  435. .forget-pass-item {
  436. margin: auto;
  437. width: 556rpx;
  438. margin-top: 30rpx;
  439. text-align: right;
  440. }
  441. .forget-pass {
  442. color: #002F69;
  443. }
  444. .login-btn {
  445. margin: auto;
  446. width: 556rpx;
  447. margin-top: 40rpx;
  448. height: 45px;
  449. background: #DDDDDD;
  450. border-radius: 48rpx;
  451. }
  452. }
  453. .change-ip {
  454. margin-top: 200rpx;
  455. text-align: center;
  456. .forget-pass {
  457. color: #002F69;
  458. border-bottom: 2rpx solid #002F69;
  459. }
  460. }
  461. .download-box {
  462. display: flex;
  463. align-items: center;
  464. justify-content: center;
  465. height: 100%;
  466. .loading-box {
  467. display: flex;
  468. flex-direction: column;
  469. justify-content: space-between;
  470. width: 360rpx;
  471. height: 360rpx;
  472. padding: 20rpx;
  473. background-color: #fff;
  474. border-radius: 40rpx;
  475. }
  476. .loading-icon {
  477. flex: 4;
  478. display: flex;
  479. flex-direction: column;
  480. justify-content: center;
  481. }
  482. .loading-text {
  483. flex: 1;
  484. display: flex;
  485. align-items: flex-end;
  486. text-align: center;
  487. }
  488. .loading-progress {
  489. flex: 1;
  490. display: flex;
  491. align-items: flex-end;
  492. }
  493. }
  494. }
  495. </style>