✨ 评分减分累计与最高扣分、用户部门标签联动树,并修复对账导入与结算调整等

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-23 04:28:22 +08:00
parent 8d9fe998c0
commit 2a5eca8393
17 changed files with 691 additions and 307 deletions
+31 -10
View File
@@ -105,12 +105,27 @@ const isJsonContentType = res => {
return contentType.includes('application/json') || contentType.includes('text/json');
};
/**
* 是否为可按文本读取的 Blob / Blob-like(含跨 realm)。
* 禁止对普通业务 JSON 对象调用 .text()。
*/
const isBlobLikeData = value =>
value != null &&
typeof value === 'object' &&
typeof value.size === 'number' &&
typeof value.type === 'string' &&
typeof value.text === 'function';
/**
* 判断响应体是否已是解析好的对象(无需再解析)。
* 注意 Blob 也是 object,必须排除,否则会把待解析的文件流误判为已完成。
*/
const isPlainObject = value =>
value !== null && typeof value === 'object' && !(value instanceof Blob);
value !== null &&
typeof value === 'object' &&
!(value instanceof Blob) &&
!isBlobLikeData(value) &&
!(value instanceof ArrayBuffer);
//跨域请求,允许保存cookie
axios.defaults.withCredentials = true;
// NProgress Configuration
@@ -190,15 +205,20 @@ axios.interceptors.response.use(
// 用户就会以为系统崩了——而后端其实返回了明确的业务提示(如「未读取到数据行…」)。
// 这里按 Content-Type 判断:JSON 才解析回对象;真·文件流(Excel 等)保持原样不动。
// 兼容 Blob(浏览器 responseType='blob')与 string(非浏览器环境)两种形态。
// 仅对真正的 Blob/Blob-like 调 .text(),避免业务 JSON 已解析后出现
// 「e.data.text is not a function」。
if (isJsonContentType(res) && !isPlainObject(res.data)) {
try {
let text = '';
if (typeof res.data?.text === 'function') {
text = await res.data.text();
} else if (typeof res.data === 'string') {
text = res.data;
} else if (typeof res.data?.arrayBuffer === 'function') {
text = new TextDecoder().decode(await res.data.arrayBuffer());
const raw = res.data;
if (isBlobLikeData(raw) || (typeof Blob !== 'undefined' && raw instanceof Blob)) {
text = await raw.text();
} else if (typeof raw === 'string') {
text = raw;
} else if (raw && typeof raw.arrayBuffer === 'function') {
text = new TextDecoder().decode(await raw.arrayBuffer());
} else if (raw instanceof ArrayBuffer) {
text = new TextDecoder().decode(raw);
}
const parsed = typeof text === 'string' && text ? JSON.parse(text) : null;
if (parsed && typeof parsed === 'object') {
@@ -208,10 +228,11 @@ axios.interceptors.response.use(
// 声明是 JSON 却解析失败:保持原样,交给下游按文件处理
}
}
//获取状态信息
const status = res.data.error_code || res.data.code || res.status;
// 获取状态信息:文件流没有 code/msg,必须退回 HTTP status,禁止读 Blob 上的幽灵字段
const payload = isPlainObject(res.data) ? res.data : {};
const status = Number(payload.error_code || payload.code || res.status);
const statusWhiteList = website.statusWhiteList || [];
const message = res.data.msg || res.data.error_description || '系统错误';
const message = payload.msg || payload.error_description || '系统错误';
//如果在白名单里则自行catch逻辑处理
if (statusWhiteList.includes(status)) return Promise.reject(res);