@robot-admin/request-core 0.2.0 → 0.4.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/CHANGELOG.md +102 -0
- package/LICENSE +21 -0
- package/README.md +248 -357
- package/SECURITY.md +14 -0
- package/dist/axios.cjs +134 -809
- package/dist/axios.cjs.map +1 -1
- package/dist/axios.d.cts +55 -220
- package/dist/axios.d.ts +55 -220
- package/dist/axios.js +2 -790
- package/dist/axios.js.map +1 -1
- package/dist/chunk-2JXH7SIL.js +711 -0
- package/dist/chunk-2JXH7SIL.js.map +1 -0
- package/dist/chunk-56QOEWUS.js +8 -0
- package/dist/chunk-56QOEWUS.js.map +1 -0
- package/dist/chunk-DUP3Y4DN.js +320 -0
- package/dist/chunk-DUP3Y4DN.js.map +1 -0
- package/dist/chunk-JGFRUAZT.cjs +1007 -0
- package/dist/chunk-JGFRUAZT.cjs.map +1 -0
- package/dist/chunk-KHI6XQRN.cjs +717 -0
- package/dist/chunk-KHI6XQRN.cjs.map +1 -0
- package/dist/chunk-OAZ5BUBU.js +969 -0
- package/dist/chunk-OAZ5BUBU.js.map +1 -0
- package/dist/chunk-QSDNDTOZ.js +28 -0
- package/dist/chunk-QSDNDTOZ.js.map +1 -0
- package/dist/chunk-UHXBAFY6.cjs +323 -0
- package/dist/chunk-UHXBAFY6.cjs.map +1 -0
- package/dist/chunk-WUZ43MLM.cjs +30 -0
- package/dist/chunk-WUZ43MLM.cjs.map +1 -0
- package/dist/chunk-WXHQXPS4.cjs +10 -0
- package/dist/chunk-WXHQXPS4.cjs.map +1 -0
- package/dist/crud.cjs +12 -484
- package/dist/crud.cjs.map +1 -1
- package/dist/crud.d.cts +8 -269
- package/dist/crud.d.ts +8 -269
- package/dist/crud.js +4 -487
- package/dist/crud.js.map +1 -1
- package/dist/index.cjs +136 -1302
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -165
- package/dist/index.d.ts +7 -165
- package/dist/index.js +5 -1283
- package/dist/index.js.map +1 -1
- package/dist/naive.cjs +14 -0
- package/dist/naive.cjs.map +1 -0
- package/dist/naive.d.cts +9 -0
- package/dist/naive.d.ts +9 -0
- package/dist/naive.js +5 -0
- package/dist/naive.js.map +1 -0
- package/dist/types-BRDRqYFs.d.cts +197 -0
- package/dist/types-BVJhlSuh.d.cts +310 -0
- package/dist/types-BVJhlSuh.d.ts +310 -0
- package/dist/types-CUyibJZX.d.ts +197 -0
- package/dist/vue.cjs +93 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +38 -0
- package/dist/vue.d.ts +38 -0
- package/dist/vue.js +71 -0
- package/dist/vue.js.map +1 -0
- package/package.json +60 -16
package/dist/index.js
CHANGED
|
@@ -1,1285 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// src/axios/plugins/request.ts
|
|
8
|
-
var reLoginPromise = null;
|
|
9
|
-
var reLoginResolve = null;
|
|
10
|
-
var reLoginReject = null;
|
|
11
|
-
function waitForReLogin() {
|
|
12
|
-
if (!reLoginPromise) {
|
|
13
|
-
reLoginPromise = new Promise((resolve, reject) => {
|
|
14
|
-
reLoginResolve = resolve;
|
|
15
|
-
reLoginReject = reject;
|
|
16
|
-
}).finally(() => {
|
|
17
|
-
reLoginPromise = null;
|
|
18
|
-
reLoginResolve = null;
|
|
19
|
-
reLoginReject = null;
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
return reLoginPromise;
|
|
23
|
-
}
|
|
24
|
-
function getReLoginPromise() {
|
|
25
|
-
return reLoginPromise;
|
|
26
|
-
}
|
|
27
|
-
function resolveReLogin() {
|
|
28
|
-
if (reLoginResolve) {
|
|
29
|
-
reLoginResolve();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function rejectReLogin(reason) {
|
|
33
|
-
if (reLoginReject) {
|
|
34
|
-
reLoginReject(reason);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// src/axios/utils/abort.ts
|
|
39
|
-
function ensureSharedAbortController(config) {
|
|
40
|
-
if (typeof AbortController === "undefined") return null;
|
|
41
|
-
const existing = config.__abortController;
|
|
42
|
-
if (existing) {
|
|
43
|
-
existing._startTime ?? (existing._startTime = Date.now());
|
|
44
|
-
config.signal = existing.signal;
|
|
45
|
-
return existing;
|
|
46
|
-
}
|
|
47
|
-
const externalSignal = config.signal;
|
|
48
|
-
const controller = new AbortController();
|
|
49
|
-
controller._startTime = Date.now();
|
|
50
|
-
if (externalSignal && externalSignal !== controller.signal) {
|
|
51
|
-
config.__externalSignal = externalSignal;
|
|
52
|
-
const forwardAbort = () => {
|
|
53
|
-
if (!controller.signal.aborted) {
|
|
54
|
-
controller.abort(externalSignal.reason);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
if (externalSignal.aborted) {
|
|
58
|
-
forwardAbort();
|
|
59
|
-
} else {
|
|
60
|
-
externalSignal.addEventListener?.("abort", forwardAbort, { once: true });
|
|
61
|
-
config.__abortCleanup = () => {
|
|
62
|
-
externalSignal.removeEventListener?.("abort", forwardAbort);
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
config.__abortController = controller;
|
|
67
|
-
config.signal = controller.signal;
|
|
68
|
-
return controller;
|
|
69
|
-
}
|
|
70
|
-
function cleanupAbortContext(config) {
|
|
71
|
-
if (!config) return;
|
|
72
|
-
config.__abortCleanup?.();
|
|
73
|
-
if (config.__externalSignal) {
|
|
74
|
-
config.signal = config.__externalSignal;
|
|
75
|
-
} else if (config.signal === config.__abortController?.signal) {
|
|
76
|
-
delete config.signal;
|
|
77
|
-
}
|
|
78
|
-
delete config.__abortCleanup;
|
|
79
|
-
delete config.__externalSignal;
|
|
80
|
-
delete config.__abortController;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// src/axios/utils/helpers.ts
|
|
84
|
-
var binaryObjectIds = /* @__PURE__ */ new WeakMap();
|
|
85
|
-
var nextBinaryObjectId = 0;
|
|
86
|
-
function getBinaryObjectId(value) {
|
|
87
|
-
let id = binaryObjectIds.get(value);
|
|
88
|
-
if (id === void 0) {
|
|
89
|
-
id = ++nextBinaryObjectId;
|
|
90
|
-
binaryObjectIds.set(value, id);
|
|
91
|
-
}
|
|
92
|
-
return id;
|
|
93
|
-
}
|
|
94
|
-
function sortedStringify(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
95
|
-
if (obj === null || obj === void 0) {
|
|
96
|
-
return "";
|
|
97
|
-
}
|
|
98
|
-
if (typeof obj === "bigint") return `bigint:${obj.toString()}`;
|
|
99
|
-
if (typeof obj !== "object") {
|
|
100
|
-
return `${typeof obj}:${String(obj)}`;
|
|
101
|
-
}
|
|
102
|
-
if (seen.has(obj)) {
|
|
103
|
-
throw new Error("\u68C0\u6D4B\u5230\u5FAA\u73AF\u5F15\u7528\uFF0C\u65E0\u6CD5\u751F\u6210\u7A33\u5B9A\u7684\u7F13\u5B58\u952E");
|
|
104
|
-
}
|
|
105
|
-
seen.add(obj);
|
|
106
|
-
try {
|
|
107
|
-
if (Array.isArray(obj)) {
|
|
108
|
-
return `[${obj.map((item) => sortedStringify(item, seen)).join(",")}]`;
|
|
109
|
-
}
|
|
110
|
-
if (obj instanceof Date) return `date:${obj.toISOString()}`;
|
|
111
|
-
if (typeof URLSearchParams !== "undefined" && obj instanceof URLSearchParams) {
|
|
112
|
-
return `url-search:${JSON.stringify(Array.from(obj.entries()).sort())}`;
|
|
113
|
-
}
|
|
114
|
-
if (typeof FormData !== "undefined" && obj instanceof FormData) {
|
|
115
|
-
const entries = Array.from(obj.entries()).map(([key, value]) => [
|
|
116
|
-
key,
|
|
117
|
-
typeof value === "string" ? `string:${value}` : `binary:${getBinaryObjectId(value)}:${value.name}:${value.size}:${value.type}`
|
|
118
|
-
]);
|
|
119
|
-
return `form-data:${JSON.stringify(entries)}`;
|
|
120
|
-
}
|
|
121
|
-
if (typeof Blob !== "undefined" && obj instanceof Blob || obj instanceof ArrayBuffer || ArrayBuffer.isView(obj)) {
|
|
122
|
-
return `binary:${getBinaryObjectId(obj)}`;
|
|
123
|
-
}
|
|
124
|
-
const source = typeof obj.toJSON === "function" && obj.constructor?.name === "AxiosHeaders" ? obj.toJSON() : obj;
|
|
125
|
-
const sortedKeys = Object.keys(source).sort();
|
|
126
|
-
return `{${sortedKeys.map((key) => `${JSON.stringify(key)}:${sortedStringify(source[key], seen)}`).join(",")}}`;
|
|
127
|
-
} finally {
|
|
128
|
-
seen.delete(obj);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function generateRequestKey(config) {
|
|
132
|
-
const { method = "get", url = "", params, data, headers } = config;
|
|
133
|
-
const parts = [method.toUpperCase(), url];
|
|
134
|
-
if (params != null) {
|
|
135
|
-
parts.push(sortedStringify(params));
|
|
136
|
-
}
|
|
137
|
-
if (data != null) {
|
|
138
|
-
parts.push(sortedStringify(data));
|
|
139
|
-
}
|
|
140
|
-
if (headers) {
|
|
141
|
-
const authHeaders = {};
|
|
142
|
-
const authKeys = ["authorization", "x-tenant-id", "x-user-id"];
|
|
143
|
-
const lowerHeaders = {};
|
|
144
|
-
const headerSource = typeof headers.toJSON === "function" ? headers.toJSON() : headers;
|
|
145
|
-
for (const [k, v] of Object.entries(headerSource)) {
|
|
146
|
-
lowerHeaders[String(k).toLowerCase()] = v;
|
|
147
|
-
}
|
|
148
|
-
for (const key of authKeys) {
|
|
149
|
-
if (lowerHeaders[key] != null) {
|
|
150
|
-
authHeaders[key] = String(lowerHeaders[key]);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (Object.keys(authHeaders).length > 0) {
|
|
154
|
-
parts.push(sortedStringify(authHeaders));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return parts.join("|");
|
|
158
|
-
}
|
|
159
|
-
var MemoryCache = class {
|
|
160
|
-
constructor() {
|
|
161
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
162
|
-
this.maxSize = 1e3;
|
|
163
|
-
// 最大缓存数量
|
|
164
|
-
this.accessOrder = /* @__PURE__ */ new Set();
|
|
165
|
-
}
|
|
166
|
-
// 记录访问顺序
|
|
167
|
-
/**
|
|
168
|
-
* 获取缓存
|
|
169
|
-
*/
|
|
170
|
-
get(key) {
|
|
171
|
-
const item = this.cache.get(key);
|
|
172
|
-
if (!item) return null;
|
|
173
|
-
if (Date.now() > item.expireAt) {
|
|
174
|
-
this.cache.delete(key);
|
|
175
|
-
this.accessOrder.delete(key);
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
this.accessOrder.delete(key);
|
|
179
|
-
this.accessOrder.add(key);
|
|
180
|
-
return item.data;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* 设置缓存
|
|
184
|
-
*/
|
|
185
|
-
set(key, data, ttl) {
|
|
186
|
-
if (!Number.isFinite(ttl) || ttl < 0) {
|
|
187
|
-
throw new RangeError("\u7F13\u5B58 TTL \u5FC5\u987B\u662F\u5927\u4E8E\u6216\u7B49\u4E8E 0 \u7684\u6709\u9650\u6570\u503C");
|
|
188
|
-
}
|
|
189
|
-
if (this.maxSize === 0) return;
|
|
190
|
-
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
191
|
-
this.evictOldest();
|
|
192
|
-
}
|
|
193
|
-
const expireAt = Date.now() + ttl;
|
|
194
|
-
this.cache.set(key, {
|
|
195
|
-
data,
|
|
196
|
-
expireAt
|
|
197
|
-
});
|
|
198
|
-
this.accessOrder.delete(key);
|
|
199
|
-
this.accessOrder.add(key);
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* 删除缓存
|
|
203
|
-
*/
|
|
204
|
-
delete(key) {
|
|
205
|
-
this.accessOrder.delete(key);
|
|
206
|
-
return this.cache.delete(key);
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* 清空所有缓存
|
|
210
|
-
*/
|
|
211
|
-
clear() {
|
|
212
|
-
this.cache.clear();
|
|
213
|
-
this.accessOrder.clear();
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* 清理过期缓存
|
|
217
|
-
*/
|
|
218
|
-
cleanup() {
|
|
219
|
-
const now = Date.now();
|
|
220
|
-
const entries = Array.from(this.cache.entries());
|
|
221
|
-
for (const [key, item] of entries) {
|
|
222
|
-
if (now > item.expireAt) {
|
|
223
|
-
this.cache.delete(key);
|
|
224
|
-
this.accessOrder.delete(key);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* 获取缓存大小
|
|
230
|
-
*/
|
|
231
|
-
get size() {
|
|
232
|
-
return this.cache.size;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* 设置最大缓存大小
|
|
236
|
-
*/
|
|
237
|
-
setMaxSize(size) {
|
|
238
|
-
if (!Number.isInteger(size) || size < 0) {
|
|
239
|
-
throw new RangeError("\u7F13\u5B58\u6700\u5927\u5BB9\u91CF\u5FC5\u987B\u662F\u5927\u4E8E\u6216\u7B49\u4E8E 0 \u7684\u6574\u6570");
|
|
240
|
-
}
|
|
241
|
-
this.maxSize = size;
|
|
242
|
-
while (this.cache.size > this.maxSize) {
|
|
243
|
-
this.evictOldest();
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* 清理最旧的缓存(LRU)
|
|
248
|
-
*/
|
|
249
|
-
evictOldest() {
|
|
250
|
-
const oldestKey = this.accessOrder.values().next().value;
|
|
251
|
-
if (oldestKey) {
|
|
252
|
-
this.cache.delete(oldestKey);
|
|
253
|
-
this.accessOrder.delete(oldestKey);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
var globalCache = new MemoryCache();
|
|
258
|
-
function delay(ms, signal) {
|
|
259
|
-
if (signal?.aborted) {
|
|
260
|
-
return Promise.reject(createAbortError(signal.reason));
|
|
261
|
-
}
|
|
262
|
-
return new Promise((resolve, reject) => {
|
|
263
|
-
const timer = setTimeout(() => {
|
|
264
|
-
signal?.removeEventListener?.("abort", onAbort);
|
|
265
|
-
resolve();
|
|
266
|
-
}, Math.max(0, Number.isFinite(ms) ? ms : 0));
|
|
267
|
-
const onAbort = () => {
|
|
268
|
-
clearTimeout(timer);
|
|
269
|
-
signal?.removeEventListener?.("abort", onAbort);
|
|
270
|
-
reject(createAbortError(signal?.reason));
|
|
271
|
-
};
|
|
272
|
-
signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
function createAbortError(reason) {
|
|
276
|
-
if (reason instanceof Error) return reason;
|
|
277
|
-
return Object.assign(new Error("canceled"), {
|
|
278
|
-
name: "AbortError",
|
|
279
|
-
code: "ERR_CANCELED",
|
|
280
|
-
reason
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
function isNetworkError(error) {
|
|
284
|
-
return !error.response && Boolean(error.code) && error.code !== "ECONNABORTED" && error.code !== "ERR_CANCELED" && error.message !== "canceled" && error.message !== "Request aborted" && error.message !== "Request cancelled";
|
|
285
|
-
}
|
|
286
|
-
function isTimeoutError(error) {
|
|
287
|
-
return error?.code === "ECONNABORTED" || error?.code === "ETIMEDOUT";
|
|
288
|
-
}
|
|
289
|
-
function isRetryableStatus(status, retryableStatusCodes) {
|
|
290
|
-
return retryableStatusCodes.includes(status);
|
|
291
|
-
}
|
|
292
|
-
function normalizeConfig(config, defaults) {
|
|
293
|
-
if (config === true) {
|
|
294
|
-
return { ...defaults, enabled: true };
|
|
295
|
-
}
|
|
296
|
-
if (config === false) {
|
|
297
|
-
return { ...defaults, enabled: false };
|
|
298
|
-
}
|
|
299
|
-
if (config && typeof config === "object") {
|
|
300
|
-
const definedEntries = Object.entries(config).filter(
|
|
301
|
-
([, value]) => value !== void 0
|
|
302
|
-
);
|
|
303
|
-
return { ...defaults, ...Object.fromEntries(definedEntries) };
|
|
304
|
-
}
|
|
305
|
-
return defaults;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// src/axios/plugins/dedupe.ts
|
|
309
|
-
var DEFAULT_DEDUPE_CONFIG = {
|
|
310
|
-
enabled: true,
|
|
311
|
-
keyGenerator: generateRequestKey
|
|
312
|
-
};
|
|
313
|
-
var pendingRequests = /* @__PURE__ */ new Map();
|
|
314
|
-
var CLEANUP_INTERVAL = 3e4;
|
|
315
|
-
var REQUEST_TIMEOUT = 5 * 60 * 1e3;
|
|
316
|
-
var cleanupTimer = null;
|
|
317
|
-
function cleanupExpiredRequests() {
|
|
318
|
-
const now = Date.now();
|
|
319
|
-
Array.from(pendingRequests.entries()).forEach(([key, controller]) => {
|
|
320
|
-
const startTime = controller._startTime || now;
|
|
321
|
-
if (now - startTime > REQUEST_TIMEOUT) {
|
|
322
|
-
try {
|
|
323
|
-
controller.abort();
|
|
324
|
-
} catch (error) {
|
|
325
|
-
console.warn("Abort error:", error);
|
|
326
|
-
}
|
|
327
|
-
pendingRequests.delete(key);
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
stopCleanupTimerIfIdle();
|
|
331
|
-
}
|
|
332
|
-
function startCleanupTimer() {
|
|
333
|
-
if (cleanupTimer) return;
|
|
334
|
-
cleanupTimer = setInterval(cleanupExpiredRequests, CLEANUP_INTERVAL);
|
|
335
|
-
cleanupTimer.unref?.();
|
|
336
|
-
}
|
|
337
|
-
function stopCleanupTimerIfIdle() {
|
|
338
|
-
if (pendingRequests.size === 0 && cleanupTimer) {
|
|
339
|
-
clearInterval(cleanupTimer);
|
|
340
|
-
cleanupTimer = null;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
function removePendingRequest(config) {
|
|
344
|
-
const requestKey = config.__requestKey;
|
|
345
|
-
const controller = config.__abortController;
|
|
346
|
-
if (requestKey && controller && pendingRequests.get(requestKey) === controller) {
|
|
347
|
-
pendingRequests.delete(requestKey);
|
|
348
|
-
}
|
|
349
|
-
stopCleanupTimerIfIdle();
|
|
350
|
-
}
|
|
351
|
-
function onRequest(config) {
|
|
352
|
-
const enhancedConfig = config;
|
|
353
|
-
const dedupeConfig = normalizeConfig(
|
|
354
|
-
enhancedConfig.dedupe,
|
|
355
|
-
DEFAULT_DEDUPE_CONFIG
|
|
356
|
-
);
|
|
357
|
-
if (!dedupeConfig.enabled) {
|
|
358
|
-
return config;
|
|
359
|
-
}
|
|
360
|
-
if (config.__fromCache) {
|
|
361
|
-
return config;
|
|
362
|
-
}
|
|
363
|
-
const keyGenerator = dedupeConfig.keyGenerator || DEFAULT_DEDUPE_CONFIG.keyGenerator;
|
|
364
|
-
const requestKey = keyGenerator(config);
|
|
365
|
-
const existing = pendingRequests.get(requestKey);
|
|
366
|
-
if (existing) {
|
|
367
|
-
try {
|
|
368
|
-
existing.abort();
|
|
369
|
-
} catch (error) {
|
|
370
|
-
console.warn("Abort existing request error:", error);
|
|
371
|
-
}
|
|
372
|
-
pendingRequests.delete(requestKey);
|
|
373
|
-
}
|
|
374
|
-
const controller = ensureSharedAbortController(enhancedConfig);
|
|
375
|
-
if (!controller) return config;
|
|
376
|
-
enhancedConfig.__requestKey = requestKey;
|
|
377
|
-
pendingRequests.set(requestKey, controller);
|
|
378
|
-
startCleanupTimer();
|
|
379
|
-
return config;
|
|
380
|
-
}
|
|
381
|
-
function onResponse(response) {
|
|
382
|
-
const config = response.config;
|
|
383
|
-
removePendingRequest(config);
|
|
384
|
-
return response;
|
|
385
|
-
}
|
|
386
|
-
function onResponseError(error) {
|
|
387
|
-
const config = error.config;
|
|
388
|
-
if (config) {
|
|
389
|
-
removePendingRequest(config);
|
|
390
|
-
}
|
|
391
|
-
return Promise.reject(error);
|
|
392
|
-
}
|
|
393
|
-
function setupDedupePlugin(instance) {
|
|
394
|
-
instance.interceptors.request.use(onRequest);
|
|
395
|
-
instance.interceptors.response.use(onResponse, onResponseError);
|
|
396
|
-
}
|
|
397
|
-
function cancelAllPendingRequests() {
|
|
398
|
-
pendingRequests.forEach((controller) => {
|
|
399
|
-
try {
|
|
400
|
-
controller.abort();
|
|
401
|
-
} catch (error) {
|
|
402
|
-
console.warn("Error aborting pending request:", error);
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
pendingRequests.clear();
|
|
406
|
-
stopCleanupTimerIfIdle();
|
|
407
|
-
}
|
|
408
|
-
function getPendingRequestCount() {
|
|
409
|
-
return pendingRequests.size;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// src/axios/plugins/cache.ts
|
|
413
|
-
var DEFAULT_CACHE_CONFIG = {
|
|
414
|
-
enabled: false,
|
|
415
|
-
ttl: 5 * 60 * 1e3,
|
|
416
|
-
// 5 分钟
|
|
417
|
-
forceUpdate: false
|
|
418
|
-
};
|
|
419
|
-
function shouldUseCache(config, cacheConfig) {
|
|
420
|
-
if (config.method?.toUpperCase() !== "GET") {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
if (!cacheConfig.enabled) {
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
if (cacheConfig.forceUpdate) {
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
return true;
|
|
430
|
-
}
|
|
431
|
-
function createCacheResponse(cachedData, config) {
|
|
432
|
-
return {
|
|
433
|
-
data: cachedData.data,
|
|
434
|
-
status: cachedData.status,
|
|
435
|
-
statusText: `${cachedData.statusText} (from cache)`,
|
|
436
|
-
headers: cachedData.headers,
|
|
437
|
-
config
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
function tryGetFromCache(config, cacheConfig) {
|
|
441
|
-
if (!shouldUseCache(config, cacheConfig)) {
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
|
-
const requestKey = generateRequestKey(config);
|
|
445
|
-
const cachedData = globalCache.get(requestKey);
|
|
446
|
-
if (cachedData) {
|
|
447
|
-
return createCacheResponse(cachedData, config);
|
|
448
|
-
}
|
|
449
|
-
return null;
|
|
450
|
-
}
|
|
451
|
-
function saveToCache(response, config, cacheConfig) {
|
|
452
|
-
if (config.method?.toUpperCase() === "GET" && cacheConfig.enabled && response.status === 200) {
|
|
453
|
-
const requestKey = generateRequestKey(config);
|
|
454
|
-
const ttl = cacheConfig.ttl ?? DEFAULT_CACHE_CONFIG.ttl;
|
|
455
|
-
const cachedResponse = {
|
|
456
|
-
data: response.data,
|
|
457
|
-
status: response.status,
|
|
458
|
-
statusText: response.statusText,
|
|
459
|
-
headers: { ...response.headers }
|
|
460
|
-
};
|
|
461
|
-
globalCache.set(requestKey, cachedResponse, ttl);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
function onRequest2(config) {
|
|
465
|
-
const enhancedConfig = config;
|
|
466
|
-
const cacheConfig = normalizeConfig(
|
|
467
|
-
enhancedConfig.cache,
|
|
468
|
-
DEFAULT_CACHE_CONFIG
|
|
469
|
-
);
|
|
470
|
-
const cachedResponse = tryGetFromCache(config, cacheConfig);
|
|
471
|
-
if (cachedResponse) {
|
|
472
|
-
config.__fromCache = true;
|
|
473
|
-
return Promise.reject({
|
|
474
|
-
__fromCache: true,
|
|
475
|
-
__cachedResponse: cachedResponse,
|
|
476
|
-
config
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
return config;
|
|
480
|
-
}
|
|
481
|
-
function onResponse2(response) {
|
|
482
|
-
const config = response.config;
|
|
483
|
-
if (config.__fromCache) {
|
|
484
|
-
return config.__cachedResponse;
|
|
485
|
-
}
|
|
486
|
-
const cacheConfig = normalizeConfig(
|
|
487
|
-
config.cache,
|
|
488
|
-
DEFAULT_CACHE_CONFIG
|
|
489
|
-
);
|
|
490
|
-
saveToCache(response, response.config, cacheConfig);
|
|
491
|
-
return response;
|
|
492
|
-
}
|
|
493
|
-
function onResponseError2(error) {
|
|
494
|
-
if (error.__fromCache) {
|
|
495
|
-
return Promise.resolve(error.__cachedResponse);
|
|
496
|
-
}
|
|
497
|
-
return Promise.reject(error);
|
|
498
|
-
}
|
|
499
|
-
function setupCachePlugin(instance) {
|
|
500
|
-
instance.interceptors.request.use(onRequest2);
|
|
501
|
-
instance.interceptors.response.use(onResponse2, onResponseError2);
|
|
502
|
-
}
|
|
503
|
-
function clearAllCache() {
|
|
504
|
-
globalCache.clear();
|
|
505
|
-
}
|
|
506
|
-
function clearCache(config) {
|
|
507
|
-
const requestKey = generateRequestKey(config);
|
|
508
|
-
return globalCache.delete(requestKey);
|
|
509
|
-
}
|
|
510
|
-
function cleanupExpiredCache() {
|
|
511
|
-
globalCache.cleanup();
|
|
512
|
-
}
|
|
513
|
-
function getCacheSize() {
|
|
514
|
-
return globalCache.size;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// src/axios/plugins/retry.ts
|
|
518
|
-
var DEFAULT_RETRY_CONFIG = {
|
|
519
|
-
enabled: false,
|
|
520
|
-
count: 3,
|
|
521
|
-
delay: 1e3,
|
|
522
|
-
exponentialBackoff: true,
|
|
523
|
-
jitter: true,
|
|
524
|
-
retryableStatusCodes: [408, 429, 500, 502, 503, 504],
|
|
525
|
-
// 默认仅重试幂等方法,避免对 POST 等非幂等请求重复执行造成副作用(重复扣款/重复创建)
|
|
526
|
-
retryableMethods: ["GET", "HEAD", "OPTIONS", "PUT", "DELETE"]
|
|
527
|
-
};
|
|
528
|
-
function isCancelError(error) {
|
|
529
|
-
return error?.name === "CanceledError" || error?.name === "AbortError" || error?.code === "ERR_CANCELED";
|
|
530
|
-
}
|
|
531
|
-
function shouldRetry(error, retryConfig) {
|
|
532
|
-
if (!retryConfig.enabled) {
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
const config = error.config;
|
|
536
|
-
const currentRetryCount = config.__retryCount ?? 0;
|
|
537
|
-
if (currentRetryCount >= retryConfig.count) {
|
|
538
|
-
return false;
|
|
539
|
-
}
|
|
540
|
-
if (isCancelError(error)) {
|
|
541
|
-
return false;
|
|
542
|
-
}
|
|
543
|
-
const method = (config.method || "get").toUpperCase();
|
|
544
|
-
if (!retryConfig.retryableMethods.some(
|
|
545
|
-
(retryableMethod) => retryableMethod.toUpperCase() === method
|
|
546
|
-
)) {
|
|
547
|
-
return false;
|
|
548
|
-
}
|
|
549
|
-
if (isNetworkError(error)) {
|
|
550
|
-
return true;
|
|
551
|
-
}
|
|
552
|
-
if (isTimeoutError(error)) {
|
|
553
|
-
return true;
|
|
554
|
-
}
|
|
555
|
-
if (error.response?.status) {
|
|
556
|
-
return isRetryableStatus(
|
|
557
|
-
error.response.status,
|
|
558
|
-
retryConfig.retryableStatusCodes
|
|
559
|
-
);
|
|
560
|
-
}
|
|
561
|
-
return false;
|
|
562
|
-
}
|
|
563
|
-
function getRetryDelay(retryCount, retryConfig) {
|
|
564
|
-
let calculated;
|
|
565
|
-
if (!retryConfig.exponentialBackoff) {
|
|
566
|
-
calculated = retryConfig.delay;
|
|
567
|
-
} else {
|
|
568
|
-
calculated = retryConfig.delay * Math.pow(2, retryCount - 1);
|
|
569
|
-
}
|
|
570
|
-
if (retryConfig.jitter) {
|
|
571
|
-
const factor = 0.75 + Math.random() * 0.5;
|
|
572
|
-
calculated = Math.round(calculated * factor);
|
|
573
|
-
}
|
|
574
|
-
return Math.min(Math.max(0, calculated), 3e4);
|
|
575
|
-
}
|
|
576
|
-
function setupRetryPlugin(instance) {
|
|
577
|
-
const onResponseError4 = async (error) => {
|
|
578
|
-
const config = error.config;
|
|
579
|
-
if (!config) {
|
|
580
|
-
return Promise.reject(error);
|
|
581
|
-
}
|
|
582
|
-
const retryConfig = normalizeConfig(
|
|
583
|
-
config.retry,
|
|
584
|
-
DEFAULT_RETRY_CONFIG
|
|
585
|
-
);
|
|
586
|
-
if (!shouldRetry(error, retryConfig)) {
|
|
587
|
-
return Promise.reject(error);
|
|
588
|
-
}
|
|
589
|
-
config.__retryCount = (config.__retryCount ?? 0) + 1;
|
|
590
|
-
const retryDelay = getRetryDelay(config.__retryCount, retryConfig);
|
|
591
|
-
try {
|
|
592
|
-
await delay(retryDelay, config.signal);
|
|
593
|
-
} catch (abortError) {
|
|
594
|
-
const error_ = Object.assign(new Error("canceled"), {
|
|
595
|
-
name: "CanceledError",
|
|
596
|
-
code: "ERR_CANCELED",
|
|
597
|
-
config,
|
|
598
|
-
cause: abortError
|
|
599
|
-
});
|
|
600
|
-
return Promise.reject(error_);
|
|
601
|
-
}
|
|
602
|
-
const retryConfig_ = { ...config };
|
|
603
|
-
delete retryConfig_.__cancelId;
|
|
604
|
-
delete retryConfig_.__requestKey;
|
|
605
|
-
return instance.request(retryConfig_);
|
|
606
|
-
};
|
|
607
|
-
instance.interceptors.response.use(void 0, onResponseError4);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// src/axios/plugins/response.ts
|
|
611
|
-
function setupResponsePlugin(instance) {
|
|
612
|
-
instance.interceptors.response.use(
|
|
613
|
-
(response) => {
|
|
614
|
-
cleanupAbortContext(response.config);
|
|
615
|
-
return response;
|
|
616
|
-
},
|
|
617
|
-
(error) => {
|
|
618
|
-
cleanupAbortContext(error?.config);
|
|
619
|
-
return Promise.reject(error);
|
|
620
|
-
}
|
|
621
|
-
);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// src/axios/plugins/cancel.ts
|
|
625
|
-
var DEFAULT_CANCEL_CONFIG = {
|
|
626
|
-
enabled: true,
|
|
627
|
-
whitelist: []
|
|
628
|
-
};
|
|
629
|
-
var cancelableRequests = /* @__PURE__ */ new Map();
|
|
630
|
-
var requestId = 0;
|
|
631
|
-
var CLEANUP_INTERVAL2 = 3e4;
|
|
632
|
-
var REQUEST_TIMEOUT2 = 3e5;
|
|
633
|
-
var cleanupTimer2 = null;
|
|
634
|
-
function cleanupExpiredRequests2() {
|
|
635
|
-
const now = Date.now();
|
|
636
|
-
const expiredKeys = [];
|
|
637
|
-
for (const [key, controller] of cancelableRequests.entries()) {
|
|
638
|
-
const requestStartTime = controller._startTime || now;
|
|
639
|
-
if (now - requestStartTime > REQUEST_TIMEOUT2) {
|
|
640
|
-
expiredKeys.push(key);
|
|
641
|
-
try {
|
|
642
|
-
controller.abort();
|
|
643
|
-
} catch (error) {
|
|
644
|
-
console.warn("Error aborting expired request:", error);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
expiredKeys.forEach((key) => cancelableRequests.delete(key));
|
|
649
|
-
stopCleanupTimerIfIdle2();
|
|
650
|
-
}
|
|
651
|
-
function startCleanupTimer2() {
|
|
652
|
-
if (cleanupTimer2) return;
|
|
653
|
-
cleanupTimer2 = setInterval(cleanupExpiredRequests2, CLEANUP_INTERVAL2);
|
|
654
|
-
cleanupTimer2.unref?.();
|
|
655
|
-
}
|
|
656
|
-
function stopCleanupTimer() {
|
|
657
|
-
if (cleanupTimer2) {
|
|
658
|
-
clearInterval(cleanupTimer2);
|
|
659
|
-
cleanupTimer2 = null;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
function stopCleanupTimerIfIdle2() {
|
|
663
|
-
if (cancelableRequests.size === 0) stopCleanupTimer();
|
|
664
|
-
}
|
|
665
|
-
function isInWhitelist(url, whitelist) {
|
|
666
|
-
return whitelist.some((pattern) => pattern.test(url));
|
|
667
|
-
}
|
|
668
|
-
function onRequest3(config) {
|
|
669
|
-
const enhancedConfig = config;
|
|
670
|
-
const cancelConfig = normalizeConfig(
|
|
671
|
-
enhancedConfig.cancel,
|
|
672
|
-
DEFAULT_CANCEL_CONFIG
|
|
673
|
-
);
|
|
674
|
-
if (!cancelConfig.enabled) {
|
|
675
|
-
return config;
|
|
676
|
-
}
|
|
677
|
-
if (config.__fromCache) {
|
|
678
|
-
return config;
|
|
679
|
-
}
|
|
680
|
-
const url = config.url || "";
|
|
681
|
-
if (isInWhitelist(url, cancelConfig.whitelist)) {
|
|
682
|
-
return config;
|
|
683
|
-
}
|
|
684
|
-
const activeController = ensureSharedAbortController(enhancedConfig);
|
|
685
|
-
if (!activeController) return config;
|
|
686
|
-
const id = `request_${++requestId}`;
|
|
687
|
-
enhancedConfig.__cancelId = id;
|
|
688
|
-
cancelableRequests.set(id, activeController);
|
|
689
|
-
startCleanupTimer2();
|
|
690
|
-
return config;
|
|
691
|
-
}
|
|
692
|
-
function onResponse3(response) {
|
|
693
|
-
const config = response.config;
|
|
694
|
-
const cancelId = config.__cancelId;
|
|
695
|
-
if (cancelId) {
|
|
696
|
-
cancelableRequests.delete(cancelId);
|
|
697
|
-
stopCleanupTimerIfIdle2();
|
|
698
|
-
}
|
|
699
|
-
return response;
|
|
700
|
-
}
|
|
701
|
-
function onResponseError3(error) {
|
|
702
|
-
const config = error.config;
|
|
703
|
-
const cancelId = config?.__cancelId;
|
|
704
|
-
if (cancelId) {
|
|
705
|
-
cancelableRequests.delete(cancelId);
|
|
706
|
-
stopCleanupTimerIfIdle2();
|
|
707
|
-
}
|
|
708
|
-
return Promise.reject(error);
|
|
709
|
-
}
|
|
710
|
-
function setupCancelPlugin(instance) {
|
|
711
|
-
instance.interceptors.request.use(onRequest3);
|
|
712
|
-
instance.interceptors.response.use(onResponse3, onResponseError3);
|
|
713
|
-
}
|
|
714
|
-
function cancelAllRequests() {
|
|
715
|
-
cancelableRequests.forEach((controller) => {
|
|
716
|
-
try {
|
|
717
|
-
controller.abort();
|
|
718
|
-
} catch (error) {
|
|
719
|
-
console.warn("Error aborting request:", error);
|
|
720
|
-
}
|
|
721
|
-
});
|
|
722
|
-
cancelableRequests.clear();
|
|
723
|
-
stopCleanupTimer();
|
|
724
|
-
}
|
|
725
|
-
function getCancelableRequestCount() {
|
|
726
|
-
return cancelableRequests.size;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// src/axios/plugins/index.ts
|
|
730
|
-
function setupPlugins(instance) {
|
|
731
|
-
setupCachePlugin(instance);
|
|
732
|
-
setupCancelPlugin(instance);
|
|
733
|
-
setupDedupePlugin(instance);
|
|
734
|
-
setupRetryPlugin(instance);
|
|
735
|
-
setupResponsePlugin(instance);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// src/axios/service.ts
|
|
739
|
-
var globalService = null;
|
|
740
|
-
function setGlobalAxiosInstance(instance) {
|
|
741
|
-
globalService = instance;
|
|
742
|
-
}
|
|
743
|
-
function getGlobalAxiosInstance() {
|
|
744
|
-
if (!globalService) {
|
|
745
|
-
throw new Error(
|
|
746
|
-
"Axios instance not initialized. Please call createRequestCore() or setGlobalAxiosInstance() first."
|
|
747
|
-
);
|
|
748
|
-
}
|
|
749
|
-
return globalService;
|
|
750
|
-
}
|
|
751
|
-
new Proxy({}, {
|
|
752
|
-
get(_target, prop) {
|
|
753
|
-
return getGlobalAxiosInstance()[prop];
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
async function getData(url, config) {
|
|
757
|
-
const response = await getGlobalAxiosInstance().get(url, config);
|
|
758
|
-
return response.data;
|
|
759
|
-
}
|
|
760
|
-
async function postData(url, data, config) {
|
|
761
|
-
const response = await getGlobalAxiosInstance().post(url, data, config);
|
|
762
|
-
return response.data;
|
|
763
|
-
}
|
|
764
|
-
async function putData(url, data, config) {
|
|
765
|
-
const response = await getGlobalAxiosInstance().put(url, data, config);
|
|
766
|
-
return response.data;
|
|
767
|
-
}
|
|
768
|
-
async function deleteData(url, config) {
|
|
769
|
-
const response = await getGlobalAxiosInstance().delete(url, config);
|
|
770
|
-
return response.data;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// src/axios/request.ts
|
|
774
|
-
function createAxiosInstance(config = {}) {
|
|
775
|
-
const instance = axios.create({
|
|
776
|
-
timeout: 5e3,
|
|
777
|
-
headers: {
|
|
778
|
-
"Content-Type": "application/json"
|
|
779
|
-
},
|
|
780
|
-
...config
|
|
781
|
-
});
|
|
782
|
-
setupPlugins(instance);
|
|
783
|
-
return instance;
|
|
784
|
-
}
|
|
785
|
-
var onReLoginSuccess = () => {
|
|
786
|
-
resolveReLogin();
|
|
787
|
-
};
|
|
788
|
-
var onReLoginCancel = () => {
|
|
789
|
-
rejectReLogin(new Error("\u91CD\u65B0\u767B\u5F55\u5DF2\u53D6\u6D88"));
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
// src/core.ts
|
|
793
|
-
var globalConfig = {
|
|
794
|
-
successCodes: [200, 0, "200", "0"],
|
|
795
|
-
fieldAliases: {
|
|
796
|
-
data: ["data", "list", "items", "records"],
|
|
797
|
-
list: ["list", "items", "records", "rows", "data"],
|
|
798
|
-
total: ["total", "totalCount", "count", "totalElements"]
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
function getGlobalConfig() {
|
|
802
|
-
return globalConfig;
|
|
803
|
-
}
|
|
804
|
-
function createRequestCore(config = {}) {
|
|
805
|
-
const {
|
|
806
|
-
request = {},
|
|
807
|
-
interceptors = {},
|
|
808
|
-
successCodes,
|
|
809
|
-
fieldAliases
|
|
810
|
-
} = config;
|
|
811
|
-
if (successCodes) {
|
|
812
|
-
globalConfig.successCodes = successCodes;
|
|
813
|
-
}
|
|
814
|
-
if (fieldAliases) {
|
|
815
|
-
globalConfig.fieldAliases = {
|
|
816
|
-
data: fieldAliases.data || globalConfig.fieldAliases.data,
|
|
817
|
-
list: fieldAliases.list || globalConfig.fieldAliases.list,
|
|
818
|
-
total: fieldAliases.total || globalConfig.fieldAliases.total
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
const axiosInstance = createAxiosInstance(request);
|
|
822
|
-
setGlobalAxiosInstance(axiosInstance);
|
|
823
|
-
if (interceptors.request) {
|
|
824
|
-
axiosInstance.interceptors.request.use(
|
|
825
|
-
interceptors.request,
|
|
826
|
-
interceptors.requestError
|
|
827
|
-
);
|
|
828
|
-
}
|
|
829
|
-
if (interceptors.response) {
|
|
830
|
-
axiosInstance.interceptors.response.use(
|
|
831
|
-
interceptors.response,
|
|
832
|
-
interceptors.responseError
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
return {
|
|
836
|
-
install(app) {
|
|
837
|
-
app.config.globalProperties.$axios = axiosInstance;
|
|
838
|
-
},
|
|
839
|
-
axiosInstance
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// src/composables/useTableCrud/constants.ts
|
|
844
|
-
var DEFAULT_CONFIG = {
|
|
845
|
-
/** 默认 ID 字段名 */
|
|
846
|
-
idKey: "id",
|
|
847
|
-
/** 默认分页大小 */
|
|
848
|
-
pageSize: 10,
|
|
849
|
-
/** 默认启用分页 */
|
|
850
|
-
paginationEnabled: true,
|
|
851
|
-
/** 默认当前页 */
|
|
852
|
-
currentPage: 1
|
|
853
|
-
};
|
|
854
|
-
var DATA_FIELD_ALIASES = ["data", "list", "items", "records"];
|
|
855
|
-
var LIST_FIELD_ALIASES = [
|
|
856
|
-
"list",
|
|
857
|
-
"items",
|
|
858
|
-
"records",
|
|
859
|
-
"rows",
|
|
860
|
-
"data"
|
|
861
|
-
];
|
|
862
|
-
var TOTAL_FIELD_ALIASES = [
|
|
863
|
-
"total",
|
|
864
|
-
"totalCount",
|
|
865
|
-
"count",
|
|
866
|
-
"totalElements"
|
|
867
|
-
];
|
|
868
|
-
var SUCCESS_CODES = [200, 0, "200", "0"];
|
|
869
|
-
var DEFAULT_MESSAGES = {
|
|
870
|
-
createSuccess: "\u65B0\u589E\u6210\u529F",
|
|
871
|
-
updateSuccess: "\u66F4\u65B0\u6210\u529F",
|
|
872
|
-
deleteSuccess: "\u5220\u9664\u6210\u529F",
|
|
873
|
-
saveError: "\u4FDD\u5B58\u5931\u8D25",
|
|
874
|
-
deleteError: "\u5220\u9664\u5931\u8D25",
|
|
875
|
-
loadError: "\u6570\u636E\u52A0\u8F7D\u5931\u8D25",
|
|
876
|
-
detailError: "\u8BE6\u60C5\u83B7\u53D6\u5931\u8D25",
|
|
877
|
-
noDeleteApi: "\u672A\u914D\u7F6E\u5220\u9664\u63A5\u53E3"
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
// src/composables/useTableCrud/utils.ts
|
|
881
|
-
function getRuntimeFieldAliases() {
|
|
882
|
-
const config = getGlobalConfig();
|
|
883
|
-
return {
|
|
884
|
-
data: config.fieldAliases.data || DATA_FIELD_ALIASES,
|
|
885
|
-
list: config.fieldAliases.list || LIST_FIELD_ALIASES,
|
|
886
|
-
total: config.fieldAliases.total || TOTAL_FIELD_ALIASES
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
function getRuntimeSuccessCodes() {
|
|
890
|
-
const config = getGlobalConfig();
|
|
891
|
-
return config.successCodes || SUCCESS_CODES;
|
|
892
|
-
}
|
|
893
|
-
var FieldFinder = {
|
|
894
|
-
/**
|
|
895
|
-
* 查找第一个存在的字段值
|
|
896
|
-
*/
|
|
897
|
-
findFirst(obj, aliases, defaultValue) {
|
|
898
|
-
if (!obj || typeof obj !== "object") return defaultValue;
|
|
899
|
-
for (const key of aliases) {
|
|
900
|
-
if (key in obj && obj[key] !== void 0) {
|
|
901
|
-
return obj[key];
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
return defaultValue;
|
|
905
|
-
},
|
|
906
|
-
/**
|
|
907
|
-
* 查找第一个存在的数字字段
|
|
908
|
-
*/
|
|
909
|
-
findNumber(obj, aliases, defaultValue = 0) {
|
|
910
|
-
const value = this.findFirst(obj, aliases, defaultValue);
|
|
911
|
-
return Number(value) || defaultValue;
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
var ResponseNormalizer = {
|
|
915
|
-
/**
|
|
916
|
-
* 判断响应是否成功
|
|
917
|
-
*/
|
|
918
|
-
isSuccess(res) {
|
|
919
|
-
if (typeof res.success === "boolean") return res.success;
|
|
920
|
-
const successCodes = getRuntimeSuccessCodes();
|
|
921
|
-
return successCodes.includes(res.code) || successCodes.includes(String(res.code));
|
|
922
|
-
},
|
|
923
|
-
/**
|
|
924
|
-
* 标准化响应数据(提取 data 层)
|
|
925
|
-
*/
|
|
926
|
-
normalize(res) {
|
|
927
|
-
if (!res || typeof res !== "object" || !("data" in res)) {
|
|
928
|
-
return { data: res, success: true, raw: res };
|
|
929
|
-
}
|
|
930
|
-
const aliases = getRuntimeFieldAliases();
|
|
931
|
-
return {
|
|
932
|
-
data: FieldFinder.findFirst(res, aliases.data, res),
|
|
933
|
-
success: ResponseNormalizer.isSuccess(res),
|
|
934
|
-
raw: res
|
|
935
|
-
};
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
var UrlUtils = {
|
|
939
|
-
/**
|
|
940
|
-
* 构建 URL(处理路径参数)
|
|
941
|
-
*/
|
|
942
|
-
buildUrl(endpoint, id) {
|
|
943
|
-
if (id !== void 0 && endpoint.includes(":id")) {
|
|
944
|
-
return endpoint.replace(":id", String(id));
|
|
945
|
-
}
|
|
946
|
-
return endpoint;
|
|
947
|
-
}
|
|
948
|
-
};
|
|
949
|
-
var DataExtractor = {
|
|
950
|
-
/**
|
|
951
|
-
* 从响应中提取列表数据(支持多种格式)
|
|
952
|
-
*
|
|
953
|
-
* 支持的响应结构:
|
|
954
|
-
* 1. { code: 0, data: { list: [...], total: 10 } } // 嵌套结构(最常见)
|
|
955
|
-
* 2. { data: { items: [...], total: 10 } } // 嵌套结构
|
|
956
|
-
* 3. { list: [...], total: 10 } // 扁平结构
|
|
957
|
-
* 4. { items: [...], totalCount: 10 } // 不同字段名
|
|
958
|
-
* 5. { data: [...] } // 直接数组
|
|
959
|
-
* 6. [...] // 纯数组
|
|
960
|
-
*/
|
|
961
|
-
extractList(response) {
|
|
962
|
-
const normalized = ResponseNormalizer.normalize(response);
|
|
963
|
-
const dataLayer = normalized.data ?? response;
|
|
964
|
-
const aliases = getRuntimeFieldAliases();
|
|
965
|
-
const list = FieldFinder.findFirst(dataLayer, aliases.list, []);
|
|
966
|
-
const total = FieldFinder.findNumber(dataLayer, aliases.total, 0);
|
|
967
|
-
return {
|
|
968
|
-
items: Array.isArray(list) ? list : [],
|
|
969
|
-
total
|
|
970
|
-
};
|
|
971
|
-
},
|
|
972
|
-
/**
|
|
973
|
-
* 从响应中提取详情数据
|
|
974
|
-
*/
|
|
975
|
-
extractDetail(response) {
|
|
976
|
-
const normalized = ResponseNormalizer.normalize(response);
|
|
977
|
-
return normalized.data;
|
|
978
|
-
}
|
|
979
|
-
};
|
|
980
|
-
var RowUtils = {
|
|
981
|
-
/**
|
|
982
|
-
* 从数组中查找行索引
|
|
983
|
-
*/
|
|
984
|
-
findIndex(items, idKey, id) {
|
|
985
|
-
return items.findIndex((item) => item[idKey] === id);
|
|
986
|
-
},
|
|
987
|
-
/**
|
|
988
|
-
* 从数组中移除行
|
|
989
|
-
*/
|
|
990
|
-
remove(items, idKey, id) {
|
|
991
|
-
const index = this.findIndex(items, idKey, id);
|
|
992
|
-
if (index !== -1) {
|
|
993
|
-
items.splice(index, 1);
|
|
994
|
-
return true;
|
|
995
|
-
}
|
|
996
|
-
return false;
|
|
997
|
-
},
|
|
998
|
-
/**
|
|
999
|
-
* 生成默认 ID
|
|
1000
|
-
*/
|
|
1001
|
-
generateId() {
|
|
1002
|
-
return Date.now() + Math.floor(Math.random() * 1e3);
|
|
1003
|
-
}
|
|
1004
|
-
};
|
|
1005
|
-
|
|
1006
|
-
// src/composables/useTableCrud/useTableCrud.ts
|
|
1007
|
-
function useTableCrud(config) {
|
|
1008
|
-
const {
|
|
1009
|
-
api,
|
|
1010
|
-
columns,
|
|
1011
|
-
customActions = [],
|
|
1012
|
-
detail: detailConfig,
|
|
1013
|
-
idKey = DEFAULT_CONFIG.idKey,
|
|
1014
|
-
defaultPageSize = DEFAULT_CONFIG.pageSize,
|
|
1015
|
-
defaultPaginationEnabled = DEFAULT_CONFIG.paginationEnabled,
|
|
1016
|
-
autoLoad = true,
|
|
1017
|
-
extractListData
|
|
1018
|
-
} = config;
|
|
1019
|
-
const message = useMessage();
|
|
1020
|
-
const dialog = useDialog();
|
|
1021
|
-
const data = shallowRef([]);
|
|
1022
|
-
const total = ref(0);
|
|
1023
|
-
const loading = ref(false);
|
|
1024
|
-
const tableRef = ref();
|
|
1025
|
-
const paginationEnabled = ref(defaultPaginationEnabled);
|
|
1026
|
-
const page = reactive({
|
|
1027
|
-
current: DEFAULT_CONFIG.currentPage,
|
|
1028
|
-
size: defaultPageSize
|
|
1029
|
-
});
|
|
1030
|
-
const detailVisible = ref(false);
|
|
1031
|
-
const detailData = ref(null);
|
|
1032
|
-
const detailTitle = ref("");
|
|
1033
|
-
const detail = {
|
|
1034
|
-
visible: detailVisible,
|
|
1035
|
-
data: detailData,
|
|
1036
|
-
title: detailTitle,
|
|
1037
|
-
show: (row) => {
|
|
1038
|
-
detailData.value = row;
|
|
1039
|
-
detailTitle.value = `\u8BE6\u60C5 - ${row.name || row[idKey]}`;
|
|
1040
|
-
detailVisible.value = true;
|
|
1041
|
-
},
|
|
1042
|
-
close: () => {
|
|
1043
|
-
detailVisible.value = false;
|
|
1044
|
-
detailData.value = null;
|
|
1045
|
-
detailTitle.value = "";
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
const refresh = async () => {
|
|
1049
|
-
if (!api.list) return;
|
|
1050
|
-
loading.value = true;
|
|
1051
|
-
try {
|
|
1052
|
-
const queryParams = paginationEnabled.value ? { page: page.current, pageSize: page.size } : {};
|
|
1053
|
-
const response = await getData(api.list, { params: queryParams });
|
|
1054
|
-
const extracted = extractListData ? extractListData(response) : DataExtractor.extractList(response);
|
|
1055
|
-
data.value = extracted.items;
|
|
1056
|
-
total.value = extracted.total;
|
|
1057
|
-
} catch (error) {
|
|
1058
|
-
console.error("[useTableCrud] \u6570\u636E\u52A0\u8F7D\u5931\u8D25:", error);
|
|
1059
|
-
message.error(DEFAULT_MESSAGES.loadError);
|
|
1060
|
-
} finally {
|
|
1061
|
-
loading.value = false;
|
|
1062
|
-
}
|
|
1063
|
-
};
|
|
1064
|
-
const getDetail = async (row) => {
|
|
1065
|
-
if (!api.get) {
|
|
1066
|
-
detail.show(row);
|
|
1067
|
-
return row;
|
|
1068
|
-
}
|
|
1069
|
-
loading.value = true;
|
|
1070
|
-
try {
|
|
1071
|
-
const url = UrlUtils.buildUrl(api.get, row[idKey]);
|
|
1072
|
-
const response = await getData(url, {});
|
|
1073
|
-
const detailData2 = DataExtractor.extractDetail(response);
|
|
1074
|
-
if (detailData2) {
|
|
1075
|
-
detail.show(detailData2);
|
|
1076
|
-
return detailData2;
|
|
1077
|
-
}
|
|
1078
|
-
return null;
|
|
1079
|
-
} catch (error) {
|
|
1080
|
-
console.error("[useTableCrud] \u8BE6\u60C5\u83B7\u53D6\u5931\u8D25:", error);
|
|
1081
|
-
message.error(DEFAULT_MESSAGES.detailError);
|
|
1082
|
-
return null;
|
|
1083
|
-
} finally {
|
|
1084
|
-
loading.value = false;
|
|
1085
|
-
}
|
|
1086
|
-
};
|
|
1087
|
-
const create = async (row) => {
|
|
1088
|
-
if (!api.create) {
|
|
1089
|
-
message.warning("\u672A\u914D\u7F6E\u65B0\u589E\u63A5\u53E3");
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
loading.value = true;
|
|
1093
|
-
try {
|
|
1094
|
-
await postData(api.create, row);
|
|
1095
|
-
message.success(DEFAULT_MESSAGES.createSuccess);
|
|
1096
|
-
await refresh();
|
|
1097
|
-
} catch (error) {
|
|
1098
|
-
console.error("[useTableCrud] \u65B0\u589E\u5931\u8D25:", error);
|
|
1099
|
-
message.error("\u65B0\u589E\u5931\u8D25");
|
|
1100
|
-
throw error;
|
|
1101
|
-
} finally {
|
|
1102
|
-
loading.value = false;
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
1105
|
-
const save = async (row) => {
|
|
1106
|
-
if (!api.update) {
|
|
1107
|
-
message.warning("\u672A\u914D\u7F6E\u66F4\u65B0\u63A5\u53E3");
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
loading.value = true;
|
|
1111
|
-
try {
|
|
1112
|
-
const url = UrlUtils.buildUrl(api.update, row[idKey]);
|
|
1113
|
-
await putData(url, row);
|
|
1114
|
-
message.success(DEFAULT_MESSAGES.updateSuccess);
|
|
1115
|
-
await refresh();
|
|
1116
|
-
} catch (error) {
|
|
1117
|
-
console.error("[useTableCrud] \u66F4\u65B0\u5931\u8D25:", error);
|
|
1118
|
-
message.error(DEFAULT_MESSAGES.saveError);
|
|
1119
|
-
throw error;
|
|
1120
|
-
} finally {
|
|
1121
|
-
loading.value = false;
|
|
1122
|
-
}
|
|
1123
|
-
};
|
|
1124
|
-
const remove = async (row) => {
|
|
1125
|
-
if (!api.remove) {
|
|
1126
|
-
message.warning(DEFAULT_MESSAGES.noDeleteApi);
|
|
1127
|
-
return;
|
|
1128
|
-
}
|
|
1129
|
-
loading.value = true;
|
|
1130
|
-
try {
|
|
1131
|
-
const url = UrlUtils.buildUrl(api.remove, row[idKey]);
|
|
1132
|
-
await deleteData(url);
|
|
1133
|
-
message.success(DEFAULT_MESSAGES.deleteSuccess);
|
|
1134
|
-
RowUtils.remove(data.value, idKey, row[idKey]);
|
|
1135
|
-
await refresh();
|
|
1136
|
-
} catch (error) {
|
|
1137
|
-
console.error("[useTableCrud] \u5220\u9664\u5931\u8D25:", error);
|
|
1138
|
-
message.error(DEFAULT_MESSAGES.deleteError);
|
|
1139
|
-
throw error;
|
|
1140
|
-
} finally {
|
|
1141
|
-
loading.value = false;
|
|
1142
|
-
}
|
|
1143
|
-
};
|
|
1144
|
-
const batchRemove = async (rows) => {
|
|
1145
|
-
if (!rows || rows.length === 0) {
|
|
1146
|
-
message.warning("\u8BF7\u9009\u62E9\u8981\u5220\u9664\u7684\u6570\u636E");
|
|
1147
|
-
return;
|
|
1148
|
-
}
|
|
1149
|
-
if (!api.remove && !api.batchRemove) {
|
|
1150
|
-
message.warning(DEFAULT_MESSAGES.noDeleteApi);
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
|
-
loading.value = true;
|
|
1154
|
-
try {
|
|
1155
|
-
if (api.batchRemove) {
|
|
1156
|
-
const ids = rows.map((row) => row[idKey]);
|
|
1157
|
-
await postData(api.batchRemove, { ids });
|
|
1158
|
-
} else {
|
|
1159
|
-
await Promise.all(
|
|
1160
|
-
rows.map((row) => {
|
|
1161
|
-
const url = UrlUtils.buildUrl(api.remove, row[idKey]);
|
|
1162
|
-
return deleteData(url);
|
|
1163
|
-
})
|
|
1164
|
-
);
|
|
1165
|
-
}
|
|
1166
|
-
message.success(`\u6210\u529F\u5220\u9664 ${rows.length} \u6761\u6570\u636E`);
|
|
1167
|
-
await refresh();
|
|
1168
|
-
} catch (error) {
|
|
1169
|
-
console.error("[useTableCrud] \u6279\u91CF\u5220\u9664\u5931\u8D25:", error);
|
|
1170
|
-
message.error("\u6279\u91CF\u5220\u9664\u5931\u8D25");
|
|
1171
|
-
throw error;
|
|
1172
|
-
} finally {
|
|
1173
|
-
loading.value = false;
|
|
1174
|
-
}
|
|
1175
|
-
};
|
|
1176
|
-
const handleCancel = async () => {
|
|
1177
|
-
await refresh();
|
|
1178
|
-
};
|
|
1179
|
-
const handlePaginationChange = (pageNum, pageSize) => {
|
|
1180
|
-
page.current = pageNum;
|
|
1181
|
-
page.size = pageSize;
|
|
1182
|
-
refresh();
|
|
1183
|
-
};
|
|
1184
|
-
const handleRowDelete = (deletedRow) => {
|
|
1185
|
-
RowUtils.remove(data.value, idKey, deletedRow[idKey]);
|
|
1186
|
-
};
|
|
1187
|
-
const pagination = computed(() => {
|
|
1188
|
-
if (!paginationEnabled.value) return false;
|
|
1189
|
-
return {
|
|
1190
|
-
enabled: true,
|
|
1191
|
-
page: page.current,
|
|
1192
|
-
pageSize: page.size
|
|
1193
|
-
};
|
|
1194
|
-
});
|
|
1195
|
-
const createActionContext = (index) => ({
|
|
1196
|
-
data: data.value,
|
|
1197
|
-
index,
|
|
1198
|
-
page,
|
|
1199
|
-
paginationEnabled: paginationEnabled.value,
|
|
1200
|
-
message,
|
|
1201
|
-
dialog,
|
|
1202
|
-
refresh
|
|
1203
|
-
});
|
|
1204
|
-
const actions = computed(() => {
|
|
1205
|
-
const result = {};
|
|
1206
|
-
if (api.update) {
|
|
1207
|
-
result.edit = async (row) => {
|
|
1208
|
-
try {
|
|
1209
|
-
await save(row);
|
|
1210
|
-
return { data: row, error: null };
|
|
1211
|
-
} catch (error) {
|
|
1212
|
-
return { data: null, error };
|
|
1213
|
-
}
|
|
1214
|
-
};
|
|
1215
|
-
}
|
|
1216
|
-
if (api.remove) {
|
|
1217
|
-
result.delete = async (row) => {
|
|
1218
|
-
try {
|
|
1219
|
-
await remove(row);
|
|
1220
|
-
return { data: { success: true }, error: null };
|
|
1221
|
-
} catch (error) {
|
|
1222
|
-
return { data: null, error };
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
|
-
}
|
|
1226
|
-
if (api.get) {
|
|
1227
|
-
result.detail = async (row) => {
|
|
1228
|
-
try {
|
|
1229
|
-
const detailData2 = await getDetail(row);
|
|
1230
|
-
return { data: detailData2, error: null };
|
|
1231
|
-
} catch (error) {
|
|
1232
|
-
return { data: null, error };
|
|
1233
|
-
}
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
if (customActions.length > 0) {
|
|
1237
|
-
result.custom = customActions.map((action) => ({
|
|
1238
|
-
key: action.key,
|
|
1239
|
-
label: action.label,
|
|
1240
|
-
icon: action.icon,
|
|
1241
|
-
type: action.type || "default",
|
|
1242
|
-
onClick: (row, index) => {
|
|
1243
|
-
const context = createActionContext(index);
|
|
1244
|
-
return action.handler(row, context);
|
|
1245
|
-
}
|
|
1246
|
-
}));
|
|
1247
|
-
}
|
|
1248
|
-
return result;
|
|
1249
|
-
});
|
|
1250
|
-
if (autoLoad) {
|
|
1251
|
-
refresh();
|
|
1252
|
-
}
|
|
1253
|
-
return {
|
|
1254
|
-
// 数据状态
|
|
1255
|
-
data,
|
|
1256
|
-
loading,
|
|
1257
|
-
total,
|
|
1258
|
-
// 表格配置
|
|
1259
|
-
columns: computed(() => columns),
|
|
1260
|
-
actions,
|
|
1261
|
-
tableRef,
|
|
1262
|
-
// 分页
|
|
1263
|
-
page,
|
|
1264
|
-
paginationEnabled,
|
|
1265
|
-
pagination,
|
|
1266
|
-
// 核心方法
|
|
1267
|
-
refresh,
|
|
1268
|
-
create,
|
|
1269
|
-
save,
|
|
1270
|
-
remove,
|
|
1271
|
-
batchRemove,
|
|
1272
|
-
getDetail,
|
|
1273
|
-
// 事件处理
|
|
1274
|
-
handleCancel,
|
|
1275
|
-
handlePaginationChange,
|
|
1276
|
-
handleRowDelete,
|
|
1277
|
-
// 详情弹窗
|
|
1278
|
-
detail,
|
|
1279
|
-
detailConfig
|
|
1280
|
-
};
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
export { cancelAllPendingRequests, cancelAllRequests, cleanupExpiredCache, clearAllCache, clearCache, createAxiosInstance, createRequestCore, deleteData, getCacheSize, getCancelableRequestCount, getData, getGlobalConfig, getPendingRequestCount, getReLoginPromise, onReLoginCancel, onReLoginSuccess, postData, putData, useTableCrud, waitForReLogin };
|
|
1
|
+
export { createRequestClient, setDefaultRequestClient } from './chunk-DUP3Y4DN.js';
|
|
2
|
+
export { useTableCrud } from './chunk-56QOEWUS.js';
|
|
3
|
+
export { useNaiveTableCrud } from './chunk-QSDNDTOZ.js';
|
|
4
|
+
import './chunk-2JXH7SIL.js';
|
|
5
|
+
export { MemoryCache, RequestError, cancelAllPendingRequests, cancelAllRequests, cancelRequestScope, cleanupExpiredCache, clearAllCache, clearCache, clearCacheByPrefix, clearCacheByTag, createAxiosInstance, createRequestCore, deleteData, generateRequestKey, getCacheSize, getCancelableRequestCount, getData, getGlobalConfig, getPendingRequestCount, getReLoginPromise, isCanceledError, isRequestError, normalizeRequestError, onReLoginCancel, onReLoginSuccess, patchData, postData, putData, waitForReLogin } from './chunk-OAZ5BUBU.js';
|
|
1284
6
|
//# sourceMappingURL=index.js.map
|
|
1285
7
|
//# sourceMappingURL=index.js.map
|