封装message,统一处理http响应
This commit is contained in:
parent
7bf0b5fb7f
commit
4f70b83f54
@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build"
|
||||
"build": "vite build"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@ -17,6 +17,7 @@
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.10",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^3.2.4",
|
||||
|
@ -1,16 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<button @click="showMessage">显示消息</button>
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {ref} from "vue";
|
||||
|
||||
import message from "./components/message";
|
||||
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
setup() {
|
||||
return {}
|
||||
return {
|
||||
showMessage() {
|
||||
message.info('test display')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -13,7 +13,39 @@ body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, 'Source Han Sans SC', 'Microsoft YaHei', 'Microsoft YaHei UI', "Helvetica Neue", sans-serif;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.container{
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.message-wrapper {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #000000d9;
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5715;
|
||||
list-style: none;
|
||||
font-feature-settings: "tnum";
|
||||
position: fixed;
|
||||
top: 8px;
|
||||
left: 0;
|
||||
z-index: 1010;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
.message-notice {
|
||||
|
||||
padding: 8px;
|
||||
text-align: center
|
||||
}
|
||||
.message-notice-content {
|
||||
display: inline-block;
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
|
||||
pointer-events: all
|
||||
}
|
17
admin-fe/src/components/message/Toast.vue
Normal file
17
admin-fe/src/components/message/Toast.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="message-notice">
|
||||
<div class="message-notice-content">
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
message: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
23
admin-fe/src/components/message/index.ts
Normal file
23
admin-fe/src/components/message/index.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {createVNode, render} from 'vue'
|
||||
import Toast from './Toast.vue'
|
||||
|
||||
export const toast = (message: string) => {
|
||||
if (timer) clearTimeout(timer)
|
||||
let div = document.querySelector('.message-wrapper');
|
||||
if (!div) {
|
||||
div = document.createElement('div');
|
||||
div.classList.add("message-wrapper");
|
||||
document.body.append(div);
|
||||
}
|
||||
// TODO 完善多消息同时共存 - 主要时添加新的容器
|
||||
const messageNode = createVNode(Toast, {message})
|
||||
render(messageNode, div)
|
||||
// @ts-ignore
|
||||
timer = setTimeout(() => {
|
||||
div.removeChild(messageNode.el as Node)
|
||||
}, 3000)
|
||||
}
|
||||
let timer = 0;
|
||||
export default {
|
||||
toast,
|
||||
}
|
@ -2,7 +2,7 @@ import {createApp} from 'vue';
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import {httpConfig} from "./util/http";
|
||||
|
||||
import './assets/app.css'
|
||||
|
||||
httpConfig.baseURL = "http://localhost:8080"
|
||||
|
||||
|
4
admin-fe/src/service/types.d.ts
vendored
Normal file
4
admin-fe/src/service/types.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
type AdminLoginModel = {
|
||||
account: string
|
||||
token: string
|
||||
}
|
@ -1,7 +1,18 @@
|
||||
import {toast} from "../components/message";
|
||||
|
||||
export type HttpMethod = 'get' | 'post' | 'delete' | 'put'
|
||||
|
||||
export enum RequestDataContentType {
|
||||
JSON = 'application/json;charset=UTF-8',
|
||||
FORM = 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8',
|
||||
}
|
||||
|
||||
export const httpConfig = {
|
||||
baseURL: ''
|
||||
baseURL: '',
|
||||
globalErrorHandler: {
|
||||
1201: '请求参数不合法'
|
||||
}
|
||||
}
|
||||
export type ResponseModel<T> = {
|
||||
code: number
|
||||
@ -12,27 +23,80 @@ export type ResponseModel<T> = {
|
||||
|
||||
class Http {
|
||||
post<T>(url, data) {
|
||||
return this.request<T>(url, 'post', data)
|
||||
return this.request<T>(url, data)
|
||||
}
|
||||
|
||||
request<T>(url: string, method: HttpMethod, data: any = null) {
|
||||
return new Promise<ResponseModel<T>>((resolve, reject) => {
|
||||
get<T>(url, data = null) {
|
||||
return this.request<T>(url, data, 'get')
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /xxxx?a=1&b=2
|
||||
* NAME: value
|
||||
* NAME2: value
|
||||
* ....
|
||||
*
|
||||
* POSTDATA
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
* @param method
|
||||
* @param data
|
||||
*/
|
||||
request<T>(url: string, data: any = null, method: HttpMethod = 'post', type: 'normal' | 'form' = 'normal') {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
let contentType = RequestDataContentType.FORM;
|
||||
if (data) {
|
||||
if (type === 'form') {
|
||||
const form = new FormData();
|
||||
for (const key in data) {
|
||||
form.append(key, data[key]);
|
||||
}
|
||||
data = form; // 将data有{} => formData
|
||||
contentType = RequestDataContentType.FORM_DATA; // 由于使用formData
|
||||
method = 'post';
|
||||
} else if (method == 'post') {
|
||||
// 将数据对象 转成json
|
||||
data = JSON.stringify(data);
|
||||
contentType = RequestDataContentType.JSON;
|
||||
} else {
|
||||
// 装对象转成 key=value&key=value
|
||||
const params = [];
|
||||
for (const key in data) {
|
||||
params.push(`${key}=${data[key]}`);
|
||||
}
|
||||
data = params.join('&')
|
||||
}
|
||||
}
|
||||
|
||||
fetch(httpConfig.baseURL + url, {
|
||||
method,
|
||||
body: JSON.stringify(data),
|
||||
body: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
'Content-Type': contentType
|
||||
}
|
||||
})
|
||||
.then(res => res.json()) // 只要json的响应数据
|
||||
.then((res: ResponseModel<T>) => {
|
||||
if (res.code !== 0) {
|
||||
const {code, data, message} = res;
|
||||
if (code !== 0) {
|
||||
const err = httpConfig.globalErrorHandler[code]
|
||||
// 需要统一处理数据
|
||||
if (code === 403) {
|
||||
toast("登录凭证无效或者已过期")
|
||||
return;
|
||||
} else if (err) {
|
||||
toast(httpConfig.globalErrorHandler[code])
|
||||
return;
|
||||
}
|
||||
reject(Error(res.message))
|
||||
return;
|
||||
}
|
||||
resolve(res.data)
|
||||
}).catch(reject)
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,14 @@
|
||||
<input placeholder="请输入密码" type="text" v-model="data.password">
|
||||
{{ data.password }}
|
||||
</p>
|
||||
<button type="submit">登录</button>
|
||||
<div class="error">{{ err }}</div>
|
||||
<button :disabled="loading" :type="loading?'button':'submit'">{{loading?'正在登录':'登录'}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {reactive} from "vue";
|
||||
import {reactive, ref} from "vue";
|
||||
import http from "../util/http";
|
||||
|
||||
export default {
|
||||
@ -27,25 +28,36 @@ export default {
|
||||
account: '',
|
||||
password: ''
|
||||
})
|
||||
const loading = ref(false)
|
||||
const err = ref()
|
||||
|
||||
function onLogin(e: Event) {
|
||||
e.preventDefault()
|
||||
http.post('/admin/user/login', data).then(result => {
|
||||
loading.value = true
|
||||
http.post<AdminLoginModel>('/admin/user/login', data).then(result => {
|
||||
console.log(result)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
}).catch(e => {
|
||||
err.value = e.message
|
||||
console.log(e)
|
||||
}).finally(()=>{
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
data, onLogin
|
||||
data, onLogin, err,loading
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-wrapper {
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.login-wrapper {
|
||||
width: 500px;
|
||||
margin: 50px auto;
|
||||
}
|
||||
</style>
|
13
admin-fe/tsconfig.json
Normal file
13
admin-fe/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"include": [
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"vite.config.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default {
|
||||
server: {
|
||||
port: 10086
|
||||
},
|
||||
// 必须配置vue插件
|
||||
plugins: [vue()]
|
||||
}
|
@ -17,6 +17,11 @@
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.15.17.tgz#870daa61c257dfa0ee4f0ed71704d55e9af8e20c"
|
||||
integrity sha512-IA1O7f7qxw2DX8oqTpugHElr926phs7Rq8ULXleBMk4go5K05BU0mI8BfCkWcYAvcmVaMc13bv5W3LIUlU6Y9w==
|
||||
|
||||
"@types/node@^18.11.10":
|
||||
version "18.11.10"
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-18.11.10.tgz#4c64759f3c2343b7e6c4b9caf761c7a3a05cee34"
|
||||
integrity sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==
|
||||
|
||||
"@vitejs/plugin-vue@^3.2.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz#a1484089dd85d6528f435743f84cdd0d215bbb54"
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.xiaoyan.point.api.controller.admin;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.xiaoyan.point.api.error.BizException;
|
||||
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||
@ -33,8 +34,10 @@ public class UserAdminController {
|
||||
userStoreMap.put("test", UserAdminInfo.create(2, "test", "123123"));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@PostMapping("login")
|
||||
public UserAdminInfo login(@Validated @RequestBody UserAdminInfo user) {
|
||||
Thread.sleep(1);
|
||||
// 判断是否存在账号
|
||||
if (!userStoreMap.containsKey(user.getAccount())) {
|
||||
throw BizException.create("账号不存在");
|
||||
|
Loading…
x
Reference in New Issue
Block a user