瀏覽代碼

新增登录页

mxd 3 年之前
父節點
當前提交
261506985c

二進制
src/assets/PoetsenOne.woff2


+ 7 - 0
src/assets/index.css

@@ -4,6 +4,13 @@
   font-weight: 100;
   font-style: normal;
 }
+@font-face {
+  font-family: PoetsenOne;
+  src: url(PoetsenOne.woff2) format('woff2');
+  font-weight: 100;
+  font-style: normal;
+}
+
 .magic-editor {
   width: 100%;
   height: 100%;

+ 193 - 0
src/assets/login-bg.svg

@@ -0,0 +1,193 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" preserveAspectRatio="xMidYMid" viewBox="0 0 1920 1080">
+<g transform="translate(960,540) scale(1,-1) translate(-960,-540)"><path id="path0" d="M 1349.9098887622815 185.16915627008808
+c 0 26.590437311255734 -6.5061708314774656 7.6376788021692 -14.143849633646665 7.6376788021692
+S 1321.6221894949883 211.7595935813438 1321.6221894949883 185.16915627008808
+s 6.5061708314774656 -7.6376788021692 14.143849633646665 -7.6376788021692
+S 1349.9098887622815 158.57871895883235 1349.9098887622815 185.16915627008808
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="14.632267999638175" fill="#ff708e">
+  <animateMotion begin="-11.590466641060427s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path0"></mpath>
+  </animateMotion>
+</circle><path id="path1" d="M 1299.6932195239785 317.12638037505536
+c 0 34.821134259509634 -8.520064765624698 10.001815159646386 -18.521879925271083 10.001815159646386
+S 1262.6494596734362 351.947514634565 1262.6494596734362 317.12638037505536
+s 8.520064765624698 -10.001815159646386 18.521879925271083 -10.001815159646386
+S 1299.6932195239785 282.30524611554574 1299.6932195239785 317.12638037505536
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="17.30792014672236" fill="#de9dd6">
+  <animateMotion begin="-8.95589724484751s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path1"></mpath>
+  </animateMotion>
+</circle><path id="path2" d="M 111.25272199046691 375.8719982330086
+c 0 28.024935326008073 -6.8571650265764434 8.049715465981043 -14.906880492557486 8.049715465981043
+S 81.43896100535193 403.89693355901665 81.43896100535193 375.8719982330086
+s 6.8571650265764434 -8.049715465981043 14.906880492557486 -8.049715465981043
+S 111.25272199046691 347.8470629070005 111.25272199046691 375.8719982330086
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="12.669302833148285" fill="#e0ff77">
+  <animateMotion begin="-5.565159510466704s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path2"></mpath>
+  </animateMotion>
+</circle><path id="path3" d="M 1504.755000906474 640.8630363818409
+c 0 33.780400040902855 -8.26541703128474 9.702880862812522 -17.96829789409726 9.702880862812522
+S 1468.8184051182793 674.6434364227437 1468.8184051182793 640.8630363818409
+s 8.26541703128474 -9.702880862812522 17.96829789409726 -9.702880862812522
+S 1504.755000906474 607.082636340938 1504.755000906474 640.8630363818409
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="9.146958137129836" fill="#de9dd6">
+  <animateMotion begin="-14.752788268299275s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path3"></mpath>
+  </animateMotion>
+</circle><path id="path4" d="M 1438.7194047124874 900.4906795633224
+c 0 32.724571530537666 -8.00707601279113 9.399610971537415 -17.406686984328545 9.399610971537415
+S 1403.9060307438301 933.21525109386 1403.9060307438301 900.4906795633224
+s 8.00707601279113 -9.399610971537415 17.406686984328545 -9.399610971537415
+S 1438.7194047124874 867.7661080327847 1438.7194047124874 900.4906795633224
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="15.677317452896688" fill="#ff708e">
+  <animateMotion begin="-1.1425743261292354s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path4"></mpath>
+  </animateMotion>
+</circle><path id="path5" d="M 1377.8259677685908 190.2989727154286
+c 0 33.5014862564454 -8.197172169130257 9.622767328978998 -17.819939498109257 9.622767328978998
+S 1342.1860887723722 223.80045897187398 1342.1860887723722 190.2989727154286
+s 8.197172169130257 -9.622767328978998 17.819939498109257 -9.622767328978998
+S 1377.8259677685908 156.7974864589832 1377.8259677685908 190.2989727154286
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="10.545617900229804" fill="#51cacc">
+  <animateMotion begin="-9.925167277224837s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path5"></mpath>
+  </animateMotion>
+</circle><path id="path6" d="M 699.5619032555242 173.64339385556056
+c 0 22.890529496325936 -5.600874238462728 6.574939323412769 -12.175813561875497 6.574939323412769
+S 675.2102761317731 196.5339233518865 675.2102761317731 173.64339385556056
+s 5.600874238462728 -6.574939323412769 12.175813561875497 -6.574939323412769
+S 699.5619032555242 150.75286435923462 699.5619032555242 173.64339385556056
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="8.823697641429444" fill="#ff708e">
+  <animateMotion begin="-7.101400252511483s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path6"></mpath>
+  </animateMotion>
+</circle><path id="path7" d="M 1502.3184744544892 748.3256840717742
+c 0 29.56321240330199 -7.233551971020699 8.491561009459081 -15.72511298047978 8.491561009459081
+S 1470.8682484935298 777.8888964750762 1470.8682484935298 748.3256840717742
+s 7.233551971020699 -8.491561009459081 15.72511298047978 -8.491561009459081
+S 1502.3184744544892 718.7624716684721 1502.3184744544892 748.3256840717742
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="15.097313756793348" fill="#e0ff77">
+  <animateMotion begin="-16.2767664139038s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path7"></mpath>
+  </animateMotion>
+</circle><path id="path8" d="M 875.9912218633518 184.51950247788722
+c 0 36.37142976127214 -8.899392388396373 10.447112803769658 -19.34650519216603 10.447112803769658
+S 837.2982114790199 220.89093223915935 837.2982114790199 184.51950247788722
+s 8.899392388396373 -10.447112803769658 19.34650519216603 -10.447112803769658
+S 875.9912218633518 148.14807271661508 875.9912218633518 184.51950247788722
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="17.19104452482677" fill="#51cacc">
+  <animateMotion begin="-1.8652637198274213s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path8"></mpath>
+  </animateMotion>
+</circle><path id="path9" d="M 1479.2399634419357 61.33508696828571
+c 0 34.11872390217692 -8.348198401596479 9.800058993178476 -18.148257394774955 9.800058993178476
+S 1442.943448652386 95.45381087046263 1442.943448652386 61.33508696828571
+s 8.348198401596479 -9.800058993178476 18.148257394774955 -9.800058993178476
+S 1479.2399634419357 27.21636306610879 1479.2399634419357 61.33508696828571
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="15.855811877531224" fill="#9df871">
+  <animateMotion begin="-3.035988641499956s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path9"></mpath>
+  </animateMotion>
+</circle><path id="path10" d="M 571.4191895582195 191.5481744110148
+c 0 20.79300718126673 -5.087650693288667 5.972459509512785 -11.060110202801452 5.972459509512785
+S 549.2989691526167 212.34118159228154 549.2989691526167 191.5481744110148
+s 5.087650693288667 -5.972459509512785 11.060110202801452 -5.972459509512785
+S 571.4191895582195 170.75516722974805 571.4191895582195 191.5481744110148
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="16.72806401591559" fill="#ff708e">
+  <animateMotion begin="-1.7963849564032675s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path10"></mpath>
+  </animateMotion>
+</circle><path id="path11" d="M 105.18777938216608 104.43185429353139
+c 0 26.00935428319513 -6.36399094163285 7.470771974960303 -13.834762916593153 7.470771974960303
+S 77.51825354897979 130.44120857672652 77.51825354897979 104.43185429353139
+s 6.36399094163285 -7.470771974960303 13.834762916593153 -7.470771974960303
+S 105.18777938216608 78.42250001033625 105.18777938216608 104.43185429353139
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="16.44114740668901" fill="#51cacc">
+  <animateMotion begin="-3.6172728417846622s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path11"></mpath>
+  </animateMotion>
+</circle><path id="path12" d="M 53.5023681447867 1041.9723638812375
+c 0 22.600107101926067 -5.5298134398329735 6.491520125021317 -12.021333564854292 6.491520125021317
+S 29.459701015078114 1064.5724709831636 29.459701015078114 1041.9723638812375
+s 5.5298134398329735 -6.491520125021317 12.021333564854292 -6.491520125021317
+S 53.5023681447867 1019.3722567793114 53.5023681447867 1041.9723638812375
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="16.253802352244648" fill="#9df871">
+  <animateMotion begin="-2.2741458273148574s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path12"></mpath>
+  </animateMotion>
+</circle><path id="path13" d="M 1489.2513333213988 969.2237471962012
+c 0 21.52668839880468 -5.2671684380054 6.183197731571558 -11.450366169576958 6.183197731571558
+S 1466.350600982245 990.7504355950059 1466.350600982245 969.2237471962012
+s 5.2671684380054 -6.183197731571558 11.450366169576958 -6.183197731571558
+S 1489.2513333213988 947.6970587973965 1489.2513333213988 969.2237471962012
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="15.194742236185608" fill="#ff708e">
+  <animateMotion begin="-11.741976075373328s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path13"></mpath>
+  </animateMotion>
+</circle><path id="path14" d="M 1845.6473677110291 551.4828587242023
+c 0 22.591554773482507 -5.527720848830826 6.489063605149231 -12.016784453980057 6.489063605149231
+S 1821.613798803069 574.0744134976848 1821.613798803069 551.4828587242023
+s 5.527720848830826 -6.489063605149231 12.016784453980057 -6.489063605149231
+S 1845.6473677110291 528.8913039507198 1845.6473677110291 551.4828587242023
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="14.99698402981728" fill="#de9dd6">
+  <animateMotion begin="-18.600839623781276s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path14"></mpath>
+  </animateMotion>
+</circle><path id="path15" d="M 1922.0685155799683 945.9007213755189
+c 0 31.615027706616466 -7.735591885661475 9.080912213602602 -16.81650409926408 9.080912213602602
+S 1888.43550738144 977.5157490821354 1888.43550738144 945.9007213755189
+s 7.735591885661475 -9.080912213602602 16.81650409926408 -9.080912213602602
+S 1922.0685155799683 914.2856936689024 1922.0685155799683 945.9007213755189
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="8.827700721901026" fill="#9df871">
+  <animateMotion begin="-19.16890602299407s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path15"></mpath>
+  </animateMotion>
+</circle><path id="path16" d="M 100.86860223361062 27.378621310533717
+c 0 34.76624257836834 -8.50663382236672 9.98604840016963 -18.49268222253635 9.98604840016963
+S 63.883237788537926 62.14486388890206 63.883237788537926 27.378621310533717
+s 8.50663382236672 -9.98604840016963 18.49268222253635 -9.98604840016963
+S 100.86860223361062 -7.387621267834625 100.86860223361062 27.378621310533717
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="16.13956668595096" fill="#ff708e">
+  <animateMotion begin="-2.2692229534473984s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path16"></mpath>
+  </animateMotion>
+</circle><path id="path17" d="M 1178.9411193810608 445.72324429352415
+c 0 30.400067965806628 -7.438314502271834 8.731934415710414 -16.17024891798225 8.731934415710414
+S 1146.6006215450964 476.12331225933076 1146.6006215450964 445.72324429352415
+s 7.438314502271834 -8.731934415710414 16.17024891798225 -8.731934415710414
+S 1178.9411193810608 415.32317632771753 1178.9411193810608 445.72324429352415
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="15.357762329732441" fill="#51cacc">
+  <animateMotion begin="-10.157359703650904s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path17"></mpath>
+  </animateMotion>
+</circle><path id="path18" d="M 673.5817480982976 183.535715578992
+c 0 25.221915941567396 -6.171319858043086 7.244592876833188 -13.415912734876274 7.244592876833188
+S 646.7499226285449 208.7576315205594 646.7499226285449 183.535715578992
+s 6.171319858043086 -7.244592876833188 13.415912734876274 -7.244592876833188
+S 673.5817480982976 158.3137996374246 673.5817480982976 183.535715578992
+z" fill="none" stroke="none"></path>
+<circle cx="0" cy="0" r="9.556473475843394" fill="#51cacc">
+  <animateMotion begin="-0.8141051610736438s" dur="20s" repeatCount="indefinite">
+    <mpath xlink:href="#path18"></mpath>
+  </animateMotion>
+</circle></g>
+</svg>

二進制
src/assets/logo-magic-api.png


+ 6 - 1
src/components/common/form/magic-input.vue

@@ -1,6 +1,7 @@
 <template>
 	<input class="magic-input" :class="{'magic-input__border': border}" :value="value" :placeholder="placeholder" :readonly="readonly" :style="style" :type="type"
-		   @input="e => $emit('update:value', e.target.value)" :autocomplete="autocomplete"/>
+		   @input="e => $emit('update:value', e.target.value)" :autocomplete="autocomplete"
+		   @keypress.enter.stop="onEnter"/>
 </template>
 <script setup>
 import { computed } from "@vue/reactivity"
@@ -24,6 +25,10 @@ const props = defineProps({
 	border: {
 		type: Boolean,
 		default: true
+	},
+	onEnter: {
+		type: Function,
+		default: () => {}
 	}
 })
 const autocomplete = computed(() => props.type === 'password' ? 'new-password' : null)

+ 29 - 26
src/components/magic-editor.vue

@@ -1,14 +1,15 @@
 <template>
     <div class="magic-editor" :style="themeStyle" @contextmenu.prevent="" ref="root">
-        <!-- 顶部区域 -->
-        <magic-header :themeStyle="themeStyle" v-if="loadFinish"/>
-        <magic-main ref="componentMain" @onLoad="init" v-if="loadFinish"/>
-        <!-- 状态条 -->
-        <magic-status-bar :config="config" v-if="loadFinish" />
-		<magic-login v-model:value="showLogin" v-if="loadFinish"/>
+		<magic-login v-show="showLogin" v-model:value="showLogin" v-model:error="errorMessage"/>
+		<!-- 顶部区域 -->
+		<magic-header :themeStyle="themeStyle" v-if="loadFinish"/>
+		<magic-main ref="componentMain" @onLoad="init" v-if="loadFinish"/>
+		<!-- 状态条 -->
+		<magic-status-bar :config="config" v-if="loadFinish"/>
+
 		<!-- 消息通知区域 -->
-		<magic-notify v-if="loadFinish" />
-        <div class="magic-mounts"></div>
+		<magic-notify v-if="loadFinish"/>
+		<div class="magic-mounts"></div>
     </div>
 </template>
 <script setup>
@@ -30,7 +31,6 @@ import Message from '../scripts/constants/message.js'
 import { loadPlugin, randomString, replaceURL } from '../scripts/utils.js'
 import store from '../scripts/store.js'
 import * as monaco from 'monaco-editor'
-import modal from './common/dialog/magic-modal.js'
 import { default as $i, add as i18nAdd} from '../scripts/i18n.js'
 initializeMagicScript()
 provide('bus', bus)
@@ -53,6 +53,7 @@ const showLogin = ref(false)
 const componentMain = ref(null)
 const root = ref(null)
 const loadFinish = ref(false)
+const errorMessage = ref(null)
 provide('ELEMENT_ROOT', root)
 provide('activateUserFiles', ref({}))
 let websocket = null
@@ -104,7 +105,6 @@ Promise.all([JavaClass.initClasses(), JavaClass.initImportClass(), installPlugin
 		}
 	})
 	loadFinish.value = true
-	hideLoadingElement()
 })
 const options = props.config.options || []
 provide('options', options)
@@ -153,15 +153,18 @@ const checkUpdate = () => {
 		})
 }
 const autoLogin = () => {
-	constants.HEADER_MAGIC_TOKEN_VALUE = store.get(constants.STORE.token) || constants.HEADER_MAGIC_TOKEN_VALUE
-	bus.status('message.tryAutoLogin')
-	request.sendPost('/login').success(isLogin => {
-		if(isLogin){
-			bus.status('message.autoLoginSuccess')
-			bus.$emit(Message.LOGINED)
-		} else {
-			showLogin.value = true
-		}
+	return new Promise(resolve => {
+		constants.HEADER_MAGIC_TOKEN_VALUE = store.get(constants.STORE.token) || constants.HEADER_MAGIC_TOKEN_VALUE
+		bus.status('message.tryAutoLogin')
+		request.sendPost('/login').success(isLogin => {
+			showLogin.value = !isLogin
+			if(isLogin){
+				nextTick(() => {
+					bus.status('message.autoLoginSuccess')
+					bus.$emit(Message.LOGINED)
+				})
+			}
+		}).end(resolve)
 	})
 }
 const hideLoadingElement = () => {
@@ -185,16 +188,16 @@ const init = () => {
 				content: $i('message.versionConflict', constants.MAGIC_API_VERSION_TEXT, constants.config.version)
 			})
 		}
-		hideLoadingElement()
-		autoLogin()
-		if(props.config.checkUpdate !== false) {
-			checkUpdate()
-		}
+		autoLogin().then(() => {
+			hideLoadingElement()
+			if(props.config.checkUpdate !== false) {
+				checkUpdate()
+			}
+		})
 	}).catch(e => {
 		console.error(e)
 		hideLoadingElement()
-		modal.alert($i('message.loadConfigError'), $i('message.tips'))
-		bus.status('message.loadConfigError', false)
+		errorMessage.value = $i('message.loadConfigError')
 	})
 }
 // 快捷键处理

+ 164 - 16
src/components/panel/main/magic-login.vue

@@ -1,17 +1,23 @@
 <template>
-    <magic-dialog :title="$i('message.login')" :showClose="false" v-model:value="value" >
-        <div class="magic-login">
-            <label>{{ $i('message.username') }}:</label>
-            <magic-input :onEnter="doLogin" v-model:value="username"/>
-            <div style="height: 2px"/>
-            <label>{{ $i('message.password') }}:</label>
-            <magic-input :onEnter="doLogin"  v-model:value="password" type="password"/>
-            <div style="height: 2px"/>
+    <div class="magic-login">
+        <div class="magic-login-box">
+            <div class="magic-login-logo"></div>
+            <div class="magic-login-text">Magic-API <span v-if="constants.MAGIC_API_VERSION_TEXT">v{{constants.MAGIC_API_VERSION_TEXT}}</span></div>
+            <div class="magic-login-row error" v-if="error"><magic-icon icon="error"/><span>{{ error }}</span></div>
+            <div class="magic-login-row">
+                <magic-icon icon="user"/>
+                <magic-input :onEnter="doLogin" v-model:value="username" :placeholder="$i('message.username')"/>
+            </div>
+            <div class="magic-login-row">
+                <magic-icon icon="password"/>
+                <magic-input :onEnter="doLogin"  v-model:value="password" type="password" :placeholder="$i('message.password')"/>
+            </div>
+            <div class="magic-login-row">
+                <magic-button :value="$i('message.login')" @onClick="doLogin"/>
+            </div>
         </div>
-        <magic-button-group align="center">
-            <magic-button :value="$i('message.login')" @onClick="doLogin"/>
-        </magic-button-group>
-    </magic-dialog>
+        <div class="magic-login-copyright">Copyright © 2020-{{new Date().getYear() + 1900}} <a href="https://ssssssss.org.cn" target="_blank">ssssssss.org.cn</a> All rights reserved.</div>
+    </div>
 </template>
 <script setup>
 import { ref } from 'vue'
@@ -22,19 +28,39 @@ import Message from '../../../scripts/constants/message.js'
 import request from '../../../scripts/request.js'
 import store from '../../../scripts/store.js'
 defineProps({
-    value: Boolean
+    value: Boolean,
+    error: String
 })
 const username = ref('')
 const password = ref('')
-const emit = defineEmits(['update:value'])
+const emit = defineEmits(['update:value', 'update:error'])
+bus.$on()
 const doLogin = () => {
     if(username.value && password.value){
+        emit('update:error', null)
         request.sendPost('/login', { username: username.value, password: password.value }).success((successed, response) => {
             if(successed){
                 emit('update:value', false)
                 constants.HEADER_MAGIC_TOKEN_VALUE = response.headers[constants.HEADER_MAGIC_TOKEN]
                 store.set(constants.STORE.token, constants.HEADER_MAGIC_TOKEN_VALUE)
                 bus.$emit(Message.LOGINED)
+                username.value = ''
+                password.value = ''
+            }
+        }).exception((code, message) => {
+            if(code != 401){
+                message = translateCode(code, message)
+            }
+            emit('update:error', message)
+        }).error((_code, _message, error) => {
+            if(error){
+                let message = ''
+                if (error.response) {
+                    message = JSON.stringify(error.response.data || '') || $i('code.invalid', error.response.status)
+                } else {
+                    message = error.message
+                }
+                emit('update:error', message)
             }
         })
     }
@@ -46,7 +72,129 @@ label {
   text-align: right;
   display: inline-block;
 }
-.magic-login :deep(.magic-input){
-    width: auto !important;
+.magic-login{
+    position: fixed;
+    z-index: 999999999999;
+    background: #fff;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-image: url(../../../assets/login-bg.svg);
+}
+.magic-login .magic-login-box{
+    border-radius: 5px;
+    width: 450px;
+    box-shadow: 0 7px 25px rgba(0,0,0,.08);
+    position: absolute;
+    box-sizing: border-box;
+    padding-top:60px;
+    top:33.333333%;
+    margin-top: -125px;
+    background-color: #fff;
+}
+.magic-login-logo{
+    background-image: url(../../../assets/logo-magic-api.png);
+    width: 128px;
+    height: 128px;
+    background-size: 90px 90px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    position: absolute;
+    top: -64px;
+    left: 50%;
+    margin-left: -64px;
+    border-radius: 64px;
+    box-shadow: 0 0 20px 5px rgba(0,0,0,.08);
+    padding: 10px;
+    background-color: #fff;
+}
+.magic-login-text{
+    height: 70px;
+    line-height: 70px;
+    display: block;
+    text-align: center;
+    font-family: PoetsenOne;
+    font-size: 28px;
+    color: #808080;
+}
+.magic-login-text span{
+    font-size: 16px;
+}
+.magic-login-copyright{
+    text-align: center;
+    color: #999;
+    font-size: 18px;
+    font-family: Avenir,Helvetica,Arial,sans-serif;
+    position: absolute;
+    bottom: 50px;
+}
+.magic-login-copyright a{
+    text-decoration: none;
+    color: #2196f3;
+    outline: 0;
+}
+.magic-login-row{
+    width: 400px;
+    margin:25px auto;
+    position: relative;
+}
+.magic-login-row.error{
+    background-color: #fff1f0;
+    border: 1px solid #ffa39e;
+    color: #000;
+    border-radius: 4px;
+    padding:10px 0;
+    padding-left: 40px;
+}
+.magic-login-row.error span{
+    font-size: 14px;
+    word-break: break-all;
+}
+.magic-login-row svg{
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    top: 15px;
+    left: 15px;
+}
+.magic-login-row :deep(.magic-icon-error){
+    fill: red;
+}
+.magic-login-box .magic-input{
+    height: 50px;
+    line-height: 50px;
+    background-color: transparent;
+    display: block;
+    border: 1px solid #D9D9D9;
+    border-radius: 4px;
+    padding-left: 40px;
+    color: rgba(0,0,0,.65);
+    transition: all .3s;
+    font-size: 16px;
+}
+.magic-login-box .magic-input:focus{
+    border-color:#0784de;
+}
+.magic-login-box .magic-button{
+    width: 100%;
+    height: 50px;
+    line-height: 50px;
+    background-color: #2196f3;
+    color: #fff;
+    border-radius: 4px;
+    font-size: 18px;
+    border-color: #2196f3;
+    transition: all .3s;
+}
+.magic-login-box .magic-button:hover,
+.magic-login-box .magic-button:focus{
+    background-color: #4db5ff !important;
+    border-color: #4db5ff !important;
+}
+.magic-login-box .magic-button:active{
+    background-color: #1272cc;
+    border-color: #1272cc;
 }
 </style>

+ 3 - 3
src/scripts/request.js

@@ -110,7 +110,7 @@ class HttpRequest {
 
 	processError(error) {
 		if (error.response) {
-			modal.alert(JSON.stringify(error.response.data || '') || $i('code.invalid', error.response.status), $i('code.invalid', error.response.status))
+			modal.alert(JSON.stringify(error.response?.data || '') || $i('code.invalid', error.response?.status), $i('code.invalid', error.response?.status))
 		} else {
 			modal.alert(error.message, $i('code.httpError'))
 		}
@@ -184,7 +184,7 @@ class HttpRequest {
 			})
 			.catch((error) => {
 				if (typeof httpResponse.errorHandle === 'function') {
-					httpResponse.errorHandle(error.response.data, error.response, error)
+					httpResponse.errorHandle(error.response?.data, error.response, error)
 				} else {
 					this.processError(error)
 
@@ -199,4 +199,4 @@ class HttpRequest {
 	}
 }
 
-export default new HttpRequest()
+export default new HttpRequest()