增加基本的api请求代码
This commit is contained in:
parent
0362a15d4a
commit
da9e681fa5
59
package-lock.json
generated
59
package-lock.json
generated
@ -3423,6 +3423,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"async-validator": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npmmirror.com/async-validator/download/async-validator-1.8.5.tgz",
|
||||
"integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
|
||||
"requires": {
|
||||
"babel-runtime": "6.x"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
|
||||
@ -3479,6 +3487,14 @@
|
||||
"resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101385256&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz",
|
||||
"integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmmirror.com/axios/download/axios-0.21.4.tgz",
|
||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.0"
|
||||
}
|
||||
},
|
||||
"babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz",
|
||||
@ -3538,6 +3554,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-helper-vue-jsx-merge-props": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
||||
"integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
|
||||
},
|
||||
"babel-loader": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/babel-loader/download/babel-loader-8.2.3.tgz",
|
||||
@ -6035,6 +6056,26 @@
|
||||
"resolved": "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.4.27.tgz",
|
||||
"integrity": "sha512-uZ95szi3zUbzRDx1zx/xnsCG+2xgZyy57pDOeaeO4r8zx5Dqe8Jv1ti8cunvBwJHVI5LzPuw8umKwZb3WKYxSQ=="
|
||||
},
|
||||
"element-ui": {
|
||||
"version": "2.15.6",
|
||||
"resolved": "https://registry.npmmirror.com/element-ui/download/element-ui-2.15.6.tgz",
|
||||
"integrity": "sha512-rcYXEKd/j2G0AgficAOk1Zd1AsnHRkhmrK4yLHmNOiimU2JfsywgfKUjMoFuT6pQx0luhovj8lFjpE4Fnt58Iw==",
|
||||
"requires": {
|
||||
"async-validator": "~1.8.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
||||
"deepmerge": "^1.2.0",
|
||||
"normalize-wheel": "^1.0.1",
|
||||
"resize-observer-polyfill": "^1.5.0",
|
||||
"throttle-debounce": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmmirror.com/deepmerge/download/deepmerge-1.5.2.tgz",
|
||||
"integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz?cache=0&sync_timestamp=1612291311722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felliptic%2Fdownload%2Felliptic-6.5.4.tgz",
|
||||
@ -7901,8 +7942,7 @@
|
||||
"follow-redirects": {
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.6.tgz",
|
||||
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A=="
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
@ -11142,6 +11182,11 @@
|
||||
"integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-wheel": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/normalize-wheel/download/normalize-wheel-1.0.1.tgz",
|
||||
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/npm-run-path/download/npm-run-path-2.0.2.tgz",
|
||||
@ -13155,6 +13200,11 @@
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz",
|
||||
"integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.nlark.com/resolve/download/resolve-1.20.0.tgz",
|
||||
@ -14812,6 +14862,11 @@
|
||||
"neo-async": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"throttle-debounce": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/throttle-debounce/download/throttle-debounce-1.1.0.tgz",
|
||||
"integrity": "sha1-UYU9o3vmihVctugns1FKPEIuic0="
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz",
|
||||
|
@ -9,7 +9,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@walletconnect/web3-provider": "^1.7.1",
|
||||
"axios": "^0.21.0",
|
||||
"core-js": "^3.6.5",
|
||||
"element-ui": "^2.15.6",
|
||||
"js-cookie": "^2.2.1",
|
||||
"videojs-contrib-hls": "^5.15.0",
|
||||
"vue": "^2.6.11",
|
||||
|
@ -4,14 +4,16 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import { Component } from 'vue-property-decorator'
|
||||
import ResizeMixin from '@/utils/resize'
|
||||
import { mixins } from 'vue-class-component'
|
||||
|
||||
@Component({
|
||||
name: 'App',
|
||||
components: {
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
export default class extends mixins(ResizeMixin) {
|
||||
created() {
|
||||
console.log('main app created')
|
||||
}
|
||||
|
53
src/api/User.ts
Normal file
53
src/api/User.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import request from '@/utils/request'
|
||||
export interface IUser {
|
||||
id: string
|
||||
username: string
|
||||
showname: string
|
||||
comment: string
|
||||
locked: boolean
|
||||
avatar: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export const defaultUser: IUser = {
|
||||
id: '',
|
||||
username: '',
|
||||
showname: '',
|
||||
comment: '',
|
||||
locked: false,
|
||||
password: '',
|
||||
avatar: ''
|
||||
}
|
||||
export const getUserInfo = (data: any) =>
|
||||
request({
|
||||
url: '/api/user/info',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
|
||||
export const login = (data: any) =>
|
||||
request({
|
||||
url: '/api/user/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
|
||||
export const logout = () =>
|
||||
request({
|
||||
url: '/api/user/logout',
|
||||
method: 'post'
|
||||
})
|
||||
|
||||
export const changePass = (params: any) =>
|
||||
request({
|
||||
url: '/api/user/passwd',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
|
||||
export const changeInfo = (params: any) =>
|
||||
request({
|
||||
url: '/api/user/update_info',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
@ -51,7 +51,7 @@ import TopUserInfo from '@/components/market/TopUserInfo.vue'
|
||||
components: { TopUserInfo }
|
||||
})
|
||||
export default class extends Vue {
|
||||
walletCollected = true;
|
||||
walletCollected = false;
|
||||
infoPanelShow = false
|
||||
}
|
||||
</script>
|
||||
|
@ -1,9 +1,12 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import 'video.js/dist/video-js.css'
|
||||
|
||||
Vue.use(ElementUI)
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
|
@ -1,11 +1,13 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import { IAppState } from './modules/app'
|
||||
import { IUserState } from './modules/user'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export interface IRootState {
|
||||
app: IAppState
|
||||
user: IUserState
|
||||
}
|
||||
|
||||
// Declare empty store first, dynamically register all modules later.
|
||||
|
139
src/store/modules/user.ts
Normal file
139
src/store/modules/user.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import {
|
||||
Action,
|
||||
getModule,
|
||||
Module,
|
||||
Mutation,
|
||||
VuexModule
|
||||
} from 'vuex-module-decorators'
|
||||
import { getToken, removeToken, setToken } from '@/utils/cookies'
|
||||
import { getUserInfo, login, logout } from '@/api/User'
|
||||
import store from '@/store'
|
||||
|
||||
export interface IUserState {
|
||||
token: string
|
||||
name: string
|
||||
avatar: string
|
||||
introduction: string
|
||||
roles: string[]
|
||||
email: string
|
||||
permissions: string[][]
|
||||
level: number
|
||||
sex?: string
|
||||
}
|
||||
|
||||
@Module({ dynamic: true, store, name: 'user' })
|
||||
class User extends VuexModule implements IUserState {
|
||||
public token = getToken() || ''
|
||||
public name = ''
|
||||
public avatar = ''
|
||||
public introduction = ''
|
||||
public roles: string[] = []
|
||||
public permissions: string[][] = []
|
||||
public email = ''
|
||||
public level = 999
|
||||
public sex = '0'
|
||||
|
||||
@Action
|
||||
public async Login(userInfo: { username: string, password: string }) {
|
||||
let { username, password } = userInfo
|
||||
username = username.trim()
|
||||
const { data } = await login({ username, password })
|
||||
setToken(data.token)
|
||||
this.SET_TOKEN(data.token)
|
||||
}
|
||||
|
||||
@Action
|
||||
public ResetToken() {
|
||||
removeToken()
|
||||
this.SET_TOKEN('')
|
||||
this.SET_ROLES([])
|
||||
this.SET_PERMISSIONS([])
|
||||
}
|
||||
|
||||
@Action
|
||||
public async GetUserInfo() {
|
||||
if (this.token === '') {
|
||||
throw Error('GetUserInfo: token is undefined!')
|
||||
}
|
||||
const { data } = await getUserInfo({ /* Your params here */ })
|
||||
if (!data) {
|
||||
throw Error('Verification failed, please Login again.')
|
||||
}
|
||||
const { showname, avatar, introduction, permissions, level } = data
|
||||
|
||||
this.SET_NAME(showname)
|
||||
this.SET_AVATAR(avatar)
|
||||
this.SET_INTRODUCTION(introduction)
|
||||
this.SET_PERMISSIONS(permissions)
|
||||
this.SET_LEVEL(level)
|
||||
}
|
||||
|
||||
@Action
|
||||
public async UpdateInfo(data: any) {
|
||||
const { showname, avatar } = data
|
||||
this.SET_NAME(showname)
|
||||
this.SET_AVATAR(avatar)
|
||||
}
|
||||
|
||||
@Action
|
||||
public async LogOut() {
|
||||
if (this.token === '') {
|
||||
throw Error('LogOut: token is undefined!')
|
||||
}
|
||||
await logout()
|
||||
removeToken()
|
||||
this.SET_TOKEN('')
|
||||
this.SET_ROLES([])
|
||||
this.SET_PERMISSIONS([])
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_TOKEN(token: string) {
|
||||
this.token = token
|
||||
}
|
||||
|
||||
@Action
|
||||
public async updatePageToken(token: string) {
|
||||
this.SET_TOKEN(token)
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_NAME(name: string) {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_AVATAR(avatar: string) {
|
||||
this.avatar = avatar
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_INTRODUCTION(introduction: string) {
|
||||
this.introduction = introduction
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_ROLES(roles: string[]) {
|
||||
this.roles = roles
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_LEVEL(level: number) {
|
||||
this.level = level
|
||||
}
|
||||
|
||||
@Mutation
|
||||
private SET_PERMISSIONS(permissions: string[]) {
|
||||
const results: string[][] = []
|
||||
for (const permission of permissions) {
|
||||
if (permission === '*') {
|
||||
results.push(['*', '*'])
|
||||
} else {
|
||||
results.push(permission.split(':'))
|
||||
}
|
||||
}
|
||||
this.permissions = results
|
||||
}
|
||||
}
|
||||
|
||||
export const UserModule = getModule(User)
|
72
src/utils/request.ts
Normal file
72
src/utils/request.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import axios from 'axios'
|
||||
import { Message, MessageBox } from 'element-ui'
|
||||
import { UserModule } from '@/store/modules/user'
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: process.env.VUE_APP_BASE_API,
|
||||
timeout: 5000
|
||||
})
|
||||
|
||||
// Request interceptors
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
// Add X-Access-Token header to every request, you can add other custom headers here
|
||||
if (UserModule.token) {
|
||||
config.headers.authorization = 'Bearer ' + UserModule.token
|
||||
}
|
||||
config.headers['Content-Type'] = 'application/json'
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// Response interceptors
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
// Some example codes here:
|
||||
// code == 0: success
|
||||
// code == 50001: invalid access token
|
||||
// code == 50002: already login in other place
|
||||
// code == 50003: access token expired
|
||||
// code == 50004: invalid user (user not exist)
|
||||
// code == 10: username or password is incorrect
|
||||
// You can change this part for your own usage.
|
||||
const res = response.data
|
||||
if (res.code) {
|
||||
Message({
|
||||
message: res.msg || 'Error',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
||||
MessageBox.confirm(
|
||||
'You have been logged out, try to login again.',
|
||||
'Log out',
|
||||
{
|
||||
confirmButtonText: 'Relogin',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
UserModule.ResetToken()
|
||||
location.reload() // To prevent bugs from vue-router
|
||||
})
|
||||
}
|
||||
return Promise.reject(new Error(res.msg || 'Error'))
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
47
src/utils/resize.ts
Normal file
47
src/utils/resize.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import { AppModule, DeviceType } from '@/store/modules/app'
|
||||
|
||||
const WIDTH = 992 // refer to Bootstrap's responsive design
|
||||
|
||||
@Component({
|
||||
name: 'ResizeMixin'
|
||||
})
|
||||
export default class extends Vue {
|
||||
get device() {
|
||||
return AppModule.device
|
||||
}
|
||||
|
||||
@Watch('$route')
|
||||
private onRouteChange() {
|
||||
console.log('route change: ', this.$route?.fullPath)
|
||||
}
|
||||
|
||||
beforeMount() {
|
||||
window.addEventListener('resize', this.resizeHandler)
|
||||
}
|
||||
|
||||
mounted() {
|
||||
const isMobile = this.isMobile()
|
||||
if (isMobile) {
|
||||
AppModule.ToggleDevice(DeviceType.Mobile)
|
||||
}
|
||||
}
|
||||
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.resizeHandler)
|
||||
}
|
||||
|
||||
private isMobile() {
|
||||
const rect = document.body.getBoundingClientRect()
|
||||
return rect.width - 1 < WIDTH
|
||||
}
|
||||
|
||||
private resizeHandler() {
|
||||
if (!document.hidden) {
|
||||
const isMobile = this.isMobile()
|
||||
AppModule.ToggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop)
|
||||
if (isMobile) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user