近况
怎么说呢,半个多月没更新。这段时间感觉挺摆烂的,一些期末想做的东西最后也没做。现在只有几个半成品。
my_diary
这个已经放在GitHub上了,但是怎么说呢,写得相当不好就是了。
后端
貌似是我用go写的第二个后端,比第一个要好一些,但是感觉挺拉跨的。感觉也暴露出很多问题,文件夹结构,controller、services、repository的分层,还有鉴权。
在B站上看到说redis层管理登录用户什么的,我完全没做。auth和public的接口糅合在一起了,感觉如果后面要加东西会很屎。
文件夹分成了user和diary这两个文件夹,然后再分别有三个层。之前看同学写java好像是直接分成三个文件夹,而不是像我这样子。写的时候感觉好像还好,不知道会有什么问题。
前端
花了几天时间把后端写好,然后卡死在了前端。感觉我没有那种设计的天赋,如果给我个图我大概率能写出来,但是什么都没有感觉太困难了。
前端的网络请求封装再次困扰了我。大概是这样的
太长了,收起来
typescript
import { ref } from 'vue'
import type { Ref } from 'vue'
import { getToken } from './auth'
enum Code {
Fail = 0,
Unauthorized = 1,
Success = 100,
}
export interface Response<T> {
code: Code
data: T
message: string
}
export interface Result<T> {
data: Ref<T>
isLoading: Ref<boolean>
error: Ref<Error | null>
}
function isResponse<T>(data: unknown): data is Response<T> {
if (!data) {
return false
}
if (typeof data === 'object') {
return 'code' in data && 'data' in data && 'message' in data
}
return false
}
export interface Query {
[key: string]: string | number
}
class RequestHandler {
#baseUrl: string
private static instance: RequestHandler
private constructor(baseUrl: string = import.meta.env.VITE_API_BASE_URL) {
this.#baseUrl = baseUrl
}
public static getInstance(): RequestHandler {
if (!RequestHandler.instance) {
RequestHandler.instance = new RequestHandler()
}
return RequestHandler.instance
}
private useRequest<T>(url: string, requestInit: RequestInit, isAsync: true): Promise<T>
private useRequest<T>(url: string, requestInit: RequestInit, isAsync: false): Result<T>
private useRequest<T>(
url: string,
requestInit: RequestInit,
isAsync: boolean = true,
): Promise<T> | Result<T> {
if (isAsync) {
return fetch(url, {
// requestInit
headers:{
...requestInit.headers,
},
method:requestInit.method,
mode:'cors',
body:requestInit.body
})
.then((response) => response.json())
.then((data) => {
if (isResponse<T>(data)) {
this.codeHandler(data.code)
return data.data
}
throw new Error('0')
})
}
const data = ref<T>()
const isLoading = ref(true)
const error = ref<Error | null>(null)
fetch(url, requestInit)
.then((response) => response.json())
.then((res) => {
if (!isResponse<T>(res)) {
throw new Error('0')
}
this.codeHandler(res.code)
data.value = res.data
})
.catch((error) => {
console.error(error)
error.value = error
})
.finally(() => {
isLoading.value = false
})
return {
data,
isLoading,
error,
} as Result<T>
}
private codeHandler(code: Code) {
switch (code) {
case 0: {
throw new Error('fail')
}
case 1: {
// TODO: 重新登录
console.log('未登录')
break
}
case 100 :{
break
}
default: {
throw new Error('后端改了前端没改')
}
}
}
public Get<T>(url: string, query: Query, isAuth: boolean, isAsync: true): Promise<T>
public Get<T>(url: string, query: Query, isAuth: boolean, isAsync: false): Result<T>
public Get<T>(
url: string,
query: Query,
isAuth: boolean = true,
isAsync: boolean = true,
): Promise<T> | Result<T> {
const headers = new Headers()
if (isAuth) {
const token = getToken()
if (!token) {
throw new Error('1')
}
headers.set('Authorization', `Bearer ${token}`)
}
const queryParams = new URLSearchParams()
for (const key in query) {
if (Object.prototype.hasOwnProperty.call(query, key)) {
queryParams.append(key, query[key].toString())
}
}
let fullUrl = this.#baseUrl + url
if (queryParams.toString()) {
fullUrl += '?' + queryParams.toString()
}
if (isAsync) {
return this.useRequest<T>(
fullUrl,
{
method: 'GET',
headers,
},
true,
)
} else {
return this.useRequest<T>(
fullUrl,
{
method: 'GET',
headers,
},
false,
)
}
}
public Post<T>(url: string, body: unknown, isAuth: boolean, isAsync: true): Promise<T>
public Post<T>(url: string, body: unknown, isAuth: boolean, isAsync: false): Result<T>
public Post<T>(
url: string,
body: unknown,
isAuth: boolean = true,
isAsync: boolean = true,
): Promise<T> | Result<T> {
const headers = new Headers()
if (body instanceof Object) {
headers.set('Content-Type', 'application/json')
} else {
headers.delete('Content-Type')
}
if (isAuth) {
const token = getToken()
if (!token) {
throw new Error('1')
}
headers.set('Authorization', `Bearer ${token}`)
}
if (isAsync) {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'POST',
headers,
body: JSON.stringify(body),
},
true,
)
} else {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'POST',
headers,
body: JSON.stringify(body),
},
false,
)
}
}
public Put<T>(url: string, body: unknown, isAuth: boolean, isAsync: true): Promise<T>
public Put<T>(url: string, body: unknown, isAuth: boolean, isAsync: false): Result<T>
public Put<T>(
url: string,
body: unknown,
isAuth: boolean = true,
isAsync: boolean = true,
): Promise<T> | Result<T> {
const headers = new Headers()
if (body instanceof Object) {
headers.set('Content-Type', 'application/json')
} else {
headers.delete('Content-Type')
}
if (isAuth) {
const token = getToken()
if (!token) {
throw new Error('1')
}
headers.set('Authorization', `Bearer ${token}`)
}
if (isAsync) {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'PUT',
headers,
body: JSON.stringify(body),
},
true,
)
} else {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'PUT',
headers,
body: JSON.stringify(body),
},
false,
)
}
}
public Delete<T>(url: string, isAuth: boolean, isAsync: true): Promise<T>
public Delete<T>(url: string, isAuth: boolean, isAsync: false): Result<T>
public Delete<T>(
url: string,
isAuth: boolean = true,
isAsync: boolean = true,
): Promise<T> | Result<T> {
const headers = new Headers()
if (isAuth) {
const token = getToken()
if (!token) {
throw new Error('1')
}
headers.set('Authorization', `Bearer ${token}`)
}
if (isAsync) {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'DELETE',
headers,
},
true,
)
} else {
return this.useRequest<T>(
this.#baseUrl + url,
{
method: 'DELETE',
headers,
},
false,
)
}
}
}
export const requestHandler = RequestHandler.getInstance()
只能说能用,但是感觉很奇怪。
心语
总感觉不是自己想要的效果,也不知道该怎么写。现在也只写了一点。
写出一个博客主题感觉不会太难,毕竟也就是vue多了一些东西。感觉让它更通用、设计主题才是难点。有点想先模仿一个写好的主题造一个了。