fdb2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +21 -0
- package/.editorconfig +11 -0
- package/.eslintrc.cjs +14 -0
- package/.eslintrc.json +7 -0
- package/.prettierrc.js +3 -0
- package/.tpl.env +22 -0
- package/README.md +260 -0
- package/bin/build.sh +28 -0
- package/bin/deploy.sh +8 -0
- package/bin/dev.sh +10 -0
- package/bin/docker/.env +4 -0
- package/bin/docker/dev-docker-compose.yml +43 -0
- package/bin/docker/dev.Dockerfile +24 -0
- package/bin/docker/prod-docker-compose.yml +17 -0
- package/bin/docker/prod.Dockerfile +29 -0
- package/bin/fdb2.js +142 -0
- package/data/connections.demo.json +32 -0
- package/env.d.ts +1 -0
- package/nw-build.js +120 -0
- package/nw-dev.js +65 -0
- package/package.json +114 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +9 -0
- package/public/modules/header.tpl +14 -0
- package/public/modules/initial_state.tpl +55 -0
- package/server/index.ts +677 -0
- package/server/model/connection.entity.ts +66 -0
- package/server/model/database.entity.ts +246 -0
- package/server/service/connection.service.ts +334 -0
- package/server/service/database/base.service.ts +363 -0
- package/server/service/database/database.service.ts +510 -0
- package/server/service/database/index.ts +7 -0
- package/server/service/database/mssql.service.ts +723 -0
- package/server/service/database/mysql.service.ts +761 -0
- package/server/service/database/oracle.service.ts +839 -0
- package/server/service/database/postgres.service.ts +744 -0
- package/server/service/database/sqlite.service.ts +559 -0
- package/server/service/session.service.ts +158 -0
- package/server.js +128 -0
- package/src/adapter/ajax.ts +135 -0
- package/src/assets/base.css +1 -0
- package/src/assets/database.css +950 -0
- package/src/assets/images/collapse.png +0 -0
- package/src/assets/images/no-login.png +0 -0
- package/src/assets/images/svg/illustrations/illustration-1.svg +1 -0
- package/src/assets/images/svg/illustrations/illustration-2.svg +2 -0
- package/src/assets/images/svg/illustrations/illustration-3.svg +50 -0
- package/src/assets/images/svg/illustrations/illustration-4.svg +1 -0
- package/src/assets/images/svg/illustrations/illustration-5.svg +73 -0
- package/src/assets/images/svg/illustrations/illustration-6.svg +89 -0
- package/src/assets/images/svg/illustrations/illustration-7.svg +39 -0
- package/src/assets/images/svg/illustrations/illustration-8.svg +1 -0
- package/src/assets/images/svg/separators/curve-2.svg +3 -0
- package/src/assets/images/svg/separators/curve.svg +3 -0
- package/src/assets/images/svg/separators/line.svg +3 -0
- package/src/assets/images/theme/light/screen-1-1000x800.jpg +0 -0
- package/src/assets/images/theme/light/screen-2-1000x800.jpg +0 -0
- package/src/assets/login/bg.jpg +0 -0
- package/src/assets/login/bg.png +0 -0
- package/src/assets/login/left.jpg +0 -0
- package/src/assets/logo.svg +73 -0
- package/src/assets/logo.webp +0 -0
- package/src/assets/main.css +1 -0
- package/src/base/config.ts +20 -0
- package/src/base/detect.ts +134 -0
- package/src/base/entity.ts +92 -0
- package/src/base/eventBus.ts +37 -0
- package/src/base//345/237/272/347/241/200/345/261/202.md +7 -0
- package/src/components/connection-editor/index.vue +590 -0
- package/src/components/dataGrid/index.vue +105 -0
- package/src/components/dataGrid/pagination.vue +106 -0
- package/src/components/loading/index.vue +43 -0
- package/src/components/modal/index.ts +181 -0
- package/src/components/modal/index.vue +560 -0
- package/src/components/toast/index.ts +44 -0
- package/src/components/toast/toast.vue +58 -0
- package/src/components/user/name.vue +104 -0
- package/src/components/user/selector.vue +416 -0
- package/src/domain/SysConfig.ts +74 -0
- package/src/platform/App.vue +8 -0
- package/src/platform/database/components/connection-detail.vue +1154 -0
- package/src/platform/database/components/data-editor.vue +478 -0
- package/src/platform/database/components/data-import-export.vue +1602 -0
- package/src/platform/database/components/database-detail.vue +1173 -0
- package/src/platform/database/components/database-monitor.vue +1086 -0
- package/src/platform/database/components/db-tools.vue +577 -0
- package/src/platform/database/components/query-history.vue +1349 -0
- package/src/platform/database/components/sql-executor.vue +738 -0
- package/src/platform/database/components/sql-query-editor.vue +1046 -0
- package/src/platform/database/components/table-detail.vue +1376 -0
- package/src/platform/database/components/table-editor.vue +690 -0
- package/src/platform/database/explorer.vue +1840 -0
- package/src/platform/database/index.vue +1193 -0
- package/src/platform/database/layout.vue +367 -0
- package/src/platform/database/router.ts +37 -0
- package/src/platform/database/styles/common.scss +602 -0
- package/src/platform/database/types/common.ts +445 -0
- package/src/platform/database/utils/export.ts +232 -0
- package/src/platform/database/utils/helpers.ts +437 -0
- package/src/platform/index.ts +33 -0
- package/src/platform/router.ts +41 -0
- package/src/service/base.ts +128 -0
- package/src/service/database.ts +500 -0
- package/src/service/login.ts +121 -0
- package/src/shims-vue.d.ts +7 -0
- package/src/stores/connection.ts +266 -0
- package/src/stores/session.ts +87 -0
- package/src/typings/database-types.ts +413 -0
- package/src/typings/database.ts +364 -0
- package/src/typings/global.d.ts +58 -0
- package/src/typings/pinia.d.ts +8 -0
- package/src/utils/clipboard.ts +30 -0
- package/src/utils/database-types.ts +243 -0
- package/src/utils/modal.ts +124 -0
- package/src/utils/request.ts +55 -0
- package/src/utils/sleep.ts +4 -0
- package/src/utils/toast.ts +73 -0
- package/src/utils/util.ts +171 -0
- package/src/utils/xlsx.ts +228 -0
- package/tsconfig.json +33 -0
- package/tsconfig.server.json +19 -0
- package/view/index.html +9 -0
- package/view/modules/header.tpl +14 -0
- package/view/modules/initial_state.tpl +20 -0
- package/vite.config.ts +384 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Provide, Scope, ScopeEnum, Config, Inject } from '@midwayjs/core';
|
|
2
|
+
import { ISessionService, TencentService } from '@cicctencent/midwayjs-base';
|
|
3
|
+
import { Session, GetLoginSessionReq, GetLoginSessionRes, LogoutReq, LogoutRes, LoginByWxReq, LoginByWxRsp, LoginByAccountReq, LoginByAccountRsp } from '@fefeding/common/dist/models/account/session';
|
|
4
|
+
|
|
5
|
+
@Provide('session:service')
|
|
6
|
+
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
|
7
|
+
export class SessionService extends ISessionService {
|
|
8
|
+
@Config('loginOption')
|
|
9
|
+
loginOption: any;
|
|
10
|
+
|
|
11
|
+
@Inject()
|
|
12
|
+
tencentService: TencentService;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 根据ID获取session
|
|
16
|
+
* 并判断session是否在有效期
|
|
17
|
+
* @param id token唯一
|
|
18
|
+
*/
|
|
19
|
+
async getLoginSession(id: string): Promise<Session> {
|
|
20
|
+
const req = new GetLoginSessionReq();
|
|
21
|
+
req.id = id;
|
|
22
|
+
const res = await this.requestBaseApi<GetLoginSessionRes>(req);
|
|
23
|
+
return res?.data || null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 下线
|
|
27
|
+
* @param id 需要下线的id或者session
|
|
28
|
+
*/
|
|
29
|
+
async logout(id: string): Promise<any> {
|
|
30
|
+
const req = new LogoutReq();
|
|
31
|
+
req.id = id;
|
|
32
|
+
const res = await this.requestBaseApi<LogoutRes>(req);
|
|
33
|
+
this.ctx.currentSession = null;
|
|
34
|
+
return res;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 登录接口
|
|
39
|
+
* @param loginParams 登录参数
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
async loginByWx(loginParams: LoginByWxReq) {
|
|
43
|
+
const req = new LoginByWxReq();
|
|
44
|
+
req.fromJSON(loginParams);
|
|
45
|
+
const res = await this.requestBaseApi<LoginByWxRsp>(req);
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 帐号登陆
|
|
51
|
+
* @param loginParams
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
async loginByAccount(loginParams: LoginByAccountReq) {
|
|
55
|
+
loginParams.appId = '0';//this.baseServiceOption.appId?.toString() || '0';
|
|
56
|
+
|
|
57
|
+
const req = new LoginByAccountReq();
|
|
58
|
+
req.fromJSON(loginParams);
|
|
59
|
+
const res = await this.requestBaseApi<LoginByAccountRsp>(req);
|
|
60
|
+
return res;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 用临时码登陆
|
|
65
|
+
* @param code 登陆临时码
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
async loginByCode(code: string) {
|
|
69
|
+
const res = await this.requestBaseApi('/api/session/loginByAuthCode', {
|
|
70
|
+
data: {
|
|
71
|
+
code
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return res?.data || null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 生成临时登陆码
|
|
79
|
+
* @param id 登陆token
|
|
80
|
+
* @returns
|
|
81
|
+
*/
|
|
82
|
+
async createAuthCode(id: string) {
|
|
83
|
+
const res = await this.requestBaseApi('/api/session/createAuthCode', {
|
|
84
|
+
data: {
|
|
85
|
+
id
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return res;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 生成登陆用公众号二维码
|
|
92
|
+
// 先生成一个验证码,当用户扫码后,事件回调获取验证码后再生成session
|
|
93
|
+
async createWxLoginQrcode() {
|
|
94
|
+
|
|
95
|
+
const res = await this.requestBaseApi('/api/session/createWxLoginQrcode', {
|
|
96
|
+
data: {
|
|
97
|
+
appId: this.loginOption.wxAppId
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
//console.log(res);
|
|
101
|
+
return res;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 验证码登陆
|
|
105
|
+
async loginByVerifyCode(code: string, appId?: number,prefix?: string) {
|
|
106
|
+
if(!code) throw Error('code不可为空');
|
|
107
|
+
appId = appId || this.loginOption.wxAppId;
|
|
108
|
+
|
|
109
|
+
const res = await this.requestBaseApi('/api/session/loginByVerifyCode', {
|
|
110
|
+
data: {
|
|
111
|
+
appId,
|
|
112
|
+
code,
|
|
113
|
+
prefix
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return res;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 更新用户信息
|
|
120
|
+
async updateUser(user: any) {
|
|
121
|
+
const userId = this.ctx.currentSession?.userId || 0;
|
|
122
|
+
if(!userId) return;
|
|
123
|
+
//console.log(loginParams, req);
|
|
124
|
+
const res = await this.requestBaseApi('/api/account/updateUser', {
|
|
125
|
+
data: {
|
|
126
|
+
user: {
|
|
127
|
+
...user,
|
|
128
|
+
id: userId,
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
params: {
|
|
132
|
+
token: this.ctx.currentSession?.id
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
console.log('updateUser', res);
|
|
136
|
+
return res;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 上传头像图片
|
|
140
|
+
async uploadAvatar(file: any) {
|
|
141
|
+
|
|
142
|
+
const userId = this.ctx.currentSession?.userId || 0;
|
|
143
|
+
if(!userId) return;
|
|
144
|
+
|
|
145
|
+
let filename = file['filename'] as string || '1.png';
|
|
146
|
+
|
|
147
|
+
const key = `avator/${userId}/${filename}`;
|
|
148
|
+
|
|
149
|
+
const res = await this.tencentService.uploadCosFile(key, file.data);
|
|
150
|
+
console.log(res);
|
|
151
|
+
const user = {
|
|
152
|
+
id: userId,
|
|
153
|
+
avatar: res.url || key,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return await this.updateUser(user);
|
|
157
|
+
}
|
|
158
|
+
}
|
package/server.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const express = require('express');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
// 日志文件路径 - 使用绝对路径
|
|
8
|
+
const logFilePath = path.resolve(__dirname, 'server.log');
|
|
9
|
+
|
|
10
|
+
// 重定向控制台输出到日志文件
|
|
11
|
+
const logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
|
|
12
|
+
|
|
13
|
+
// 保存原始的 console.log 和 console.error
|
|
14
|
+
const originalLog = console.log;
|
|
15
|
+
const originalError = console.error;
|
|
16
|
+
|
|
17
|
+
// 重写 console.log
|
|
18
|
+
console.log = function(...args) {
|
|
19
|
+
const output = args.join(' ') + '\n';
|
|
20
|
+
logStream.write(output);
|
|
21
|
+
originalLog.apply(console, args);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// 重写 console.error
|
|
25
|
+
console.error = function(...args) {
|
|
26
|
+
const output = args.join(' ') + '\n';
|
|
27
|
+
logStream.write(output);
|
|
28
|
+
originalError.apply(console, args);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 创建 express 应用
|
|
32
|
+
const app = express();
|
|
33
|
+
|
|
34
|
+
// 静态文件目录
|
|
35
|
+
const staticDir = path.join(__dirname, 'dist');
|
|
36
|
+
|
|
37
|
+
// 解析 JSON 请求体
|
|
38
|
+
app.use(express.json());
|
|
39
|
+
|
|
40
|
+
// 设置 CORS 头
|
|
41
|
+
app.use((req, res, next) => {
|
|
42
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
43
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
44
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
45
|
+
next();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// 处理 API 请求
|
|
49
|
+
app.use('/api/', async (req, res, next) => {
|
|
50
|
+
if (req.method === 'POST') {
|
|
51
|
+
try {
|
|
52
|
+
const serverModule = require('./dist/server/index.js');
|
|
53
|
+
const handleDatabaseRoutes = serverModule.handleDatabaseRoutes;
|
|
54
|
+
|
|
55
|
+
// 调用 handleDatabaseRoutes 函数处理请求
|
|
56
|
+
const result = await handleDatabaseRoutes(req.originalUrl, req.body);
|
|
57
|
+
|
|
58
|
+
// 返回处理结果
|
|
59
|
+
res.status(200).json({
|
|
60
|
+
ret: 0,
|
|
61
|
+
msg: 'success',
|
|
62
|
+
data: result
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('API Error:', error);
|
|
66
|
+
res.status(500).json({
|
|
67
|
+
ret: 500,
|
|
68
|
+
msg: error.message || 'Internal server error'
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
next();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 配置静态文件目录 - 只有 /public 请求指向 public 目录
|
|
77
|
+
app.use('/public', express.static(path.join(staticDir, 'public')));
|
|
78
|
+
|
|
79
|
+
// 所有未匹配的路由都指向 index.html
|
|
80
|
+
app.use((req, res) => {
|
|
81
|
+
const indexPath = path.join(staticDir, 'view', 'index.html');
|
|
82
|
+
res.sendFile(indexPath, (err) => {
|
|
83
|
+
if (err) {
|
|
84
|
+
res.status(500).send('Error loading index.html');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 解析命令行参数获取端口
|
|
90
|
+
let portFromArgs;
|
|
91
|
+
for (let i = 0; i < process.argv.length; i++) {
|
|
92
|
+
if ((process.argv[i] === '--port' || process.argv[i] === '-p') && process.argv[i + 1]) {
|
|
93
|
+
portFromArgs = parseInt(process.argv[i + 1]);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 启动服务器
|
|
99
|
+
const PORT = portFromArgs || process.env.PORT || 9300;
|
|
100
|
+
app.listen(PORT, () => {
|
|
101
|
+
|
|
102
|
+
// 将 PID 写入 PID 文件
|
|
103
|
+
const pidFilePath = path.join(__dirname, 'server.pid');
|
|
104
|
+
fs.writeFileSync(pidFilePath, process.pid.toString());
|
|
105
|
+
console.log(`PID ${process.pid} written to ${pidFilePath}`);
|
|
106
|
+
|
|
107
|
+
console.log(`Server is running on port ${PORT}`);
|
|
108
|
+
console.log(`http://localhost:${PORT}`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 处理进程退出事件,关闭日志流
|
|
112
|
+
process.on('exit', () => {
|
|
113
|
+
logStream.end();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 处理未捕获的异常
|
|
117
|
+
process.on('uncaughtException', (err) => {
|
|
118
|
+
console.error('Uncaught exception:', err);
|
|
119
|
+
logStream.end();
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// 处理未处理的 Promise 拒绝
|
|
124
|
+
process.on('unhandledRejection', (err) => {
|
|
125
|
+
console.error('Unhandled rejection:', err);
|
|
126
|
+
logStream.end();
|
|
127
|
+
process.exit(1);
|
|
128
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import baseConf from '@/base/config';
|
|
4
|
+
export const pendingMap = new Map();
|
|
5
|
+
export const service = axios.create({
|
|
6
|
+
baseURL: `${baseConf.baseURL}`, // 设置统一的请求前缀// http://localhost:8888
|
|
7
|
+
timeout: 30000, // 设置统一的超时时长
|
|
8
|
+
});
|
|
9
|
+
service.interceptors.request.use(
|
|
10
|
+
config => {
|
|
11
|
+
const pendingKey = getPendingKey(config);
|
|
12
|
+
if (pendingMap.has(pendingKey)) {
|
|
13
|
+
const controller = pendingMap.get(pendingKey);
|
|
14
|
+
controller.abort();
|
|
15
|
+
} else {
|
|
16
|
+
addPending(config);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return config;
|
|
20
|
+
},
|
|
21
|
+
error => {
|
|
22
|
+
return Promise.reject(error);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
service.interceptors.response.use(
|
|
26
|
+
response => {
|
|
27
|
+
removePending(response.config);
|
|
28
|
+
return response;
|
|
29
|
+
},
|
|
30
|
+
error => {
|
|
31
|
+
error.config && removePending(error.config);
|
|
32
|
+
error.message = getHttpErrorMsg(error);
|
|
33
|
+
return Promise.reject(error);
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
type Config = AxiosRequestConfig & { debounceRequest?: boolean };
|
|
37
|
+
export function request(axiosConfig: Config): Promise<AxiosResponse<any, any>> {
|
|
38
|
+
// 自定义配置
|
|
39
|
+
const options = Object.assign(
|
|
40
|
+
{
|
|
41
|
+
debounceRequest: true, // 是否开启取消重复请求, 默认为 true
|
|
42
|
+
},
|
|
43
|
+
axiosConfig
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return service(options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 生成每个请求唯一的键
|
|
51
|
+
* @param {*} config
|
|
52
|
+
* @returns string
|
|
53
|
+
*/
|
|
54
|
+
function getPendingKey(config: AxiosRequestConfig) {
|
|
55
|
+
const { url, method, params } = config;
|
|
56
|
+
let { data } = config;
|
|
57
|
+
if (typeof data === 'string') {
|
|
58
|
+
data = JSON.parse(data);
|
|
59
|
+
}
|
|
60
|
+
// 以url和...组成字符串作为储存的key值
|
|
61
|
+
return [url, method, JSON.stringify(params), JSON.stringify(data)].join(
|
|
62
|
+
'&'
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
|
|
67
|
+
*
|
|
68
|
+
* @param {*} config
|
|
69
|
+
*/
|
|
70
|
+
function addPending(config: AxiosRequestConfig) {
|
|
71
|
+
const pendingKey = getPendingKey(config);
|
|
72
|
+
const controller = new AbortController();
|
|
73
|
+
config.signal = controller.signal;
|
|
74
|
+
pendingMap.set(pendingKey, controller);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 删除重复的请求key
|
|
78
|
+
* @param {*} config
|
|
79
|
+
*/
|
|
80
|
+
function removePending(config: AxiosRequestConfig) {
|
|
81
|
+
const pendingKey = getPendingKey(config);
|
|
82
|
+
if (pendingMap.has(pendingKey)) {
|
|
83
|
+
pendingMap.delete(pendingKey);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 取消所有请求
|
|
88
|
+
* @param {*} config
|
|
89
|
+
*/
|
|
90
|
+
export function abortAllPending() {
|
|
91
|
+
for (const [key, value] of pendingMap.entries()) {
|
|
92
|
+
value.abort();
|
|
93
|
+
pendingMap.delete(key);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 处理异常
|
|
98
|
+
* @param {*} error
|
|
99
|
+
*/
|
|
100
|
+
function getHttpErrorMsg(error: any) {
|
|
101
|
+
let message = '';
|
|
102
|
+
// 处理被取消的请求
|
|
103
|
+
if (axios.isCancel(error)) {
|
|
104
|
+
console.error(
|
|
105
|
+
`重复请求:${(error as any).config.url} ${error.message}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (error && error.response) {
|
|
110
|
+
switch (error.response.status) {
|
|
111
|
+
case 302:
|
|
112
|
+
message = '接口重定向了!';
|
|
113
|
+
break;
|
|
114
|
+
case 400:
|
|
115
|
+
message = '参数不正确!';
|
|
116
|
+
break;
|
|
117
|
+
case 401:
|
|
118
|
+
message = '您未登录,或者登录已经超时,请先登录!';
|
|
119
|
+
break;
|
|
120
|
+
case 403:
|
|
121
|
+
message = '您没有权限操作!';
|
|
122
|
+
break;
|
|
123
|
+
case 504:
|
|
124
|
+
message = '服务暂时无法访问,请稍后再试!';
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
message = '异常问题,请联系管理员!';
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (error.message.includes('timeout')) message = '网络请求超时!';
|
|
132
|
+
if (error.message.includes('Network'))
|
|
133
|
+
message = window.navigator.onLine ? '服务端异常!' : '您断网了!';
|
|
134
|
+
return message;
|
|
135
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* color palette from <https://github.com/vuejs/theme> */
|