login.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <template xmlns="">
  2. <div class="container">
  3. <!-- <div class="logo"></div> -->
  4. <!-- 登录区域 -->
  5. <div class="content">
  6. <!-- 配图 -->
  7. <div class="pic"></div>
  8. <!-- 表单 -->
  9. <div class="field">
  10. <!-- [移动端]标题 -->
  11. <h2 class="mobile-title">
  12. <h3 class="title">爱思系统</h3>
  13. </h2>
  14. <!-- 表单 -->
  15. <div class="form-cont">
  16. <el-tabs class="form" v-model="loginForm.loginType" style=" float:none;">
  17. <el-tab-pane label="密码登录" name="uname">
  18. </el-tab-pane>
  19. <el-tab-pane label="验证码登录" name="sms">
  20. </el-tab-pane>
  21. </el-tabs>
  22. <div>
  23. <el-form ref="loginForm" :model="loginForm" :rules="LoginRules" class="login-form">
  24. <el-form-item prop="tenantName" v-if="tenantEnable">
  25. <el-input v-model="loginForm.tenantName" type="text" auto-complete="off" placeholder='租户'>
  26. <svg-icon slot="prefix" icon-class="tree" class="el-input__icon input-icon"/>
  27. </el-input>
  28. </el-form-item>
  29. <!-- 账号密码登录 -->
  30. <div v-if="loginForm.loginType === 'uname'">
  31. <el-form-item prop="username">
  32. <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="手机号">
  33. <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
  34. </el-input>
  35. </el-form-item>
  36. <el-form-item prop="password">
  37. <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码"
  38. @keyup.enter.native="getCode">
  39. <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
  40. </el-input>
  41. </el-form-item>
  42. <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;">记住密码</el-checkbox>
  43. </div>
  44. <!-- 短信验证码登录 -->
  45. <div v-if="loginForm.loginType === 'sms'">
  46. <el-form-item prop="mobile">
  47. <el-input v-model="loginForm.mobile" type="text" auto-complete="off" placeholder="请输入手机号">
  48. <svg-icon slot="prefix" icon-class="phone" class="el-input__icon input-icon"/>
  49. </el-input>
  50. </el-form-item>
  51. <el-form-item prop="mobileCode">
  52. <el-input v-model="loginForm.mobileCode" type="text" auto-complete="off" placeholder="短信验证码"
  53. class="sms-login-mobile-code-prefix"
  54. @keyup.enter.native="handleLogin">
  55. <template>
  56. <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
  57. </template>
  58. <template slot="append">
  59. <span v-if="mobileCodeTimer <= 0" class="getMobileCode" @click="getSmsCode" style="cursor: pointer;">获取验证码</span>
  60. <span v-if="mobileCodeTimer > 0" class="getMobileCode">{{ mobileCodeTimer }}秒后可重新获取</span>
  61. </template>
  62. </el-input>
  63. </el-form-item>
  64. </div>
  65. <!-- 下方的登录按钮 -->
  66. <el-form-item style="width:100%;">
  67. <el-button :loading="loading" size="medium" type="primary" style="width:100%;"
  68. @click.native.prevent="getCode">
  69. <span v-if="!loading">登 录</span>
  70. <span v-else>登 录 中...</span>
  71. </el-button>
  72. </el-form-item>
  73. <!-- 注册 -->
  74. <div class="register-tip">
  75. 没有账号?
  76. <span class="register-btn" @click="doRegister()">免费注册</span>
  77. </div>
  78. <!-- 社交登录 -->
  79. <!-- <el-form-item style="width:100%;">
  80. <div class="oauth-login" style="display:flex">
  81. <div class="oauth-login-item" v-for="item in SysUserSocialTypeEnum" :key="item.type" @click="doSocialLogin(item)">
  82. <img :src="item.img" height="25px" width="25px" alt="登录" >
  83. <span>{{item.title}}</span>
  84. </div>
  85. </div>
  86. </el-form-item> -->
  87. <!-- 教程说明 -->
  88. <!-- <el-form-item style="width:100%; margin-top:-25px">
  89. <el-link href="https://doc.iocoder.cn/" target="_blank">📚开发指南</el-link>
  90. <el-link href="https://doc.iocoder.cn/video/" target="_blank" style="padding-left: 10px">🔥视频教程</el-link>
  91. <el-link href="https://www.iocoder.cn/Interview/good-collection/" target="_blank" style="padding-left: 10px">⚡面试手册</el-link>
  92. <el-link href="http://static.yudao.iocoder.cn/mp/Aix9975.jpeg" target="_blank" style="padding-left: 10px">🤝外包咨询</el-link>
  93. </el-form-item> -->
  94. </el-form>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. <!-- 图形验证码 -->
  100. <Verify ref="verify" :captcha-type="'blockPuzzle'" :img-size="{width:'400px',height:'200px'}"
  101. @success="handleLogin" />
  102. <!-- footer -->
  103. <!-- <div class="footer">
  104. Copyright © 2020-2022 iocoder.cn All Rights Reserved.
  105. </div> -->
  106. </div>
  107. </template>
  108. <script>
  109. import {sendSmsCode, socialAuthRedirect} from "@/api/login";
  110. import {getTenantIdByName} from "@/api/system/tenant";
  111. import {SystemUserSocialTypeEnum} from "@/utils/constants";
  112. import {getCaptchaEnable, getTenantEnable} from "@/utils/ruoyi";
  113. import {
  114. getPassword,
  115. getRememberMe, getTenantName,
  116. getUsername,
  117. removePassword, removeRememberMe, removeTenantName,
  118. removeUsername,
  119. setPassword, setRememberMe, setTenantId, setTenantName,
  120. setUsername
  121. } from "@/utils/auth";
  122. import Verify from '@/components/Verifition/Verify';
  123. import {resetUserPwd} from "@/api/system/user";
  124. export default {
  125. name: "Login",
  126. components: {
  127. Verify
  128. },
  129. data() {
  130. return {
  131. codeUrl: "",
  132. captchaEnable: true,
  133. tenantEnable: true,
  134. mobileCodeTimer: 0,
  135. loginForm: {
  136. loginType: "uname",
  137. username: "admin",
  138. password: "admin123",
  139. // username: "",
  140. // password: "",
  141. captchaVerification: "",
  142. mobile: "",
  143. mobileCode: "",
  144. rememberMe: false,
  145. tenantName: "芋道源码",
  146. },
  147. scene: 21,
  148. LoginRules: {
  149. username: [
  150. {required: true, trigger: "blur", message: "用户名不能为空"}
  151. ],
  152. password: [
  153. {required: true, trigger: "blur", message: "密码不能为空"}
  154. ],
  155. mobile: [
  156. {required: true, trigger: "blur", message: "手机号不能为空"},
  157. {
  158. validator: function (rule, value, callback) {
  159. if (/^(?:(?:\+|00)86)?1(?:3[\d]|4[5-79]|5[0-35-9]|6[5-7]|7[0-8]|8[\d]|9[189])\d{8}$/.test(value) === false) {
  160. callback(new Error("手机号格式错误"));
  161. } else {
  162. callback();
  163. }
  164. }, trigger: "blur"
  165. }
  166. ],
  167. tenantName: [
  168. {required: true, trigger: "blur", message: "租户不能为空"},
  169. {
  170. validator: (rule, value, callback) => {
  171. // debugger
  172. getTenantIdByName(value).then(res => {
  173. const tenantId = res.data;
  174. if (tenantId && tenantId >= 0) {
  175. // 设置租户
  176. setTenantId(tenantId)
  177. callback();
  178. } else {
  179. callback('租户不存在');
  180. }
  181. });
  182. },
  183. trigger: 'blur'
  184. }
  185. ]
  186. },
  187. loading: false,
  188. redirect: undefined,
  189. // 枚举
  190. SysUserSocialTypeEnum: SystemUserSocialTypeEnum,
  191. };
  192. },
  193. created() {
  194. // 租户开关
  195. this.tenantEnable = getTenantEnable();
  196. if (this.tenantEnable) {
  197. getTenantIdByName(this.loginForm.tenantName).then(res => { // 设置租户
  198. const tenantId = res.data;
  199. if (tenantId && tenantId >= 0) {
  200. setTenantId(tenantId)
  201. }
  202. });
  203. }
  204. // 验证码开关
  205. this.captchaEnable = getCaptchaEnable();
  206. // 重定向地址
  207. this.redirect = this.$route.query.redirect ? decodeURIComponent(this.$route.query.redirect) : undefined;
  208. this.getCookie();
  209. },
  210. methods: {
  211. //跳转注册
  212. doRegister() {
  213. this.$router.push({path: '/register'})
  214. },
  215. getCode() {
  216. // 情况一,未开启:则直接登录
  217. if (!this.captchaEnable) {
  218. this.handleLogin({})
  219. return;
  220. }
  221. // 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录
  222. // 弹出验证码
  223. this.$refs.verify.show()
  224. },
  225. getCookie() {
  226. const username = getUsername();
  227. const password = getPassword();
  228. const rememberMe = getRememberMe();
  229. const tenantName = getTenantName();
  230. this.loginForm = {
  231. ...this.loginForm,
  232. username: username ? username : this.loginForm.username,
  233. password: password ? password : this.loginForm.password,
  234. rememberMe: rememberMe ? getRememberMe() : false,
  235. tenantName: tenantName ? tenantName : this.loginForm.tenantName,
  236. };
  237. },
  238. handleLogin(captchaParams) {
  239. this.$refs.loginForm.validate(valid => {
  240. if (valid) {
  241. this.loading = true;
  242. // 设置 Cookie
  243. if (this.loginForm.rememberMe) {
  244. setUsername(this.loginForm.username)
  245. setPassword(this.loginForm.password)
  246. setRememberMe(this.loginForm.rememberMe)
  247. setTenantName(this.loginForm.tenantName)
  248. } else {
  249. removeUsername()
  250. removePassword()
  251. removeRememberMe()
  252. removeTenantName()
  253. }
  254. this.loginForm.captchaVerification = captchaParams.captchaVerification
  255. // 发起登陆
  256. // console.log("发起登录", this.loginForm);
  257. this.$store.dispatch(this.loginForm.loginType === "sms" ? "SmsLogin" : "Login", this.loginForm).then(() => {
  258. this.$router.push({path: "/"}).catch(() => {
  259. });
  260. }).catch(() => {
  261. this.loading = false;
  262. });
  263. }
  264. });
  265. },
  266. async doSocialLogin(socialTypeEnum) {
  267. // 设置登录中
  268. this.loading = true;
  269. let tenant = false;
  270. if (this.tenantEnable) {
  271. await this.$prompt('请输入租户名称', "提示", {
  272. confirmButtonText: "确定",
  273. cancelButtonText: "取消"
  274. }).then(async ({value}) => {
  275. await getTenantIdByName(value).then(res => {
  276. const tenantId = res.data;
  277. tenant = true
  278. if (tenantId && tenantId >= 0) {
  279. setTenantId(tenantId)
  280. }
  281. });
  282. }).catch(() => {
  283. // 取消登录按钮 loading状态
  284. this.loading = false;
  285. return false
  286. });
  287. } else {
  288. tenant = true
  289. }
  290. if(tenant){
  291. // 计算 redirectUri
  292. const redirectUri = location.origin + '/social-login?'
  293. + encodeURIComponent('type=' + socialTypeEnum.type + '&redirect=' + (this.redirect || "/")); // 重定向不能丢
  294. // const redirectUri = 'http://127.0.0.1:48080/api/gitee/callback';
  295. // const redirectUri = 'http://127.0.0.1:48080/api/dingtalk/callback';
  296. // 进行跳转
  297. socialAuthRedirect(socialTypeEnum.type, encodeURIComponent(redirectUri)).then((res) => {
  298. // console.log(res.url);
  299. window.location.href = res.data;
  300. });
  301. }
  302. },
  303. /** ========== 以下为升级短信登录 ========== */
  304. getSmsCode() {
  305. if (this.mobileCodeTimer > 0) return;
  306. this.$refs.loginForm.validate(valid => {
  307. if (!valid) return;
  308. sendSmsCode(this.loginForm.mobile, this.scene, this.loginForm.uuid, this.loginForm.code).then(res => {
  309. this.$modal.msgSuccess("获取验证码成功")
  310. this.mobileCodeTimer = 60;
  311. let msgTimer = setInterval(() => {
  312. this.mobileCodeTimer = this.mobileCodeTimer - 1;
  313. if (this.mobileCodeTimer <= 0) {
  314. clearInterval(msgTimer);
  315. }
  316. }, 1000);
  317. });
  318. });
  319. }
  320. }
  321. };
  322. </script>
  323. <style lang="scss" scoped>
  324. @import "~@/assets/styles/login.scss";
  325. .register-tip{
  326. color: #141e31;
  327. font-size: 14px;
  328. line-height: 20px;
  329. margin: 10px 0 20px;
  330. }
  331. .register-btn{
  332. color: #1890ff;
  333. cursor: pointer;
  334. }
  335. .oauth-login {
  336. display: flex;
  337. align-items: center;
  338. cursor:pointer;
  339. }
  340. .oauth-login-item {
  341. display: flex;
  342. align-items: center;
  343. margin-right: 10px;
  344. }
  345. .oauth-login-item img {
  346. height: 25px;
  347. width: 25px;
  348. }
  349. .oauth-login-item span:hover {
  350. text-decoration: underline red;
  351. color: red;
  352. }
  353. .sms-login-mobile-code-prefix {
  354. :deep(.el-input__prefix) {
  355. top: 22%;
  356. }
  357. }
  358. </style>