login.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. <template>
  2. <view id="login" class="section">
  3. <view class="bg">
  4. <image class="bgImage" :src="useStore.$state.loginBg" v-if="useStore.$state.loginBg" />
  5. </view>
  6. <view class="middle">
  7. <view class="top">
  8. <image class="logo" mode="heightFix" :src="useStore.$state.loginLogo" v-if="useStore.$state.loginLogo" />
  9. <!-- <image class="logo" mode="heightFix" src="@/static/logo200.png" v-else /> -->
  10. <text class="title" :style="{ color: useStore.$state.loginBg ? '#FFFFFF' : '#000000' }" v-if="useStore.$state.loginTitle">{{ useStore.$state.loginTitle }}</text>
  11. <!-- <text class="title" v-else>移动端登录</text> -->
  12. </view>
  13. <view class="content">
  14. <text class="title" :style="{ color: useStore.$state.loginBg ? '#FFFFFF' : '#000000' }">请登录</text>
  15. <!-- #ifdef APP-PLUS || MP-WEIXIN -->
  16. <view id="okay" v-if="!linkUrl">首次账号登录请先配置服务器</view>
  17. <view class="setting" @tap="goSeverConfig"> 配置服务器 </view>
  18. <!--#endif-->
  19. </view>
  20. <view id="login-input" v-if="switchText == '账号密码登录'">
  21. <u-input v-model="phone" prefixIcon="phone" placeholder="请输入手机号码" />
  22. <u-input v-model="verify" prefixIcon="email" placeholder="请输入验证码" :maxlength="6">
  23. <template #suffix>
  24. <button class="verify" @click="getVerifyCode">{{ !useStore.codeTime ? "获取验证码" : useStore.codeTime + "s" }}</button>
  25. </template>
  26. </u-input>
  27. </view>
  28. <view id="login-input" v-if="switchText == '验证码登录'">
  29. <u-input type="text" v-model="username" prefixIcon="account" placeholder="请输入账号" />
  30. <u-input v-model="password" prefixIcon="lock" placeholder="请输入密码" :password="inputIconBool">
  31. <template #suffix>
  32. <text :class="!inputIconBool ? 'iconfont ucicon-eye' : 'iconfont ucicon-eye-close'" @click="inputIconBool = !inputIconBool"></text>
  33. </template>
  34. </u-input>
  35. </view>
  36. <button class="submit" @click="submitRes">登 录</button>
  37. <view class="switchText">
  38. <text @click="switchMode">{{ switchText }}</text>
  39. </view>
  40. <!-- #ifdef APP-PLUS || MP-WEIXIN -->
  41. <view class="xieyi text-center">
  42. <u-checkbox-group v-model="userChecked">
  43. <u-checkbox :name="true" shape="circle" inactiveColor="#0081ff" size="13"></u-checkbox>
  44. </u-checkbox-group>
  45. <text>我已阅读并同意</text>
  46. <text @click="handleUserAgrement" class="text-blue">用户协议</text>
  47. <text>和</text>
  48. <text @click="handlePrivacy" class="text-blue">隐私协议</text>
  49. </view>
  50. <!--#endif-->
  51. </view>
  52. <view class="bottom">
  53. <div class="title">{{ useStore.$state.loginBottomTitle }}</div>
  54. </view>
  55. </view>
  56. </template>
  57. <script setup>
  58. import config from "@/config";
  59. import { onLoad, onShow, onHide, onLaunch, onReady } from "@dcloudio/uni-app";
  60. import { reactive, getCurrentInstance, toRefs, inject } from "vue";
  61. import { publicStores, useStores } from "@/store/modules/index";
  62. const useStore = useStores();
  63. const publicStore = publicStores();
  64. const { proxy } = getCurrentInstance();
  65. const data = reactive({
  66. /** login数据 */
  67. phone: undefined,
  68. verify: undefined,
  69. switchText: "验证码登录",
  70. username: undefined,
  71. password: undefined,
  72. inputIconBool: true,
  73. /** 服务器配置数据 */
  74. linkUrl: uni.getStorageSync("serveUrl"),
  75. /** 用户隐私协议数据 */
  76. userChecked: [true],
  77. });
  78. const { phone, verify, switchText, username, password, inputIconBool, linkUrl, userChecked } = toRefs(data);
  79. function goSeverConfig() {
  80. proxy.$tab.navigateTo("/pages/serveConfigSelect");
  81. }
  82. /**登录方式切换 */
  83. function switchMode() {
  84. if (switchText.value == "验证码登录") {
  85. switchText.value = "账号密码登录";
  86. } else {
  87. switchText.value = "验证码登录";
  88. }
  89. }
  90. /** 点击发送验证码 */
  91. function getVerifyCode() {
  92. //#ifdef APP-PLUS || MP-WEIXIN
  93. if (!uni.getStorageSync("serveUrl")) {
  94. proxy.$modal.msg("首次账号登录请先配置服务器");
  95. return;
  96. }
  97. //#endif
  98. verify.value = undefined;
  99. useStore.GetCodeImg({
  100. phone: phone.value,
  101. success: (res) => {
  102. proxy.$modal.msgSuccess("发送成功");
  103. },
  104. });
  105. }
  106. /**
  107. * 判断运行环境
  108. */
  109. function env() {
  110. useStore.SET_LOGINMOBILELIST({
  111. loginTitle: "",
  112. loginBottomTitle: "",
  113. loginBg: "",
  114. loginLogo: "",
  115. tenantId: "",
  116. });
  117. //#ifdef H5
  118. if (window.location.host) {
  119. linkUrl.value = window.location.host;
  120. // linkUrl.value='ces.cn';
  121. // linkUrl.value = "172.16.120.165:13207";
  122. // linkUrl.value = "172.16.120.165:13200";
  123. // linkUrl.value = "localhost:81";
  124. useStore.GetMobileTenantConfig({ url: linkUrl.value });
  125. }
  126. //#endif
  127. //#ifdef APP-PLUS || MP-WEIXIN
  128. if (uni.getStorageSync("serveUrl")) {
  129. linkUrl.value = uni.getStorageSync("serveUrl");
  130. useStore.GetMobileTenantConfig({ url: linkUrl.value });
  131. } else {
  132. uni.setStorageSync("serveUrl", "manager.usky.cn");
  133. publicStore.setServeList("manager.usky.cn", "");
  134. linkUrl.value = uni.getStorageSync("serveUrl");
  135. useStore.GetMobileTenantConfig({ url: linkUrl.value });
  136. }
  137. //#endif
  138. }
  139. /** 点击提交按钮 */
  140. function submitRes() {
  141. //#ifdef APP-PLUS || MP-WEIXIN
  142. if (!uni.getStorageSync("serveUrl")) {
  143. proxy.$modal.msg("首次登录请先进行服务器配置");
  144. return;
  145. }
  146. if (!userChecked.value[0]) {
  147. proxy.$modal.msg("请在阅读并同意 用户协议和隐私协议后登录");
  148. return;
  149. }
  150. //#endif
  151. if (switchText.value == "账号密码登录") {
  152. if (!phone.value) {
  153. proxy.$modal.msg("请输入手机号码");
  154. return;
  155. }
  156. if (!/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(phone.value)) {
  157. proxy.$modal.msg("请输入正确的手机号码");
  158. return;
  159. }
  160. if (!verify.value) {
  161. proxy.$modal.msg("请输入验证码");
  162. return;
  163. }
  164. login({
  165. phone: phone.value,
  166. verify: verify.value,
  167. tenantId: useStore.$state.tenantId,
  168. });
  169. } else {
  170. if (!username.value) {
  171. proxy.$modal.msg("请输入账户");
  172. return;
  173. }
  174. if (!password.value) {
  175. proxy.$modal.msg("请输入密码");
  176. return;
  177. }
  178. login({
  179. username: username.value,
  180. password: password.value,
  181. tenantId: useStore.$state.tenantId,
  182. });
  183. }
  184. }
  185. /** 获取登录数据 */
  186. function login(data) {
  187. proxy.$modal.loading("登录中,请耐心等待...");
  188. useStore.Login(data).then(() => {
  189. /** 获取用户信息 */
  190. proxy.$modal.closeLoading();
  191. useStore.GetInfo().then((res) => {
  192. proxy.$tab.reLaunch("/pages/index");
  193. });
  194. });
  195. }
  196. // 用户协议
  197. function handleUserAgrement() {
  198. let site = config.appInfo.agreements[0];
  199. proxy.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`);
  200. }
  201. // 隐私协议
  202. function handlePrivacy() {
  203. let site = config.appInfo.agreements[1];
  204. proxy.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`);
  205. }
  206. onShow(() => {
  207. env();
  208. useStore.SetInterval("codeTime"); //调用倒计时定时器
  209. });
  210. onLoad((options) => {});
  211. </script>
  212. <style lang="scss" scoped>
  213. .section {
  214. position: fixed;
  215. top: 0;
  216. left: 0;
  217. right: 0;
  218. bottom: 0;
  219. display: flex;
  220. width: 100%;
  221. height: 100vh;
  222. background-color: $uni-bg-color;
  223. .bg {
  224. width: 100%;
  225. height: 100%;
  226. position: fixed;
  227. top: 0;
  228. left: 0;
  229. right: 0;
  230. z-index: 0;
  231. .bgImage {
  232. width: 100%;
  233. height: 100%;
  234. }
  235. }
  236. .middle {
  237. position: relative;
  238. z-index: 1;
  239. width: 100%;
  240. padding: 0 30px;
  241. margin: auto;
  242. margin-top: 30%;
  243. .top {
  244. display: flex;
  245. align-items: center;
  246. justify-content: center;
  247. margin-bottom: 60px;
  248. .logo {
  249. height: 40px;
  250. width: auto;
  251. margin-right: 10px;
  252. }
  253. .title {
  254. font-size: 20px;
  255. color: #000;
  256. max-width: 50%;
  257. // white-space: nowrap;
  258. // overflow: hidden; //超出的文本隐藏
  259. // text-overflow: ellipsis; //溢出用省略号显示
  260. }
  261. }
  262. .content {
  263. display: flex;
  264. position: relative;
  265. margin: 30px 0 30px 0;
  266. .title {
  267. margin: auto auto auto 0;
  268. color: #000;
  269. font-size: 18px;
  270. }
  271. .icons {
  272. margin: auto 5px auto 0;
  273. }
  274. .setting {
  275. color: #2a98ff;
  276. margin: auto 0;
  277. }
  278. #okay {
  279. position: absolute;
  280. top: -35px;
  281. right: 0px;
  282. background-color: #2a98ff;
  283. text-align: center;
  284. line-height: 25px;
  285. display: inline-block;
  286. color: #fff;
  287. padding: 3px 5px;
  288. border-radius: 3px;
  289. &::after {
  290. content: "";
  291. position: absolute;
  292. border: 5px solid transparent;
  293. transform: rotate(90deg);
  294. right: 5px;
  295. bottom: -9px;
  296. border-left-color: #2a98ff;
  297. }
  298. }
  299. }
  300. // 登录页-服务器配置样式 开始
  301. #login-input {
  302. :deep(.u-input) {
  303. height: 45px;
  304. border: 0 !important;
  305. border-radius: 8px;
  306. margin-bottom: 15px;
  307. padding: 5px 12px !important;
  308. background-color: #f5f6fa !important;
  309. }
  310. :deep(.input-placeholder) {
  311. color: #c0c4cc !important;
  312. }
  313. :deep(.uni-input-wrapper) {
  314. font-size: 16px;
  315. }
  316. :deep(.u-icon__icon) {
  317. font-size: 24px !important;
  318. line-height: 24px !important;
  319. color: gray !important;
  320. }
  321. :deep(.iconfont) {
  322. color: gray !important;
  323. }
  324. :deep(:-webkit-autofill) {
  325. caret-color: #000; // 设置光标颜色
  326. // -webkit-text-fill-color: gray !important;
  327. -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
  328. background-color: transparent;
  329. background-image: none;
  330. transition: background-color 50000s ease-in-out 0s; //背景色透明 生效时长 过渡效果 启用时延迟的时间
  331. }
  332. .verify {
  333. color: #2a98ff;
  334. font-size: 14px;
  335. padding-left: 0px;
  336. padding-right: 0px;
  337. background-color: transparent;
  338. &::after {
  339. border: 0px;
  340. }
  341. }
  342. }
  343. .switchText {
  344. color: #96a6b5;
  345. width: 100%;
  346. display: block;
  347. margin-top: 20px;
  348. }
  349. .submit {
  350. height: 45px;
  351. line-height: 45px;
  352. border-radius: 24px;
  353. background: #2a98ff;
  354. color: #fff;
  355. border: 0px;
  356. }
  357. .xieyi {
  358. color: #96a6b5;
  359. margin-top: 30px;
  360. display: flex;
  361. justify-content: center;
  362. > uni-view {
  363. margin: auto 0;
  364. }
  365. > uni-text {
  366. margin: auto 0;
  367. }
  368. // animation: roundRule 0.5s linear infinite;
  369. }
  370. @keyframes roundRule {
  371. 0% {
  372. transform: translateX(0);
  373. }
  374. 50% {
  375. transform: translateX(-5px);
  376. }
  377. 100% {
  378. transform: translateX(0);
  379. }
  380. }
  381. }
  382. .bottom {
  383. position: fixed;
  384. width: 100%;
  385. bottom: 20px;
  386. .title {
  387. text-align: center;
  388. color: #96a6b5;
  389. font-size: 14px;
  390. }
  391. }
  392. }
  393. </style>