LogInExe.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <div class="loginExe">
  3. <div class="main" >
  4. <div class="title" >排水管道智能检测评估</div>
  5. <div class="left" >
  6. <div class="title2" >虚拟仿真实验平台</div>
  7. <div class="title3" >系统登录</div>
  8. <div class="edit" >
  9. <img class="editLeft" src="../assets/exeLogin/user.webp" />
  10. <input class="editRight newInput" type="text" placeholder="请输入账号" v-model="form.username" />
  11. </div>
  12. <div class="edit" >
  13. <img class="editLeft" src="../assets/exeLogin/pwd.webp" />
  14. <input class="editRight newInput" type="password" placeholder="请输入密码" v-model="form.password" />
  15. </div>
  16. <div class="btnSubmit" >
  17. <img class="btnImg" src="../assets/exeLogin/btn.webp" />
  18. <div class="btnTxt" @click="loginEvent" >登陆</div>
  19. </div>
  20. </div>
  21. </div>
  22. </div>
  23. </template>
  24. <script setup lang="ts">
  25. import { onMounted, reactive, ref, nextTick } from 'vue';
  26. import { ElForm, ElInput, ElNotification } from 'element-plus';
  27. import { loginApi, getCurrentUser } from '@/api/userApi';
  28. import { useUserInfo } from '@/stores/userInfo';
  29. import router from '../router/index';
  30. import { ElMessage } from 'element-plus';
  31. const userInfo = useUserInfo();
  32. const formRef = ref<InstanceType<typeof ElForm>>();
  33. const usernameRef = ref<InstanceType<typeof ElInput>>();
  34. const passwordRef = ref<InstanceType<typeof ElInput>>();
  35. const form = reactive({
  36. username: '',
  37. password: '',
  38. });
  39. const rules = reactive({
  40. username: [
  41. {
  42. required: true,
  43. message: '用户名不能为空',
  44. trigger: 'blur',
  45. },
  46. {
  47. validator: (rule: any, val: string, callback: Function) => {
  48. if (!val) {
  49. return callback();
  50. }
  51. // if (!/^[a-zA-Z0-9_]{2,15}$/.test(val)) {
  52. // return callback(new Error('请输入正确的账户'));
  53. // }
  54. if (typeof val != 'string') {
  55. return callback(new Error('请输入正确的账户'));
  56. }
  57. return callback();
  58. },
  59. trigger: 'blur',
  60. },
  61. ],
  62. password: [
  63. {
  64. required: true,
  65. message: '密码不能为空',
  66. trigger: 'blur',
  67. },
  68. {
  69. validator: (rule: any, val: string, callback: Function) => {
  70. if (!val) {
  71. return callback();
  72. }
  73. if (!regularPassword(val)) {
  74. return callback(new Error('请输入正确的密码'));
  75. }
  76. return callback();
  77. },
  78. trigger: 'blur',
  79. },
  80. ],
  81. });
  82. const focusInput = () => {
  83. if (form.username === '') {
  84. usernameRef.value!.focus();
  85. } else if (form.password === '') {
  86. passwordRef.value!.focus();
  87. }
  88. };
  89. const onSubmit = (formEl: InstanceType<typeof ElForm> | undefined) => {
  90. if (!formEl) return;
  91. formEl.validate((valid) => {
  92. if (valid) {
  93. loginApi(form).then((res) => {
  94. if (res.data.data.token) {
  95. userInfo.setToken(res.data.data.token, 'auth');
  96. const userType = res.data.data.userType;
  97. getCurrentUser().then((res) => {
  98. userInfo.dataFill(Object.assign({ userType: userType }, res.data.data));
  99. // // 老接口的类型 - 学生
  100. // if (userType == 0) router.push({ path: '/train' });
  101. // // 老接口的类型 - 老师
  102. // else if (userType == 1) router.push({ path: '/TaskMng' });
  103. // 老师
  104. if (userType == 0) router.push({ path: '/TaskMng' });
  105. // 学生
  106. else if (userType == 1) router.push({ path: '/studentMain' });
  107. else {
  108. ElNotification({
  109. message: '无效用户',
  110. type: 'info',
  111. });
  112. }
  113. });
  114. }
  115. });
  116. } else {
  117. return false;
  118. }
  119. });
  120. };
  121. /**
  122. * 新的登陆逻辑
  123. */
  124. const loginEvent = () => {
  125. // console.log("新的登陆逻辑 form", form);
  126. if (form.username == null || form.username == undefined || form.username == '') {
  127. ElMessage({ message: '账号必须填写', type: 'warning', });
  128. return;
  129. }
  130. if (form.password == null || form.password == undefined || form.password == '') {
  131. ElMessage({ message: '密码必须填写', type: 'warning', });
  132. return;
  133. }
  134. loginApi(form).then((res) => {
  135. if (res.data.data.token) {
  136. userInfo.setToken(res.data.data.token, 'auth');
  137. const userType = res.data.data.userType;
  138. getCurrentUser().then((res) => {
  139. userInfo.dataFill(Object.assign({ userType: userType }, res.data.data));
  140. // // 老师
  141. // if (userType == 0) router.push({ path: '/TaskMng' });
  142. // // 学生
  143. // else if (userType == 1) router.push({ path: '/studentMain' });
  144. // else {
  145. // ElNotification({
  146. // message: '无效用户',
  147. // type: 'info',
  148. // });
  149. // }
  150. mainToMaxEvent(function() {
  151. // 老师
  152. if (userType == 0) router.push({ path: '/TaskMng' });
  153. // 学生
  154. else if (userType == 1) router.push({ path: '/studentMain' });
  155. else {
  156. ElNotification({
  157. message: '无效用户',
  158. type: 'info',
  159. });
  160. }
  161. });
  162. });
  163. }
  164. });
  165. }
  166. /**
  167. * 桌面应用窗口最大化
  168. * callback
  169. */
  170. const mainToMaxEvent = (callback : any) => {
  171. fetch('http://127.0.0.1:' + window["mainToMaxPort"] + '/mainToMax')
  172. .then(response => {
  173. if (!response.ok) {
  174. throw new Error(`请求失败:${response.status} ${response.statusText}`);
  175. }
  176. return response.json(); // 若返回文本,用 response.text()
  177. })
  178. .then(data => {
  179. // console.log('获取到的数据:', data);
  180. // 这里写业务逻辑(如渲染页面)
  181. callback('yes');
  182. })
  183. .catch(error => {
  184. // console.error('请求出错:', error.message);
  185. callback('yes');
  186. });
  187. }
  188. const regularPassword = (val: string) => {
  189. if (/^[a-zA-Z0-9_@]{6,32}$/.test(val)) return true;
  190. return false;
  191. };
  192. onMounted(() => {
  193. nextTick(() => focusInput());
  194. });
  195. </script>
  196. <style lang="scss" scoped>
  197. // $proportion : 0.7;
  198. $proportion : 1;
  199. .newInput {
  200. /* 移除默认外观 */
  201. -webkit-appearance: none;
  202. -moz-appearance: none;
  203. appearance: none;
  204. /* 移除边框和轮廓 */
  205. border: none;
  206. outline: none;
  207. /* 移除默认内边距 */
  208. padding: 0;
  209. /* 继承字体样式 */
  210. font-family: inherit;
  211. font-size: inherit;
  212. line-height: inherit;
  213. /* 背景透明 */
  214. background: transparent;
  215. }
  216. .newInput::placeholder {
  217. color: #49608C;
  218. }
  219. .loginExe {
  220. box-sizing:border-box;
  221. -moz-box-sizing:border-box; /* Firefox */
  222. -webkit-box-sizing:border-box; /* Safari */
  223. -moz-user-select: none;
  224. -webkit-user-select: none;
  225. -ms-user-select: none;
  226. -khtml-user-select: none;
  227. user-select: none;
  228. }
  229. .loginExe {
  230. position: fixed;
  231. width: 100%;
  232. height: 100%;
  233. top: 0px;
  234. left: 0px;
  235. background-color: #092661;
  236. .main {
  237. position: fixed;
  238. width: 137.14rem * $proportion;
  239. height: 81.14rem * $proportion;
  240. top: 50%;
  241. left: 50%;
  242. margin: -40.57rem * $proportion 0px 0px -68.57rem * $proportion;
  243. background-image: url("../assets/exeLogin/bg.webp");
  244. -webkit-background-size: 100% 100%;
  245. -moz-background-size: 100% 100%;
  246. -o-background-size: 100% 100%;
  247. background-size: 100% 100%;
  248. background-position: center center;
  249. .title {
  250. position: absolute;
  251. top: 2.25rem * $proportion;
  252. left: 0px;
  253. width: 100%;
  254. text-align: center;
  255. font-size: 4rem * $proportion;
  256. font-weight: 700;
  257. color: #f0fffe;
  258. }
  259. .left {
  260. position: absolute;
  261. width: 46;
  262. top: 15.85rem * $proportion;
  263. left: 19.85rem * $proportion;
  264. .title2 {
  265. width: 100%;
  266. text-align: center;
  267. font-weight: 500;
  268. font-size: 5.35rem * $proportion;
  269. color: #F0F5FD;
  270. }
  271. .title3 {
  272. width: 100%;
  273. text-align: center;
  274. font-weight: 400;
  275. font-size: 3.57rem * $proportion;
  276. color: #F0F5FD;
  277. margin: 2.64rem * $proportion 0px 2.64rem * $proportion 0px;
  278. /* 设置渐变背景,从左到右 */
  279. background: linear-gradient(to right, #6A9EFF, #4ecdc4, #7DDBFA);
  280. /* 将背景裁剪到文字区域 */
  281. -webkit-background-clip: text;
  282. background-clip: text;
  283. /* 使文字颜色透明,显示背景渐变 */
  284. -webkit-text-fill-color: transparent;
  285. text-fill-color: transparent;
  286. }
  287. .edit {
  288. position: relative;
  289. width: 100%;
  290. height: 5.71rem * $proportion;
  291. border: 1px solid #71CBF2;
  292. margin: 3.92rem * $proportion 0px 3.92rem * $proportion 0px;
  293. background-color: #ffffff;
  294. .editLeft, .editRight {
  295. position: absolute;
  296. }
  297. .editLeft {
  298. width: 2.78rem * $proportion;
  299. left: 2.14rem * $proportion;
  300. top: 1.57rem * $proportion;
  301. }
  302. .editRight {
  303. left: 6.71rem * $proportion;
  304. top: 0px;
  305. bottom: 0px;
  306. right: 0px;
  307. font-weight: 400;
  308. font-size: 2.5rem * $proportion;
  309. color: #49608C;
  310. }
  311. }
  312. .btnSubmit {
  313. position: relative;
  314. width: 100%;
  315. height: 6.21rem * $proportion;
  316. cursor:pointer;
  317. .btnImg {
  318. position: absolute;
  319. top: -166%;
  320. left: -40%;
  321. width: 180%;
  322. // 穿透点击
  323. pointer-events: none;
  324. }
  325. .btnTxt {
  326. position: absolute;
  327. width: 100%;
  328. height: 100%;
  329. top: 0px;
  330. left: 0px;
  331. z-index: 1;
  332. text-align: center;
  333. font-weight: 500;
  334. font-size: 3.14rem * $proportion;
  335. color: #FFFFFF;
  336. letter-spacing: 7px;
  337. text-shadow: 0px 3px 7px rgba(39,63,121,0.25);
  338. line-height: 6.21rem * $proportion;
  339. }
  340. }
  341. }
  342. }
  343. }
  344. </style>