登录页面添加

This commit is contained in:
zhangyiming 2020-12-04 14:28:25 +08:00
parent a647a16b92
commit 10ba75b1b6
19 changed files with 246 additions and 144 deletions

View File

@ -18,16 +18,6 @@ npm run serve
npm run build npm run build
``` ```
## Run your unit tests
```
npm run test:unit
```
## Run your end-to-end tests
```
npm run test:e2e
```
## Lints and fixes files ## Lints and fixes files
``` ```
npm run lint npm run lint

6
package-lock.json generated
View File

@ -2689,9 +2689,9 @@
"dev": true "dev": true
}, },
"element-plus": { "element-plus": {
"version": "1.0.1-beta.2", "version": "1.0.1-beta.3",
"resolved": "http://192.168.250.101:4873/element-plus/-/element-plus-1.0.1-beta.2.tgz", "resolved": "http://192.168.250.101:4873/element-plus/-/element-plus-1.0.1-beta.3.tgz",
"integrity": "sha1-CmoQ3BU+5KTsVHdbrSKmhT6uYzc=", "integrity": "sha1-lF1Xh4I+ikR1G5AbGxqUrS1If18=",
"requires": { "requires": {
"@popperjs/core": "^2.4.4", "@popperjs/core": "^2.4.4",
"async-validator": "^3.4.0", "async-validator": "^3.4.0",

View File

@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"await-to-js": "^2.1.1", "await-to-js": "^2.1.1",
"axios": "^0.21.0", "axios": "^0.21.0",
"element-plus": "^1.0.1-beta.2", "element-plus": "^1.0.1-beta.3",
"vue": "^3.0.4", "vue": "^3.0.4",
"vue-class-component": "^8.0.0-rc.1", "vue-class-component": "^8.0.0-rc.1",
"vue-router": "^4.0.0-rc.6", "vue-router": "^4.0.0-rc.6",

View File

@ -1,3 +1,3 @@
<template> <template>
<router-view/> <router-view />
</template> </template>

View File

@ -1,3 +0,0 @@
import EnclosureHttp from "./utils/core";
export default EnclosureHttp;

View File

@ -10,6 +10,17 @@ body {
position: relative; position: relative;
} }
* {
touch-action: pan-y;
-moz-user-select: none;
-o-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.login, .login,
.register { .register {
width: 100%; width: 100%;

View File

@ -1,44 +1,115 @@
<template> <template>
<div class="info"> <div class="info">
<!-- <input type="text" /><br /> <el-form :model="ruleForm" ref="ruleForm" class="rule-form">
<input type="text" /><br /> <el-form-item prop="userName">
<button>1</button> --> <el-input
<p>{{ info.userName }}</p> clearable
<p>{{ info.passWord }}</p> v-model="ruleForm.userName"
<p>{{ info.dynamicText }}</p> placeholder="请输入用户名"
prefix-icon="el-icon-user"
></el-input>
</el-form-item>
<el-form-item prop="passWord">
<el-input
clearable
v-model="ruleForm.passWord"
placeholder="请输入密码"
prefix-icon="el-icon-lock"
></el-input>
</el-form-item>
<el-form-item prop="verify">
<el-input
v-model="ruleForm.verify"
placeholder="请输入验证码"
></el-input>
<span
class="verify"
title="刷新"
v-html="ruleForm.svg"
@click.prevent="refreshVerify"
></span>
</el-form-item>
<el-form-item>
<el-button type="primary" @click.prevent="onLogin">登录</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div> </div>
</template> </template>
<script lang='ts'> <script lang='ts'>
import { defineComponent, PropType } from "vue"; import {
defineComponent,
PropType,
onBeforeMount,
getCurrentInstance,
} from "vue";
export interface ContextProps { export interface ContextProps {
userName: string; userName: string;
passWord: string; passWord: string;
verify?: number; verify: number | null;
svg: any;
telephone?: number; telephone?: number;
dynamicText: string; dynamicText?: string;
} }
export default defineComponent({ export default defineComponent({
props: { props: {
info: { ruleForm: {
type: Object as PropType<ContextProps>, type: Object as PropType<ContextProps>,
require: true, require: true,
}, },
}, },
emits: ["onLogin", "refreshVerify"],
setup(props, ctx) {
let vm: any;
onBeforeMount(() => {
vm = getCurrentInstance(); //
});
//
const onLogin = (evt: Object): void => {
ctx.emit("onLogin", evt);
};
//
const refreshVerify = (): void => {
ctx.emit("refreshVerify");
};
//
const resetForm = (): void => {
vm.refs.ruleForm.resetFields();
};
return { resetForm, onLogin, refreshVerify };
},
}); });
</script> </script>
<style scoped> <style lang="scss" scoped>
.info { .info {
width: 30vw; width: 30vw;
height: 40vh; height: 48vh;
background: url("./login.png") no-repeat center; background: url("./login.png") no-repeat center;
background-size: cover; background-size: cover;
position: absolute; position: absolute;
border-radius: 20px; border-radius: 20px;
right: 100px; right: 100px;
top: 35vh; top: 30vh;
display: flex;
justify-content: center;
align-items: center;
.rule-form {
width: 80%;
.verify {
position: absolute;
margin: -10px 0 0 -120px;
&:hover {
cursor: pointer;
}
}
}
} }
</style> </style>

View File

@ -2,7 +2,7 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import store from './store' import store from './store'
import EnclosureHttp from "./api/utils/core" // import EnclosureHttp from "./utils/http"
// 内置ElementPlus // 内置ElementPlus
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
@ -14,6 +14,6 @@ import "./assets/index.css"
const app = createApp(App) const app = createApp(App)
// 全局注册Axios // 全局注册Axios
app.config.globalProperties.$http = new EnclosureHttp() // app.config.globalProperties.$http = new EnclosureHttp()
app.use(store).use(router).use(ElementPlus).mount('#app') app.use(store).use(router).use(ElementPlus).mount('#app')

View File

@ -1,5 +1,5 @@
import { AxiosRequestConfig } from "axios"; import { AxiosRequestConfig } from "axios"
import { excludeProps } from "./utils"; import { excludeProps } from "./utils"
/** /**
* *
*/ */
@ -11,21 +11,21 @@ export const defaultConfig: AxiosRequestConfig = {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest" "X-Requested-With": "XMLHttpRequest"
}, },
}; }
export function genConfig(config?: AxiosRequestConfig): AxiosRequestConfig { export function genConfig(config?: AxiosRequestConfig): AxiosRequestConfig {
if (!config) { if (!config) {
return defaultConfig; return defaultConfig
} }
const { headers } = config; const { headers } = config
if (headers && typeof headers === "object") { if (headers && typeof headers === "object") {
defaultConfig.headers = { defaultConfig.headers = {
...defaultConfig.headers, ...defaultConfig.headers,
...headers ...headers
}; }
} }
return { ...excludeProps(config!, "headers"), ...defaultConfig }; return { ...excludeProps(config!, "headers"), ...defaultConfig }
} }
export const METHODS = ["post", "get", "put", "delete", "option", "patch"]; export const METHODS = ["post", "get", "put", "delete", "option", "patch"]

View File

@ -3,11 +3,11 @@ import Axios, {
CancelTokenStatic, CancelTokenStatic,
AxiosInstance, AxiosInstance,
Canceler Canceler
} from "axios"; } from "axios"
import { genConfig } from "./config"; import { genConfig } from "./config"
import { transformConfigByMethod } from "./utils"; import { transformConfigByMethod } from "./utils"
import { import {
cancelTokenType, cancelTokenType,
@ -15,17 +15,17 @@ import {
EnclosureHttpRequestConfig, EnclosureHttpRequestConfig,
EnclosureHttpResoponse, EnclosureHttpResoponse,
EnclosureHttpError EnclosureHttpError
} from "./types.d"; } from "./types.d"
class EnclosureHttp { class EnclosureHttp {
// 初始化配置对象 // 初始化配置对象
private static initConfig: EnclosureHttpRequestConfig = {}; private static initConfig: EnclosureHttpRequestConfig = {};
// 保存当前Axios实例对象 // 保存当前Axios实例对象
private static axiosInstance: AxiosInstance = Axios.create(genConfig()); private static axiosInstance: AxiosInstance = Axios.create(genConfig());
// 保存 EnclosureHttp实例 // 保存 EnclosureHttp实例
private static EnclosureHttpInstance: EnclosureHttp; private static EnclosureHttpInstance: EnclosureHttp
// axios取消对象 // axios取消对象
private CancelToken: CancelTokenStatic = Axios.CancelToken; private CancelToken: CancelTokenStatic = Axios.CancelToken;
@ -41,12 +41,12 @@ class EnclosureHttp {
private beforeResponseCallback: EnclosureHttpRequestConfig["beforeResponseCallback"] = undefined; private beforeResponseCallback: EnclosureHttpRequestConfig["beforeResponseCallback"] = undefined;
public get cancelTokenList(): Array<cancelTokenType> { public get cancelTokenList(): Array<cancelTokenType> {
return this.sourceTokenList; return this.sourceTokenList
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
public set cancelTokenList(value) { public set cancelTokenList(value) {
throw new Error("cancelTokenList不允许赋值"); throw new Error("cancelTokenList不允许赋值")
} }
/** /**
@ -62,7 +62,7 @@ class EnclosureHttp {
*/ */
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
private genUniqueKey(config: EnclosureHttpRequestConfig): string { private genUniqueKey(config: EnclosureHttpRequestConfig): string {
return `${config.url}--${JSON.stringify(config.data)}`; return `${config.url}--${JSON.stringify(config.data)}`
} }
/** /**
@ -70,21 +70,21 @@ class EnclosureHttp {
* @returns void 0 * @returns void 0
*/ */
private cancelRepeatRequest(): void { private cancelRepeatRequest(): void {
const temp: { [key: string]: boolean } = {}; const temp: { [key: string]: boolean } = {}
this.sourceTokenList = this.sourceTokenList.reduce<Array<cancelTokenType>>( this.sourceTokenList = this.sourceTokenList.reduce<Array<cancelTokenType>>(
(res: Array<cancelTokenType>, cancelToken: cancelTokenType) => { (res: Array<cancelTokenType>, cancelToken: cancelTokenType) => {
const { cancelKey, cancelExecutor } = cancelToken; const { cancelKey, cancelExecutor } = cancelToken
if (!temp[cancelKey]) { if (!temp[cancelKey]) {
temp[cancelKey] = true; temp[cancelKey] = true
res.push(cancelToken); res.push(cancelToken)
} else { } else {
cancelExecutor(); cancelExecutor()
} }
return res; return res
}, },
[] []
); )
} }
/** /**
@ -97,7 +97,7 @@ class EnclosureHttp {
? this.sourceTokenList.filter( ? this.sourceTokenList.filter(
cancelToken => cancelToken.cancelKey !== cancelKey cancelToken => cancelToken.cancelKey !== cancelKey
) )
: []; : []
} }
/** /**
@ -108,33 +108,33 @@ class EnclosureHttp {
private httpInterceptorsRequest(): void { private httpInterceptorsRequest(): void {
EnclosureHttp.axiosInstance.interceptors.request.use( EnclosureHttp.axiosInstance.interceptors.request.use(
(config: EnclosureHttpRequestConfig) => { (config: EnclosureHttpRequestConfig) => {
const $config = config; const $config = config
const cancelKey = this.genUniqueKey($config); const cancelKey = this.genUniqueKey($config)
$config.cancelToken = new this.CancelToken((cancelExecutor: (cancel: any) => void) => { $config.cancelToken = new this.CancelToken((cancelExecutor: (cancel: any) => void) => {
this.sourceTokenList.push({ cancelKey, cancelExecutor }); this.sourceTokenList.push({ cancelKey, cancelExecutor })
}); })
this.cancelRepeatRequest(); this.cancelRepeatRequest()
this.currentCancelTokenKey = cancelKey; this.currentCancelTokenKey = cancelKey
// 优先判断post/get等方法是否传入回掉否则执行初始化设置等回掉 // 优先判断post/get等方法是否传入回掉否则执行初始化设置等回掉
if (typeof this.beforeRequestCallback === "function") { if (typeof this.beforeRequestCallback === "function") {
this.beforeRequestCallback($config); this.beforeRequestCallback($config)
this.beforeRequestCallback = undefined; this.beforeRequestCallback = undefined
return $config; return $config
} }
if (EnclosureHttp.initConfig.beforeRequestCallback) { if (EnclosureHttp.initConfig.beforeRequestCallback) {
EnclosureHttp.initConfig.beforeRequestCallback($config); EnclosureHttp.initConfig.beforeRequestCallback($config)
return $config; return $config
} }
return $config; return $config
}, },
error => { error => {
return Promise.reject(error); return Promise.reject(error)
} }
); )
} }
/** /**
@ -142,7 +142,7 @@ class EnclosureHttp {
* @returns void 0 * @returns void 0
*/ */
public clearCancelTokenList(): void { public clearCancelTokenList(): void {
this.sourceTokenList.length = 0; this.sourceTokenList.length = 0
} }
/** /**
@ -150,46 +150,46 @@ class EnclosureHttp {
* @returns void 0 * @returns void 0
*/ */
private httpInterceptorsResponse(): void { private httpInterceptorsResponse(): void {
const instance = EnclosureHttp.axiosInstance; const instance = EnclosureHttp.axiosInstance
instance.interceptors.response.use( instance.interceptors.response.use(
(response: EnclosureHttpResoponse) => { (response: EnclosureHttpResoponse) => {
// 请求每次成功一次就删除当前canceltoken标记 // 请求每次成功一次就删除当前canceltoken标记
const cancelKey = this.genUniqueKey(response.config); const cancelKey = this.genUniqueKey(response.config)
this.deleteCancelTokenByCancelKey(cancelKey); this.deleteCancelTokenByCancelKey(cancelKey)
// 优先判断post/get等方法是否传入回掉否则执行初始化设置等回掉 // 优先判断post/get等方法是否传入回掉否则执行初始化设置等回掉
if (typeof this.beforeResponseCallback === "function") { if (typeof this.beforeResponseCallback === "function") {
this.beforeResponseCallback(response); this.beforeResponseCallback(response)
this.beforeResponseCallback = undefined; this.beforeResponseCallback = undefined
return response.data; return response.data
} }
if (EnclosureHttp.initConfig.beforeResponseCallback) { if (EnclosureHttp.initConfig.beforeResponseCallback) {
EnclosureHttp.initConfig.beforeResponseCallback(response); EnclosureHttp.initConfig.beforeResponseCallback(response)
return response.data; return response.data
} }
return response.data; return response.data
}, },
(error: EnclosureHttpError) => { (error: EnclosureHttpError) => {
const $error = error; const $error = error
// 判断当前的请求中是否在 取消token数组理存在如果存在则移除单次请求流程 // 判断当前的请求中是否在 取消token数组理存在如果存在则移除单次请求流程
if (this.currentCancelTokenKey) { if (this.currentCancelTokenKey) {
const haskey = this.sourceTokenList.filter( const haskey = this.sourceTokenList.filter(
cancelToken => cancelToken.cancelKey === this.currentCancelTokenKey cancelToken => cancelToken.cancelKey === this.currentCancelTokenKey
).length; ).length
if (haskey) { if (haskey) {
this.sourceTokenList = this.sourceTokenList.filter( this.sourceTokenList = this.sourceTokenList.filter(
cancelToken => cancelToken =>
cancelToken.cancelKey !== this.currentCancelTokenKey cancelToken.cancelKey !== this.currentCancelTokenKey
); )
this.currentCancelTokenKey = ""; this.currentCancelTokenKey = ""
} }
} }
$error.isCancelRequest = Axios.isCancel($error); $error.isCancelRequest = Axios.isCancel($error)
// 所有的响应异常 区分来源为取消请求/非取消请求 // 所有的响应异常 区分来源为取消请求/非取消请求
return Promise.reject($error); return Promise.reject($error)
} }
); )
} }
public request<T>( public request<T>(
@ -202,24 +202,24 @@ class EnclosureHttp {
method, method,
url, url,
...axiosConfig ...axiosConfig
} as EnclosureHttpRequestConfig); } as EnclosureHttpRequestConfig)
// 单独处理自定义请求/响应回掉 // 单独处理自定义请求/响应回掉
if (axiosConfig?.beforeRequestCallback) { if (axiosConfig?.beforeRequestCallback) {
this.beforeRequestCallback = axiosConfig.beforeRequestCallback; this.beforeRequestCallback = axiosConfig.beforeRequestCallback
} }
if (axiosConfig?.beforeResponseCallback) { if (axiosConfig?.beforeResponseCallback) {
this.beforeResponseCallback = axiosConfig.beforeResponseCallback; this.beforeResponseCallback = axiosConfig.beforeResponseCallback
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
EnclosureHttp.axiosInstance.request(config) EnclosureHttp.axiosInstance.request(config)
.then((response: EnclosureHttpResoponse) => { .then((response: EnclosureHttpResoponse) => {
resolve(response.data); resolve(response.data)
}) })
.catch((error: any) => { .catch((error: any) => {
reject(error); reject(error)
}); })
}); })
} }
public post<T>( public post<T>(
@ -227,7 +227,7 @@ class EnclosureHttp {
params?: T, params?: T,
config?: EnclosureHttpRequestConfig config?: EnclosureHttpRequestConfig
): Promise<T> { ): Promise<T> {
return this.request<T>("post", url, params, config); return this.request<T>("post", url, params, config)
} }
public get<T>( public get<T>(
@ -235,9 +235,8 @@ class EnclosureHttp {
params?: T, params?: T,
config?: EnclosureHttpRequestConfig config?: EnclosureHttpRequestConfig
): Promise<T> { ): Promise<T> {
return this.request<T>("get", url, params, config); return this.request<T>("get", url, params, config)
} }
} }
export default EnclosureHttp; export default EnclosureHttp

3
src/utils/http/index.ts Normal file
View File

@ -0,0 +1,3 @@
import EnclosureHttp from "./core"
export const http = new EnclosureHttp()

View File

@ -4,7 +4,7 @@ import Axios, {
AxiosResponse, AxiosResponse,
Method, Method,
AxiosError AxiosError
} from "axios"; } from "axios"
import { METHODS } from './config' import { METHODS } from './config'

View File

@ -1,4 +1,4 @@
import { EnclosureHttpRequestConfig } from "./types.d"; import { EnclosureHttpRequestConfig } from "./types.d"
export function excludeProps<T extends { [key: string]: any }>( export function excludeProps<T extends { [key: string]: any }>(
origin: T, origin: T,
@ -7,23 +7,23 @@ export function excludeProps<T extends { [key: string]: any }>(
return Object.keys(origin) return Object.keys(origin)
.filter(key => !prop.includes(key)) .filter(key => !prop.includes(key))
.reduce((res, key) => { .reduce((res, key) => {
res[key] = origin[key]; res[key] = origin[key]
return res; return res
}, {} as { [key: string]: T }); }, {} as { [key: string]: T })
} }
export function transformConfigByMethod( export function transformConfigByMethod(
params: any, params: any,
config: EnclosureHttpRequestConfig config: EnclosureHttpRequestConfig
): EnclosureHttpRequestConfig { ): EnclosureHttpRequestConfig {
const { method } = config; const { method } = config
const props = ["delete", "get", "head", "options"].includes( const props = ["delete", "get", "head", "options"].includes(
method!.toLocaleLowerCase() method!.toLocaleLowerCase()
) )
? "params" ? "params"
: "data"; : "data"
return { return {
...config, ...config,
[props]: params [props]: params
}; }
} }

View File

@ -9,11 +9,11 @@ export function setToken(token: string): void {
// 取 // 取
export function getToken(): string { export function getToken(): string {
let token = sessionStorage.getItem("Token") && JSON.parse(sessionStorage.getItem("Token") || ""); let token = sessionStorage.getItem("Token") && JSON.parse(sessionStorage.getItem("Token") || "")
return token; return token
} }
// 删 // 删
export function delToken(): void { export function delToken(): void {
sessionStorage.removeItem("Token"); sessionStorage.removeItem("Token")
} }

View File

@ -1,3 +1,14 @@
<template> <template>
<div>Home</div> <div></div>
</template> </template>
<script lang='ts'>
export default {
setup() {
return {};
},
};
</script>
<style scoped>
</style>

View File

@ -1,32 +1,60 @@
<template> <template>
<div class="login"> <div class="login">
<info :info="contextInfo" /> <info
:ruleForm="contextInfo"
@on-login="onLogin"
@refreshVerify="refreshVerify"
/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref } from "vue"; import {
ref,
reactive,
onMounted,
onBeforeMount,
getCurrentInstance,
} from "vue";
import { http } from "../utils/http";
import info, { ContextProps } from "../components/info.vue"; import info, { ContextProps } from "../components/info.vue";
const contextInfo: ContextProps = {
userName: "admin",
passWord: "123456",
dynamicText: "登录",
};
export default { export default {
mounted() {
// @ts-ignore
this.$http.request("get", "/getApi");
},
components: { components: {
info, info,
}, },
setup() { setup() {
//
const getVerify = async () => {
let { svg } = await http.request("get", "/captcha");
contextInfo.svg = svg;
};
const contextInfo: ContextProps = reactive({
userName: "",
passWord: "",
verify: null,
svg: null,
});
//
const onLogin = (): void => {
console.log(contextInfo.userName);
};
const refreshVerify = (): void => {
getVerify();
};
onBeforeMount(() => {
getVerify();
});
return { return {
contextInfo, contextInfo,
onLogin,
refreshVerify,
}; };
}, },
}; };
</script> </script>
<style scoped>
</style>

View File

@ -1,21 +1,13 @@
<template> <template>
<div class="register">{{ text }}</div> <div></div>
</template> </template>
<script lang="ts"> <script lang='ts'>
import { ref } from "vue"
export default { export default {
mounted() {
// @ts-ignore
this.$http.request("get", "/getApi")
},
setup() { setup() {
const text = ref("register") return {};
return {
text,
}
}, },
} };
</script> </script>
<style scoped> <style scoped>

View File

@ -34,7 +34,7 @@
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue", "src/**/*.vue",
"tests/**/*.ts", "tests/**/*.ts",
"tests/**/*.tsx" "tests/**/*.tsx", "src/mixins/bus.js"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules"