feat: app

v3
veypi 4 weeks ago
parent 932b20fe72
commit 5b37b9f2a8

@ -20,6 +20,8 @@ export interface App {
init_role?: Role init_role?: Role
init_url: string init_url: string
user_count: number user_count: number
status: string
user_status: string
} }
export interface AppUser { export interface AppUser {
id: string id: string

@ -26,8 +26,8 @@ export interface PostOpts {
} }
// keep // keep
export function Post(json: PostOpts) { export function Post(json: PostOpts, config?: Object) {
return webapi.Post<string>(`/token`, { json }) return webapi.Post<string>(`/token`, { json, config })
} }
export function Get(token_id: string) { export function Get(token_id: string) {
return webapi.Get<models.Token>(`/token/${token_id}`, {}) return webapi.Get<models.Token>(`/token/${token_id}`, {})

@ -4,7 +4,7 @@
// Distributed under terms of the MIT license. // Distributed under terms of the MIT license.
// //
import axios, { AxiosError, AxiosInstance, type AxiosResponse } from 'axios'; import axios, { AxiosError, type AxiosInstance, type AxiosResponse } from 'axios';
// Be careful when using SSR for cross-request state pollution // Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here; // due to creating a Singleton instance here;
@ -16,6 +16,7 @@ import axios, { AxiosError, AxiosInstance, type AxiosResponse } from 'axios';
export const token = { export const token = {
value: '', value: '',
update: () => { update: () => {
console.warn('token updater not set')
return new Promise<string>((resolve) => { resolve(token.value) }) return new Promise<string>((resolve) => { resolve(token.value) })
}, },
set_updator: (fn: () => Promise<string>) => { set_updator: (fn: () => Promise<string>) => {
@ -49,10 +50,9 @@ export const token = {
} }
// 请求拦截 // 请求拦截
const beforeRequest = (config: any) => { const beforeRequest = (config: any) => {
config.retryTimes = 3 config.retryTimes = config.retryTimes || 3
// NOTE 添加自定义头部 // NOTE 添加自定义头部
token.value && (config.headers.Authorization = `Bearer ${token.value}`) token.value && (config.headers.Authorization = `Bearer ${token.value}`)
// config.headers['auth_token'] = ''
return config return config
} }
@ -83,17 +83,18 @@ const responseFailed = (client: AxiosInstance) => {
return Promise.reject(new Error('请检查网络连接')) return Promise.reject(new Error('请检查网络连接'))
} }
let needRetry = true // @ts-ignore
let needRetry = config?.needRetry !== false
if (response?.status == 404) { if (response?.status == 404) {
needRetry = false needRetry = false
} else if (response?.status == 401) { } else if (response?.status == 401 && needRetry) {
needRetry = false needRetry = false
// AuthNotFound = New(40100, "auth not found") // AuthNotFound = New(40100, "auth not found")
// AuthExpired = New(40102, "auth expired") // AuthExpired = New(40102, "auth expired")
if (data.code === 40102 || data.code === 40100) { if (data.code === 40102 || data.code === 40100) {
token.value = '' token.value = ''
return token.update().then(() => { return token.update().then(() => {
return requestRetry(client)(1000, response!) return requestRetry(client)(200, response!)
}) })
} }
} else if (response?.status == 500) { } else if (response?.status == 500) {
@ -143,6 +144,7 @@ interface data {
query?: any query?: any
form?: any form?: any
header?: any header?: any
config?: Object
} }
@ -159,6 +161,9 @@ function transData(d: data) {
if (d.header) { if (d.header) {
opts.headers = Object.assign(opts.headers, d.header) opts.headers = Object.assign(opts.headers, d.header)
} }
if (d.config) {
opts = Object.assign(opts, d.config)
}
return opts return opts
} }

@ -162,9 +162,6 @@ div[voa] {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
height: 3rem;
line-height: 3rem;
font-size: 1.25rem;
} }
.voa-account-body { .voa-account-body {
@ -199,17 +196,35 @@ div[voa] {
} }
} }
.voa-item-title {
height: 3rem;
line-height: 3rem;
font-size: 1.25rem;
cursor: pointer;
user-select: none;
font-weight: 500;
margin-left: -1rem;
}
.voa-apps { .voa-apps {
.voa-apps-header {} padding: 0 1rem;
.voa-apps-body { .voa-apps-body {
margin-top: 1rem;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1rem; gap: 1rem;
flex-direction: column;
} }
.voa-apps-box {} .voa-apps-box {
img {
border-radius: 50%;
width: 3rem;
height: 3rem;
object-fit: cover;
}
}
} }

@ -8,7 +8,16 @@ import { v } from '../v2dom'
import logic from '../logic' import logic from '../logic'
export default v('voa-account', [ export default v('voa-account', [
v('voa-account-header', [v('voa-ah-1', '我的账户'), v('voa-ah-2')]), v('voa-account-header', [
v({
class: 'voa-item-title',
children: ['我的账户'],
onclick: () => {
logic.goto('/user')
}
}),
v('voa-ah-2')]
),
v('voa-account-body', [ v('voa-account-body', [
v('voa-ab-ico', [v({ typ: 'img', attrs: { 'src': () => `${logic.user.icon}` } })]), v('voa-ab-ico', [v({ typ: 'img', attrs: { 'src': () => `${logic.user.icon}` } })]),
v('voa-ab-info', [ v('voa-ab-info', [

@ -14,28 +14,29 @@ import * as typs from "../typs"
export default () => { export default () => {
let apps: typs.App[] = proxy.Watch([]) let apps: typs.App[] = proxy.Watch([])
api.app.List({}).then(e => { api.app.List({}).then(e => {
apps.push(...e) apps.push(...e.filter((i) => i.user_status === 'ok'))
}) })
return v({ return v({
class: 'voa-apps', class: 'voa-apps',
children: [ children: [
v('voa-apps-header', [v('voa-apps-title', '我的应用')]), v('voa-apps-header',
[v({
class: 'voa-item-title',
children: ['我的应用'],
onclick: () => {
logic.goto('/')
}
})]
),
v('voa-apps-body', [ v('voa-apps-body', [
vfor(apps, vfor(apps,
(data, idx) => v('voa-apps-box', [v('span', () => idx + ': ' + data.name)])), (data) => v({
class: 'voa-apps-box',
// [logic.myapps, children: [v('img', '', { src: () => data.icon })],
// (data) => v('voa-app-box', () => data.name)],
v({
typ: 'div', children: ['add'], vbind: [logic.myapps[0], 'name'],
onclick: () => { onclick: () => {
// let tmp = apps[1] logic.goto(`/app/${data.id}`)
// apps[1] = apps[0]
// apps[0] = tmp
// apps.splice(2, 1)
apps.push({ name: new Date().toLocaleTimeString() } as any)
} }
}) }))
]) ])
] ]
}) })

@ -68,14 +68,15 @@ class Token {
if (this._typ === 'app') { if (this._typ === 'app') {
aid = logic.app_id aid = logic.app_id
} }
api.token.Post({ refresh: logic.token.refresh.raw(), user_id: logic.token.refresh.uid!, app_id: aid }).then(e => { api.token.Post({ refresh: logic.token.refresh.raw(), user_id: logic.token.refresh.uid!, app_id: aid }, { needRetry: false }).then(e => {
if (this._typ === 'oa' && logic.app_id == logic.oa_id) { if (this._typ === 'oa' && logic.app_id == logic.oa_id) {
logic.token.app.set(e) logic.token.app.set(e)
} }
this.set(e) this.set(e)
resolve(this) resolve(this)
}).catch(e => { }).catch(e => {
console.warn(`get oa token failed: ${e} `) console.warn(`refresh token failed: ${e.err || e} `)
bus.emit('logout')
reject() reject()
}) })
}) })

Loading…
Cancel
Save