From 766cc259813474949505eb5ad1fd614c88175ead Mon Sep 17 00:00:00 2001 From: none Date: Tue, 21 Mar 2023 14:06:05 +0800 Subject: [PATCH] added: api --- package.json | 2 + src/api/course.ts | 18 +++++ src/api/index.ts | 4 + src/api/internal/httpClient.ts | 137 +++++++++++++++++++++++++++++++++ src/api/login.ts | 19 +++++ src/api/system.ts | 9 +++ src/api/user.ts | 20 +++++ src/utils/index.ts | 55 +++++++++++++ 8 files changed, 264 insertions(+) create mode 100644 src/api/course.ts create mode 100644 src/api/index.ts create mode 100644 src/api/internal/httpClient.ts create mode 100644 src/api/login.ts create mode 100644 src/api/system.ts create mode 100644 src/api/user.ts create mode 100644 src/utils/index.ts diff --git a/package.json b/package.json index 1d96edf..526f928 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "dependencies": { "@reduxjs/toolkit": "^1.9.3", "antd": "^5.3.2", + "axios": "^1.3.4", "localforage": "^1.10.0", "match-sorter": "^6.3.1", + "moment": "^2.29.4", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", diff --git a/src/api/course.ts b/src/api/course.ts new file mode 100644 index 0000000..331831c --- /dev/null +++ b/src/api/course.ts @@ -0,0 +1,18 @@ +import client from "./internal/httpClient"; + +// 线上课详情 +export function detail(id: number) { + return client.get(`/api/v1/course/${id}`, {}); +} + +// 获取播放地址 +export function playUrl(courseId: number, hourId: number) { + return client.get(`/api/v1/course/${courseId}/hour/${hourId}`, {}); +} + +// 记录学员观看时长 +export function record(courseId: number, hourId: number, duration: number) { + return client.get(`/api/v1/course/${courseId}/hour/${hourId}/record`, { + duration, + }); +} diff --git a/src/api/index.ts b/src/api/index.ts new file mode 100644 index 0000000..bdc8053 --- /dev/null +++ b/src/api/index.ts @@ -0,0 +1,4 @@ +export * as login from "./login"; +export * as user from "./user"; +export * as course from "./course"; +export * as system from "./system"; diff --git a/src/api/internal/httpClient.ts b/src/api/internal/httpClient.ts new file mode 100644 index 0000000..dd615ad --- /dev/null +++ b/src/api/internal/httpClient.ts @@ -0,0 +1,137 @@ +import axios, { Axios, AxiosResponse } from "axios"; +import { message } from "antd"; +import { getToken, clearToken } from "../../utils/index"; + +const GoLogin = () => { + clearToken(); + window.location.href = "/login"; +}; + +export class HttpClient { + axios: Axios; + + constructor(url: string) { + this.axios = axios.create({ + baseURL: url, + timeout: 15000, + withCredentials: false, + headers: { + Accept: "application/json", + }, + }); + + //拦截器注册 + this.axios.interceptors.request.use( + (config) => { + const token = getToken(); + token && (config.headers.Authorization = "Bearer " + token); + return config; + }, + (err) => { + return Promise.reject(err); + } + ); + + this.axios.interceptors.response.use( + (response: AxiosResponse) => { + let code = response.data.code; //业务返回代码 + let msg = response.data.msg; //错误消息 + + if (code === 0) { + return Promise.resolve(response); + } else { + message.error(msg); + } + return Promise.reject(response); + }, + // 当http的状态码非0 + (error) => { + let status = error.response.status; + if (status === 401) { + message.error("请重新登录"); + GoLogin(); + } else if (status === 404) { + // 跳转到404页面 + } else if (status === 403) { + // 跳转到无权限页面 + } else if (status === 500) { + // 跳转到500异常页面 + } + return Promise.reject(error.response); + } + ); + } + + get(url: string, params: object) { + return new Promise((resolve, reject) => { + this.axios + .get(url, { + params: params, + }) + .then((res) => { + resolve(res.data); + }) + .catch((err) => { + reject(err.data); + }); + }); + } + + destroy(url: string) { + return new Promise((resolve, reject) => { + this.axios + .delete(url) + .then((res) => { + resolve(res.data); + }) + .catch((err) => { + reject(err.data); + }); + }); + } + + post(url: string, params: object) { + return new Promise((resolve, reject) => { + this.axios + .post(url, params) + .then((res) => { + resolve(res.data); + }) + .catch((err) => { + reject(err.data); + }); + }); + } + + put(url: string, params: object) { + return new Promise((resolve, reject) => { + this.axios + .put(url, params) + .then((res) => { + resolve(res.data); + }) + .catch((err) => { + reject(err.data); + }); + }); + } + + request(config: object) { + return new Promise((resolve, reject) => { + this.axios + .request(config) + .then((res) => { + resolve(res.data); + }) + .catch((err) => { + reject(err.data); + }); + }); + } +} + +const APP_URL = import.meta.env.VITE_APP_URL || ""; + +const client = new HttpClient(APP_URL); + +export default client; diff --git a/src/api/login.ts b/src/api/login.ts new file mode 100644 index 0000000..edc10b4 --- /dev/null +++ b/src/api/login.ts @@ -0,0 +1,19 @@ +import client from "./internal/httpClient"; + +export function login( + email: string, + password: string, + captchaKey: string, + captchaVal: string +) { + return client.post("/api/v1/auth/login/password", { + email: email, + password: password, + captcha_key: captchaKey, + captcha_value: captchaVal, + }); +} + +export function logout() { + return client.post("/api/v1/auth/logout", {}); +} diff --git a/src/api/system.ts b/src/api/system.ts new file mode 100644 index 0000000..c6c2186 --- /dev/null +++ b/src/api/system.ts @@ -0,0 +1,9 @@ +import client from "./internal/httpClient"; + +export function config() { + return client.post("/api/v1/system/config", {}); +} + +export function imageCaptcha() { + return client.post("/api/v1/system/image-captcha", {}); +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..5a5c1aa --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,20 @@ +import client from "./internal/httpClient"; + +export function detail() { + return client.get("/api/v1/user/detail", {}); +} + +// 修改密码 +export function password(oldPassword: string, newPassword: string) { + return client.put("/api/v1/user/avatar", { + old_password: oldPassword, + new_password: newPassword, + }); +} + +// 学员课程 +export function courses(depId: number) { + return client.get("/api/v1/user/courses", { + dep_id: depId, + }); +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..f39de0f --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,55 @@ +import moment from "moment"; + +export function getToken(): string { + return window.localStorage.getItem("playedu-backend-token") || ""; +} + +export function setToken(token: string) { + window.localStorage.setItem("playedu-backend-token", token); +} + +export function clearToken() { + window.localStorage.removeItem("playedu-backend-token"); +} + +export function dateFormat(dateStr: string) { + return moment(dateStr).format("YYYY-MM-DD HH:mm"); +} + +export function generateUUID(): string { + let guid = ""; + for (let i = 1; i <= 32; i++) { + let n = Math.floor(Math.random() * 16.0).toString(16); + guid += n; + if (i === 8 || i === 12 || i === 16 || i === 20) guid += "-"; + } + return guid; +} + +export function transformBase64ToBlob( + base64: string, + mime: string, + filename: string +): File { + const arr = base64.split(","); + const bstr = atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename, { type: mime }); +} + +export function getHost() { + return window.location.protocol + "//" + window.location.host + "/"; +} + +export function inStrArray(array: string[], value: string): boolean { + for (let i = 0; i < array.length; i++) { + if (array[i] === value) { + return true; + } + } + return false; +}