mirror of
https://github.com/snowykami/neo-blog.git
synced 2025-09-27 03:26:29 +00:00
⚡️ feat: add main page layout with navigation and footer
feat: create random labels page feat: implement login page with OpenID Connect support feat: add Gravatar component for user avatars feat: create Navbar component with navigation menu chore: create Sidebar component placeholder feat: implement login form with OIDC and email/password options feat: add reusable button component feat: create card component for structured content display feat: implement input component for forms feat: create label component for form labels feat: add navigation menu component for site navigation chore: add configuration file for site metadata feat: implement device context for responsive design feat: add utility functions for class name management feat: define OIDC configuration model feat: define base response model for API responses feat: define user model for user data feat: implement i18n for internationalization support feat: add English and Chinese translations for login chore: create index for locale resources chore: add blog home view placeholder
This commit is contained in:
31
web/src/api/client.ts
Normal file
31
web/src/api/client.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import axios from "axios";
|
||||
import { camelToSnakeObj, snakeToCamelObj } from "field-conv";
|
||||
|
||||
const API_SUFFIX = "/api/v1";
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: API_SUFFIX,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
axiosInstance.interceptors.request.use((config) => {
|
||||
if (config.data && typeof config.data === "object") {
|
||||
config.data = camelToSnakeObj(config.data);
|
||||
}
|
||||
if (config.params && typeof config.params === "object") {
|
||||
config.params = camelToSnakeObj(config.params);
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
axiosInstance.interceptors.response.use(
|
||||
(response) => {
|
||||
if (response.data && typeof response.data === "object") {
|
||||
response.data = snakeToCamelObj(response.data);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
export default axiosInstance;
|
56
web/src/api/user.ts
Normal file
56
web/src/api/user.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import axiosInstance from "./client";
|
||||
|
||||
import type { OidcConfig } from "@/models/oidc-config";
|
||||
import type { User } from "@/models/user";
|
||||
import type { BaseResponse } from "@/models/resp";
|
||||
|
||||
export function userLogin(
|
||||
username: string,
|
||||
password: string
|
||||
): Promise<BaseResponse<{ token: string; user: User }>> {
|
||||
return axiosInstance
|
||||
.post<BaseResponse<{ token: string; user: User }>>(
|
||||
"/user/login",
|
||||
{
|
||||
username,
|
||||
password,
|
||||
}
|
||||
)
|
||||
.then(res => res.data);
|
||||
}
|
||||
|
||||
export function userRegister(
|
||||
username: string,
|
||||
password: string,
|
||||
nickname: string,
|
||||
email: string,
|
||||
verificationCode?: string
|
||||
): Promise<BaseResponse<{ token: string; user: User }>> {
|
||||
return axiosInstance
|
||||
.post<BaseResponse<{ token: string; user: User }>>(
|
||||
"/user/register",
|
||||
{
|
||||
username,
|
||||
password,
|
||||
nickname,
|
||||
email,
|
||||
verificationCode,
|
||||
}
|
||||
)
|
||||
.then(res => res.data);
|
||||
}
|
||||
|
||||
export function ListOidcConfigs(): Promise<BaseResponse<{ oidcConfigs: OidcConfig[] }>> {
|
||||
return axiosInstance
|
||||
.get<BaseResponse<{ oidcConfigs: OidcConfig[] }>>("/user/oidc/list")
|
||||
.then(res => {
|
||||
const data = res.data;
|
||||
if ('configs' in data) {
|
||||
return {
|
||||
...data,
|
||||
oidcConfigs: data.configs,
|
||||
};
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user