Skip to content

#3 #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 14, 2025
Merged

#3 #4

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,61 @@ const MicroComponentTest = () => {

export default MicroComponentTest;
```

### 网络请求
```
import React from "react";
import Space from "@/components/Space";
//@ts-ignore
import {HttpClient,Response} from "@codingapi/ui-framework";

const httpClient = new HttpClient(10000,{
success:(msg:string)=>{
console.log('success',msg);
},
error:(msg:string)=>{
console.log('error',msg);
},
});

const HttpTest = ()=>{

const [url, setUrl] = React.useState('/api/products');

const handlerGet = ()=>{
httpClient.get(url).then((res:Response)=>{
const json = JSON.stringify(res);
console.log(json);
alert(json);
})
}

return (
<>
<div
style={{
textAlign: 'center'
}}
>
<h1>Http Test </h1>
</div>
<Space>
url:
<input
value={url}
onChange={(e) => {
setUrl(e.target.value);
}}/>
<button onClick={handlerGet}>get</button>
</Space>
</>
)
}

export default HttpTest;

```

更多实例参考: https://github.com/codingapi/ui-framework/tree/main/playground

## 主要特性
Expand All @@ -314,6 +369,7 @@ export default MicroComponentTest;
- 事件总线:用于组件间通信
- 访问控制:用于权限管理
- 微前端动态组件:支持动态加载和卸载组件
- 网络请求:封装了 HttpClient,支持 GET、POST、PUT、DELETE 等请求方式

## 开发

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codingapi/ui-framework",
"version": "0.0.25",
"version": "0.0.26",
"description": "A UI Framework built with React and Typescript",
"keywords": [
"ui",
Expand All @@ -27,6 +27,7 @@
],
"dependencies": {
"@types/node": "^22.15.2",
"axios": "^1.9.0",
"base64-js": "^1.5.1",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
Expand Down
2 changes: 2 additions & 0 deletions playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ComponentBusTest from "@/components/ComponentBusTest";
import EventBusTest from "@/components/EventBusTest";
import MicroComponentTest from "@/components/MicroComponentTest";
import Base64Test from "@/components/Base64Test";
import HttpTest from "@/components/HttpTest";

const App = () => {

Expand All @@ -18,6 +19,7 @@ const App = () => {
<EventBusTest/>
<MicroComponentTest/>
<Base64Test/>
<HttpTest/>
</div>
);
}
Expand Down
49 changes: 49 additions & 0 deletions playground/src/components/HttpTest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react";
import Space from "@/components/Space";
//@ts-ignore
import {HttpClient,Response} from "@codingapi/ui-framework";

const httpClient = new HttpClient(10000,{
success:(msg:string)=>{
console.log('success',msg);
},
error:(msg:string)=>{
console.log('error',msg);
},
});

const HttpTest = ()=>{

const [url, setUrl] = React.useState('/api/products');

const handlerGet = ()=>{
httpClient.get(url).then((res:Response)=>{
const json = JSON.stringify(res);
console.log(json);
alert(json);
})
}

return (
<>
<div
style={{
textAlign: 'center'
}}
>
<h1>Http Test </h1>
</div>
<Space>
url:
<input
value={url}
onChange={(e) => {
setUrl(e.target.value);
}}/>
<button onClick={handlerGet}>get</button>
</Space>
</>
)
}

export default HttpTest;
224 changes: 224 additions & 0 deletions src/utils/http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import axios, {AxiosInstance} from "axios";
import {sleep} from "./sleep";
import {Base64Utils} from "./base64";

export interface MessageBox {
success: (msg: string) => void;
error: (msg: string) => void;
}

export type Response = {
success: boolean;
errCode?: string;
errMessage?: string;
data?: any;
total?: number;
}

export class HttpClient {
private readonly api: AxiosInstance;
private readonly messageBox: MessageBox;

constructor(timeout: number, messageBox: MessageBox) {
this.messageBox = messageBox;
this.api = axios.create({
timeout: timeout,
headers: {
"Content-Type": "application/json",
},
});

this.addRequestInterceptors();
this.addResponseInterceptors();
}

private addRequestInterceptors() {
this.api.interceptors.request.use((config: any) => {
const token = localStorage.getItem("token");
if (token) {
config.headers = {
Authorization: `${token}`,
} as any;
}
return config;
}, (error: any) => {
return Promise.reject(error);
});
}

private addResponseInterceptors() {
this.api.interceptors.response.use(async (response: any) => {
const headers = response.headers;
const token = headers['authorization'];

const state = response.status;
if (state === 200) {
if (token) {
console.log('reset token', token);
localStorage.setItem("token", token)
}

if (response.data) {
const success = response.data.success;
if (!success) {
const errMessage = response.data.errMessage;
const errCode = response.data.errCode;
if ("token.expire" === errCode || "token.error" === errCode) {
this.messageBox.error('登录已过期,请退出再重新打开');
await sleep(1500);
localStorage.clear();
window.location.href = '/#login';
} else {
if ("login.error" === errCode) {
return response;
}
this.messageBox.error(errMessage)
}
}
} else {
this.messageBox.error('抱歉,该账户无权限访问');
}
}
return response;
},
(error: any) => {
const response = error.response;
const state = response.data.status;

if (state === 403) {
this.messageBox.error('抱歉,该账户无权限访问');
return {
data: {
success: false,
}
}
}
return Promise.reject(error);
}
)
}

public get = async (url: string, params?: any): Promise<Response> => {
try {
const response = await this.api.get(url, {
params
});
return response.data as Response;
} catch (e) {
return {
success: false,
}
}
}

public put = async (url: string, data: any): Promise<Response> => {
try {
const response = await this.api.put(url, data);
return response.data as Response;
} catch (e) {
return {
success: false,
}
}
}

public delete = async (url: string, params?: any): Promise<Response> => {
try {
const response = await this.api.delete(url, {
params
});
return response.data as Response;
} catch (e) {
return {
success: false,
}
}
}

public post = async (url: string, data: any): Promise<Response> => {
try {
const response = await this.api.post(url, data);
return response.data as Response;
} catch (e) {
return {
success: false,
}
}
}


public page = async (url: string, params: any, sort: any, filter: any, match: {
key: string,
type: string
}[]): Promise<Response> => {
const base64Match = Base64Utils.stringToBase64(JSON.stringify(match));
const base64Sort = Base64Utils.stringToBase64(JSON.stringify(sort));
const base64Filter = Base64Utils.stringToBase64(JSON.stringify(filter));

const response = await this.get(url, {
...params,
sort: base64Sort,
filter: base64Filter,
params: base64Match,
});

if (response.success) {
const list = response.data.total > 0 ? response.data.list : [];
return {
data: list,
success: response.success,
total: response.data.total
};
} else {
return {
data: [],
success: response.success,
total: 0
}
}
}


public download = async (url: string, filename?: string) => {
try {
const token = localStorage.getItem("token");
const response = await axios.get(url, {
responseType: 'blob',
headers: {
'Authorization': token,
}
});
const bytes = await response.data;
const blob = new Blob([bytes]);
const downloadUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = filename || 'result.csv';
a.click();
} catch (e) {
console.log(e);
}
}

public postDownload = async (url: string, data: any, filename?: string) => {
try {
const token = localStorage.getItem("token");
const response = await axios.post(url, data, {
responseType: 'blob',
headers: {
'Authorization': token,
}
});
const bytes = await response.data;
const blob = new Blob([bytes]);
const downloadUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = filename || 'result.csv';
a.click();
} catch (e) {
console.log(e);
}
}

}
2 changes: 2 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './base64';
export * from './dynamicComponent';
export * from './role';
export * from './sleep';
export * from './http';
7 changes: 7 additions & 0 deletions src/utils/sleep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const sleep = async (time: number) => {
return new Promise((resolve:any) => {
setTimeout(() => {
resolve();
}, time);
})
}