@yy-common/shared 1.0.0-beta.6
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/.versionrc +23 -0
- package/CHANGELOG.md +42 -0
- package/api/dict.js +60 -0
- package/api/index.js +1 -0
- package/config/config.js +65 -0
- package/config/index.js +1 -0
- package/directive/directives.js +9 -0
- package/directive/index.js +26 -0
- package/directive/module/draggable.js +44 -0
- package/directive/module/permission.js +15 -0
- package/index.js +4 -0
- package/package.json +26 -0
- package/router/basic-routes.js +28 -0
- package/router/generator-routers.js +260 -0
- package/router/guard.js +283 -0
- package/router/index.js +9 -0
- package/utils/column-setting.js +72 -0
- package/utils/com.js +8 -0
- package/utils/dict-cache.js +11 -0
- package/utils/dynamicSetting.js +45 -0
- package/utils/enum.js +137 -0
- package/utils/errorLog.js +39 -0
- package/utils/excel.js +789 -0
- package/utils/index.js +26 -0
- package/utils/is-type.js +164 -0
- package/utils/item.js +14 -0
- package/utils/metric.js +135 -0
- package/utils/number.js +12 -0
- package/utils/request/axiosN.js +142 -0
- package/utils/request/content-type.js +19 -0
- package/utils/request/index.js +2 -0
- package/utils/request/interceptors.js +156 -0
- package/utils/request/url-params.js +12 -0
- package/utils/router.js +27 -0
- package/utils/storage.js +51 -0
- package/utils/table.js +348 -0
- package/utils/token.js +51 -0
- package/utils/tree.js +39 -0
- package/utils/user.js +8 -0
- package/utils/wps.js +16 -0
package/utils/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from "./dict-cache";
|
|
2
|
+
export * from "./enum";
|
|
3
|
+
export * from "./excel";
|
|
4
|
+
export * from "./is-type";
|
|
5
|
+
export * from "./storage";
|
|
6
|
+
export * from "./request";
|
|
7
|
+
export * from "./wps";
|
|
8
|
+
export * from "./table";
|
|
9
|
+
export * from "./number";
|
|
10
|
+
export * from "./dynamicSetting";
|
|
11
|
+
|
|
12
|
+
// 山东中烟公司 卷烟 人员树
|
|
13
|
+
export * from "./com";
|
|
14
|
+
export * from "./item";
|
|
15
|
+
export * from "./user";
|
|
16
|
+
|
|
17
|
+
//山东中烟 待办路由跳转
|
|
18
|
+
export * from "./router";
|
|
19
|
+
|
|
20
|
+
// 指标仓库 查数方法
|
|
21
|
+
export * from "./metric";
|
|
22
|
+
|
|
23
|
+
// 列设置
|
|
24
|
+
export * from "./column-setting";
|
|
25
|
+
|
|
26
|
+
export * from "./tree";
|
package/utils/is-type.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
const toString = {}.toString
|
|
2
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty
|
|
3
|
+
const PRECISION = 0.00001 // numbers less than this is considered as 0
|
|
4
|
+
const objectProto = Object.prototype
|
|
5
|
+
|
|
6
|
+
export const isNull = (value) => value === null
|
|
7
|
+
export const isUndefined = (value) => value === undefined
|
|
8
|
+
export const isNil = (value) => isNull(value) || isUndefined(value)
|
|
9
|
+
|
|
10
|
+
export const getType = (value) =>
|
|
11
|
+
toString
|
|
12
|
+
.call(value)
|
|
13
|
+
.replace(/^\[object /, '')
|
|
14
|
+
.replace(/]$/, '')
|
|
15
|
+
|
|
16
|
+
export const isType = (value, type) =>
|
|
17
|
+
toString.call(value) === `[object ${type}]`
|
|
18
|
+
|
|
19
|
+
export const isPrototype = (value) => {
|
|
20
|
+
const Ctor = value && value.constructor
|
|
21
|
+
const proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto
|
|
22
|
+
return value === proto
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const isBoolean = (value) => isType(value, 'Boolean')
|
|
26
|
+
|
|
27
|
+
export const isNumber = (value) => isType(value, 'Number')
|
|
28
|
+
|
|
29
|
+
export const isString = (str) => isType(str, 'String')
|
|
30
|
+
|
|
31
|
+
export const isArray = (value) =>
|
|
32
|
+
Array.isArray ? Array.isArray(value) : isType(value, 'Array')
|
|
33
|
+
|
|
34
|
+
export const isArrayLike = (value) => {
|
|
35
|
+
/**
|
|
36
|
+
* isArrayLike([1, 2, 3]) => true
|
|
37
|
+
* isArrayLike(document.body.children) => true
|
|
38
|
+
* isArrayLike('abc') => true
|
|
39
|
+
* isArrayLike(Function) => false
|
|
40
|
+
*/
|
|
41
|
+
return value !== null && typeof value !== 'function' && Number.isFinite(value.length)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const isObject = (value) => {
|
|
45
|
+
/**
|
|
46
|
+
* isObject({}) => true
|
|
47
|
+
* isObject([1, 2, 3]) => true
|
|
48
|
+
* isObject(Function) => true
|
|
49
|
+
* isObject(null) => false
|
|
50
|
+
*/
|
|
51
|
+
const type = typeof value
|
|
52
|
+
return (value !== null && type === 'object') || type === 'function'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const isObjectLike = (value) => {
|
|
56
|
+
/**
|
|
57
|
+
* isObjectLike({}) => true
|
|
58
|
+
* isObjectLike([1, 2, 3]) => true
|
|
59
|
+
* isObjectLike(Function) => false
|
|
60
|
+
* isObjectLike(null) => false
|
|
61
|
+
*/
|
|
62
|
+
return typeof value === 'object' && value !== null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const isPlainObject = (value) => {
|
|
66
|
+
/**
|
|
67
|
+
* isObjectLike(new Foo) => false
|
|
68
|
+
* isObjectLike([1, 2, 3]) => false
|
|
69
|
+
* isObjectLike({ x: 0, y: 0 }) => true
|
|
70
|
+
* isObjectLike(Object.create(null)) => true
|
|
71
|
+
*/
|
|
72
|
+
if (!isObjectLike(value) || !isType(value, 'Object')) return false
|
|
73
|
+
if (Object.getPrototypeOf(value) === null) return true
|
|
74
|
+
let proto = value
|
|
75
|
+
while (Object.getPrototypeOf(proto) !== null) {
|
|
76
|
+
proto = Object.getPrototypeOf(proto)
|
|
77
|
+
}
|
|
78
|
+
return Object.getPrototypeOf(value) === proto
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
82
|
+
export const isFunction = (value) => isType(value, 'Function')
|
|
83
|
+
|
|
84
|
+
export const isPromise = (value) => value && typeof value.then === 'function'
|
|
85
|
+
|
|
86
|
+
export const isDate = (value) => isType(value, 'Date')
|
|
87
|
+
|
|
88
|
+
export const isArguments = (value) => isType(value, 'Arguments')
|
|
89
|
+
|
|
90
|
+
export const isRegExp = (str) => isType(str, 'RegExp')
|
|
91
|
+
|
|
92
|
+
export const isError = (value) => isType(value, 'Error')
|
|
93
|
+
|
|
94
|
+
export const isElement = (o) => o instanceof Element || o instanceof HTMLDocument
|
|
95
|
+
|
|
96
|
+
export const isEmpty = (value) => {
|
|
97
|
+
/**
|
|
98
|
+
* isEmpty(null) => true
|
|
99
|
+
* isEmpty() => true
|
|
100
|
+
* isEmpty(true) => true
|
|
101
|
+
* isEmpty(1) => true
|
|
102
|
+
* isEmpty([1, 2, 3]) => false
|
|
103
|
+
* isEmpty('abc') => false
|
|
104
|
+
* isEmpty({ a: 1 }) => false
|
|
105
|
+
*/
|
|
106
|
+
if (isNil(value)) return true
|
|
107
|
+
if (isArrayLike(value)) return !value.length
|
|
108
|
+
const type = getType(value)
|
|
109
|
+
if (['Map', 'Set'].includes(type)) return !value.size
|
|
110
|
+
if (isPrototype(value)) return !Object.keys(value).length
|
|
111
|
+
for (const key in value) {
|
|
112
|
+
if (hasOwnProperty.call(value, key)) return false
|
|
113
|
+
}
|
|
114
|
+
return true
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const isEqual = (value, other) => {
|
|
118
|
+
if (value === other) return true
|
|
119
|
+
if (!value || !other) return false
|
|
120
|
+
if (isString(value) || isString(other)) return false
|
|
121
|
+
if (isArrayLike(value) || isArrayLike(other)) {
|
|
122
|
+
if (value.length !== other.length) return false
|
|
123
|
+
let rst = true
|
|
124
|
+
for (let i = 0; i < value.length; i++) {
|
|
125
|
+
rst = isEqual(value[i], other[i])
|
|
126
|
+
if (!rst) break
|
|
127
|
+
}
|
|
128
|
+
return rst
|
|
129
|
+
}
|
|
130
|
+
if (isObjectLike(value) || isObjectLike(other)) {
|
|
131
|
+
const valueKeys = Object.keys(value)
|
|
132
|
+
const otherKeys = Object.keys(other)
|
|
133
|
+
if (valueKeys.length !== otherKeys.length) return false
|
|
134
|
+
let rst = true
|
|
135
|
+
for (let i = 0; i < valueKeys.length; i++) {
|
|
136
|
+
rst = isEqual(value[valueKeys[i]], other[valueKeys[i]])
|
|
137
|
+
if (!rst) break
|
|
138
|
+
}
|
|
139
|
+
return rst
|
|
140
|
+
}
|
|
141
|
+
return false
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** number */
|
|
145
|
+
export const isEven = (num) => isNumber(num) && num % 2 === 0
|
|
146
|
+
export const isOdd = (num) => isNumber(num) && num % 2 !== 0
|
|
147
|
+
|
|
148
|
+
export const isFinite = (value) => isNumber(value) && Number.isFinite(value)
|
|
149
|
+
|
|
150
|
+
export const isInteger = Number.isInteger
|
|
151
|
+
? Number.isInteger
|
|
152
|
+
: (num) => isNumber(num) && num % 1 === 0
|
|
153
|
+
export const isDecimal = (num) => isNumber(num) && num % 1 !== 0
|
|
154
|
+
|
|
155
|
+
export const isNegative = (num) => isNumber(num) && num < 0
|
|
156
|
+
export const isPositive = (num) => isNumber(num) && num > 0
|
|
157
|
+
|
|
158
|
+
export const isNumberEqual = (a, b, precision = PRECISION) =>
|
|
159
|
+
Math.abs(a - b) < precision
|
|
160
|
+
|
|
161
|
+
export const isEqualWith = (value, other, fn) => {
|
|
162
|
+
if (!isFunction(fn)) return isEqual(value, other)
|
|
163
|
+
return !!fn(value, other)
|
|
164
|
+
}
|
package/utils/item.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { axios } from './request/index'
|
|
2
|
+
import config from '../config/config'
|
|
3
|
+
|
|
4
|
+
const CONTEXT = config.ismAmServerContext
|
|
5
|
+
|
|
6
|
+
export function listItemTreeApi(params) {
|
|
7
|
+
return axios.get(`${CONTEXT}/tree/item/listItemTree`, { params })
|
|
8
|
+
}
|
|
9
|
+
export function getPriceInfo() {
|
|
10
|
+
return axios.get(`${CONTEXT}/basic/getPriceInfo`, {})
|
|
11
|
+
}
|
|
12
|
+
export function getItem(params) {
|
|
13
|
+
return axios.get(`${CONTEXT}/basic/getItem`, { params })
|
|
14
|
+
}
|
package/utils/metric.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import dayjs from 'dayjs'
|
|
2
|
+
import {axios} from './request'
|
|
3
|
+
import pako from 'pako'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// 日期字段映射
|
|
7
|
+
const dateEnum = {
|
|
8
|
+
YEAR: 'biz_year',
|
|
9
|
+
HALF_YEAR: 'biz_year_half',
|
|
10
|
+
SEASON: 'biz_quarter',
|
|
11
|
+
MONTH: 'biz_month',
|
|
12
|
+
TENDYAS: 'biz_tendays',
|
|
13
|
+
WEEK: 'biz_week',
|
|
14
|
+
DAYS: 'biz_date',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 转换obj中的日期字段
|
|
18
|
+
/**
|
|
19
|
+
* 转换日期字段格式
|
|
20
|
+
* 将对象中的日期相关字段转换为指定格式的日期维度字段,并删除原始日期字段
|
|
21
|
+
* @param {Object} obj - 包含日期信息的对象,应包含dataPeriodType、beginDate、endDate字段
|
|
22
|
+
* @returns {void} 直接修改传入的对象,无返回值
|
|
23
|
+
*/
|
|
24
|
+
function transDateField(obj) {
|
|
25
|
+
if (obj.dataPeriodType) {
|
|
26
|
+
// 根据数据周期类型获取日期维度字段名,默认为'biz_date'
|
|
27
|
+
let dateDim = dateEnum[obj.dataPeriodType] || 'biz_date';
|
|
28
|
+
// 格式化开始日期和结束日期,并用逗号连接,赋值给对应的日期维度字段
|
|
29
|
+
obj[dateDim] = formatDate(obj.beginDate, dateDim) + ',' + formatDate(obj.endDate, dateDim)
|
|
30
|
+
// 移除dataPeriodType\beginDate\endDate
|
|
31
|
+
delete obj.dataPeriodType
|
|
32
|
+
delete obj.beginDate
|
|
33
|
+
delete obj.endDate
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 转换过滤器中的日期字段
|
|
40
|
+
* 该函数处理不同层级的数组结构,对其中的日期字段进行转换
|
|
41
|
+
* @param {Array|Object} filter - 过滤器对象或数组,可能包含嵌套数组结构
|
|
42
|
+
* @returns {void}
|
|
43
|
+
*/
|
|
44
|
+
function transFilterDateField(filter) {
|
|
45
|
+
// 如果filter是数组
|
|
46
|
+
if (Array.isArray(filter)) {
|
|
47
|
+
// 遍历数组
|
|
48
|
+
filter.forEach((item) => {
|
|
49
|
+
if (Array.isArray(item)) {
|
|
50
|
+
// 遍历数组
|
|
51
|
+
item.forEach((item2) => {
|
|
52
|
+
transDateField(item2)
|
|
53
|
+
})
|
|
54
|
+
} else {
|
|
55
|
+
transDateField(item)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
} else {
|
|
59
|
+
transDateField(filter)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 日期格式化
|
|
64
|
+
const formatEnum = {
|
|
65
|
+
biz_year: 'YYYY-MM',
|
|
66
|
+
biz_year_half: 'YYYY-MM',
|
|
67
|
+
biz_quarter: 'YYYY-MM',
|
|
68
|
+
biz_month: 'YYYY-MM',
|
|
69
|
+
biz_tendays: 'YYYY-MM-DD',
|
|
70
|
+
biz_week: 'YYYY-MM-DD',
|
|
71
|
+
biz_date: 'YYYY-MM-DD',
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 根据日期类型,对传入的日期进行格式化处理
|
|
76
|
+
* @param {*} date
|
|
77
|
+
* @param {*} dateType
|
|
78
|
+
*/
|
|
79
|
+
function formatDate(date, dateType) {
|
|
80
|
+
// 日期对象进行格式转换
|
|
81
|
+
if (date instanceof Date) {
|
|
82
|
+
return dayjs(date).format(formatEnum[dateType])?.replaceAll('-', '')
|
|
83
|
+
} else {
|
|
84
|
+
return date?.replaceAll('-', '')
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 数据查询api
|
|
90
|
+
*/
|
|
91
|
+
function doQuery(params) {
|
|
92
|
+
return axios.post('/ddd-sc-idata-server/sc/dc/q/indexservice/queryBizIndex/v1', params)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function decompress(compressedData) {
|
|
96
|
+
try {
|
|
97
|
+
const compressedBytes = atob(compressedData)
|
|
98
|
+
const charData = compressedBytes.split('').map((x) => x.charCodeAt(0))
|
|
99
|
+
const binData = new Uint8Array(charData)
|
|
100
|
+
const decompressed = pako.inflate(binData)
|
|
101
|
+
const strData = new TextDecoder('utf-8').decode(decompressed)
|
|
102
|
+
const originalData = JSON.parse(strData)
|
|
103
|
+
return originalData
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error('数据解压失败:', error)
|
|
106
|
+
return []
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 异步查询函数,用于根据传入参数构建查询配置并执行查询操作。
|
|
113
|
+
*
|
|
114
|
+
* @param {Object} options - 查询参数对象
|
|
115
|
+
* @param {Array} options.filter - 过滤条件数组
|
|
116
|
+
* @param {Array} options.dim - 维度信息数组
|
|
117
|
+
* @param {Array} options.biz_metric - 业务指标ID数组
|
|
118
|
+
* @param {Array} options.sum - 合计
|
|
119
|
+
* @returns {Promise<Array>} 查询结果数据数组,若查询失败则返回空数组
|
|
120
|
+
*/
|
|
121
|
+
export async function metricQuery(options) {
|
|
122
|
+
console.log('query options is', options)
|
|
123
|
+
let filter = options.filter
|
|
124
|
+
transFilterDateField(filter)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
// 调用查询接口
|
|
128
|
+
try {
|
|
129
|
+
let {data} = await doQuery(options)
|
|
130
|
+
return decompress(data)
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.log('doQuery e', e)
|
|
133
|
+
return e.data
|
|
134
|
+
}
|
|
135
|
+
}
|
package/utils/number.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function secureRandomInt(range) {
|
|
2
|
+
const max = Math.floor(0xFFFFFFFF / range) * range;
|
|
3
|
+
let val;
|
|
4
|
+
|
|
5
|
+
do {
|
|
6
|
+
const buffer = new Uint32Array(1);
|
|
7
|
+
window.crypto.getRandomValues(buffer);
|
|
8
|
+
val = buffer[0];
|
|
9
|
+
} while (val >= max);
|
|
10
|
+
|
|
11
|
+
return val % range;
|
|
12
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import {inspectorError, requestInterceptors, responseInterceptors} from './interceptors';
|
|
3
|
+
import {CONTENT_TYPE, setContentType} from './content-type';
|
|
4
|
+
|
|
5
|
+
export * from './url-params';
|
|
6
|
+
export * from './content-type';
|
|
7
|
+
export {responseInterceptors};
|
|
8
|
+
const instance = axios.create({timeout: 5 * 60 * 1000});
|
|
9
|
+
instance.interceptors.request.use(requestInterceptors, inspectorError);
|
|
10
|
+
instance.interceptors.response.use(responseInterceptors, inspectorError);
|
|
11
|
+
instance.formPost = function (url, data, config) {
|
|
12
|
+
const headers = (config === null || config === void 0 ? void 0 : config.headers) || {};
|
|
13
|
+
setContentType(headers, CONTENT_TYPE.form);
|
|
14
|
+
return instance.post(url, data, Object.assign(Object.assign({}, config), {headers}));
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 对业务封装的axios service Api进行封装,封装以后的Api同一时间只有一个网络请求
|
|
19
|
+
* 即上一次发起的网络请求将调用浏览器取消网络请求
|
|
20
|
+
* 注意:如果serviceApi是多个组件共同使用时,需要慎重使用本方法,避免导致由于请求被取消导致的功能异常
|
|
21
|
+
* @param {Function} api - 需要封装的API函数
|
|
22
|
+
* @param {boolean} isPost - 是否是post请求
|
|
23
|
+
* @returns {Function} 封装后可取消的api
|
|
24
|
+
*/
|
|
25
|
+
export const wrapApi = (api, isPost = false) => {
|
|
26
|
+
// 每个函数都有自己的 controller,避免互相干扰
|
|
27
|
+
let currentController = null
|
|
28
|
+
|
|
29
|
+
const wrappedFunction = async function (...args) {
|
|
30
|
+
// 取消之前的请求
|
|
31
|
+
if (currentController) {
|
|
32
|
+
console.log('currentController.abort trigger, now cancel before request')
|
|
33
|
+
currentController.abort()
|
|
34
|
+
currentController = null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 创建新的 AbortController
|
|
38
|
+
const controller = new AbortController()
|
|
39
|
+
currentController = controller
|
|
40
|
+
|
|
41
|
+
// 准备参数
|
|
42
|
+
const newArgs = [...args]
|
|
43
|
+
const lastIndex = newArgs.length - 1
|
|
44
|
+
|
|
45
|
+
// 如果isPost是true,如果参数只有一个和两个,需要新增config参数,如果参数有三个,需要往最后一个参数增加signal
|
|
46
|
+
// 如果isPost是false,如果参数只有一个,需要新增config参数,如果参数有个,需要往最后一个参数增加signal
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// 处理配置参数
|
|
50
|
+
if (
|
|
51
|
+
(isPost ? lastIndex > 1 : lastIndex > 0) &&
|
|
52
|
+
typeof newArgs[lastIndex] === 'object' &&
|
|
53
|
+
!Array.isArray(newArgs[lastIndex])
|
|
54
|
+
) {
|
|
55
|
+
// 最后一个参数是配置对象
|
|
56
|
+
const config = newArgs[lastIndex]
|
|
57
|
+
|
|
58
|
+
// 如果有原生的 signal,需要合并处理
|
|
59
|
+
if (config.signal) {
|
|
60
|
+
// 创建一个新的 AbortController 来合并多个 signal
|
|
61
|
+
const combinedController = new AbortController()
|
|
62
|
+
const originalSignal = config.signal
|
|
63
|
+
|
|
64
|
+
// 监听原始 signal 的取消
|
|
65
|
+
originalSignal.addEventListener('abort', () => {
|
|
66
|
+
combinedController.abort(originalSignal.reason)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// 监听当前 controller 的取消
|
|
70
|
+
controller.signal.addEventListener('abort', () => {
|
|
71
|
+
combinedController.abort(controller.signal.reason)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// 使用合并后的 signal
|
|
75
|
+
newArgs[lastIndex] = {
|
|
76
|
+
...config,
|
|
77
|
+
signal: combinedController.signal,
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
// 直接使用新的 signal
|
|
81
|
+
newArgs[lastIndex] = {
|
|
82
|
+
...config,
|
|
83
|
+
signal: controller.signal,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} else if (isPost && lastIndex === 0) {
|
|
87
|
+
// 没有配置对象且没有data,添加一个
|
|
88
|
+
newArgs.push(null, { signal: controller.signal })
|
|
89
|
+
} else {
|
|
90
|
+
// 没有配置对象,添加一个
|
|
91
|
+
newArgs.push({ signal: controller.signal })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 执行请求
|
|
95
|
+
const result = await api(...newArgs)
|
|
96
|
+
|
|
97
|
+
// 请求成功后清理 controller
|
|
98
|
+
currentController = null
|
|
99
|
+
return result
|
|
100
|
+
} catch (error) {
|
|
101
|
+
// 如果是取消错误,重新抛出
|
|
102
|
+
if (error.name === 'AbortError' || axios.isCancel(error)) {
|
|
103
|
+
throw Object.assign(new Error('Request cancelled'), {
|
|
104
|
+
name: 'AbortError',
|
|
105
|
+
cancelled: true,
|
|
106
|
+
originalError: error,
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 其他错误正常抛出
|
|
111
|
+
throw error
|
|
112
|
+
} finally {
|
|
113
|
+
// 如果当前 controller 仍然是这个请求的,清理它
|
|
114
|
+
if (currentController === controller) {
|
|
115
|
+
currentController = null
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 添加取消方法,允许外部取消
|
|
121
|
+
wrappedFunction.cancel = (reason) => {
|
|
122
|
+
if (currentController) {
|
|
123
|
+
currentController.abort(reason)
|
|
124
|
+
currentController = null
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 添加检查是否正在请求的方法
|
|
129
|
+
wrappedFunction.isPending = () => {
|
|
130
|
+
return currentController !== null
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return wrappedFunction
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 对axios进行封装,返回单例模式的Api
|
|
137
|
+
instance.getSingleton = wrapApi(instance.get)
|
|
138
|
+
instance.postSingleton = wrapApi(instance.post, true)
|
|
139
|
+
instance.formPostSingleton = wrapApi(instance.formPost, true)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
export {instance};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const contentTypeKey = 'Content-Type';
|
|
2
|
+
export function getContentType(config) {
|
|
3
|
+
let type = (config === null || config === void 0 ? void 0 : config[contentTypeKey]) || (config === null || config === void 0 ? void 0 : config['content-type']) || '';
|
|
4
|
+
const suffixIdx = type.indexOf(';');
|
|
5
|
+
if (suffixIdx !== -1) {
|
|
6
|
+
type = type.substring(0, suffixIdx);
|
|
7
|
+
}
|
|
8
|
+
return type;
|
|
9
|
+
}
|
|
10
|
+
export function setContentType(headers, type) {
|
|
11
|
+
headers[contentTypeKey] = type;
|
|
12
|
+
}
|
|
13
|
+
export const CONTENT_TYPE = {
|
|
14
|
+
form: 'application/x-www-form-urlencoded',
|
|
15
|
+
multiForm: 'multipart/form-data',
|
|
16
|
+
body: 'application/json',
|
|
17
|
+
os: 'application/octet-stream',
|
|
18
|
+
json: 'application/json',
|
|
19
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import qs from "qs";
|
|
2
|
+
import { getUrlParams } from "./url-params";
|
|
3
|
+
import { CONTENT_TYPE, getContentType } from "./content-type";
|
|
4
|
+
// import cacheRules from './cache-rules'
|
|
5
|
+
import { getToken } from "../token";
|
|
6
|
+
import { axiosResponse2Str, errorLog } from "../errorLog";
|
|
7
|
+
|
|
8
|
+
const SUCCESS_CODE = 1;
|
|
9
|
+
const SUCCESS_CODE1 = 200;
|
|
10
|
+
const NO_SESSION_CODE = 10106;
|
|
11
|
+
|
|
12
|
+
const CRYPTOJSKEY = "ydyxefgabcdefg12";
|
|
13
|
+
|
|
14
|
+
function aesEncrypt(plaintText) {
|
|
15
|
+
console.log("aesEncrypt plaintText is", plaintText);
|
|
16
|
+
let options = {
|
|
17
|
+
mode: CryptoJS.mode.ECB,
|
|
18
|
+
padding: CryptoJS.pad.Pkcs7,
|
|
19
|
+
};
|
|
20
|
+
let key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY);
|
|
21
|
+
let encryptedData = CryptoJS.AES.encrypt(plaintText, key, options);
|
|
22
|
+
console.log("encryptedData", encryptedData.toString());
|
|
23
|
+
return encryptedData;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let timer = null;
|
|
27
|
+
|
|
28
|
+
function _debounce(callback) {
|
|
29
|
+
if (timer) {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
}
|
|
32
|
+
let callNow = !timer;
|
|
33
|
+
timer = setTimeout(() => {
|
|
34
|
+
timer = null;
|
|
35
|
+
}, 1000 * 20);
|
|
36
|
+
callNow && callback();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 请求的拦截器,处理Content-Type以及加入token
|
|
40
|
+
export function requestInterceptors(config) {
|
|
41
|
+
console.log("requestInterceptors config ", config);
|
|
42
|
+
let token = getToken();
|
|
43
|
+
if (token) {
|
|
44
|
+
config.headers.token = token;
|
|
45
|
+
}
|
|
46
|
+
// 以下拷自lambo-design
|
|
47
|
+
const params = getUrlParams();
|
|
48
|
+
// sso_token认证
|
|
49
|
+
if (
|
|
50
|
+
params.hasOwnProperty("sso_token") ||
|
|
51
|
+
sessionStorage.getItem("sso_token")
|
|
52
|
+
) {
|
|
53
|
+
config.params = Object.assign(
|
|
54
|
+
{
|
|
55
|
+
sso_token: params.sso_token || sessionStorage.getItem("sso_token"),
|
|
56
|
+
sso_id: params.sso_id,
|
|
57
|
+
},
|
|
58
|
+
config.params,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
const contentType = getContentType(config.headers);
|
|
62
|
+
if (config.method === "post") {
|
|
63
|
+
// form 表单方式提交
|
|
64
|
+
if (contentType === CONTENT_TYPE.form) {
|
|
65
|
+
config.data = qs.stringify(config.data);
|
|
66
|
+
} else {
|
|
67
|
+
if (config?.headers?.isEncrypt) {
|
|
68
|
+
config.data = encodeURIComponent(
|
|
69
|
+
Base64.encode(aesEncrypt(JSON.stringify(config.data))),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else if (config.method === "get") {
|
|
74
|
+
// 暂时不要这个逻辑
|
|
75
|
+
// for (let rule of cacheRules) {
|
|
76
|
+
// if (rule.test(config.url)) {
|
|
77
|
+
// return config
|
|
78
|
+
// }
|
|
79
|
+
// }
|
|
80
|
+
// if (config.url.indexOf('?') === -1) {
|
|
81
|
+
// config.url = config.url + '?t=' + new Date().getTime()
|
|
82
|
+
// } else {
|
|
83
|
+
// config.url = config.url + '&t=' + new Date().getTime()
|
|
84
|
+
// }
|
|
85
|
+
}
|
|
86
|
+
console.log('config', config)
|
|
87
|
+
return config;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function responseInterceptors(response) {
|
|
91
|
+
let data = response?.data;
|
|
92
|
+
// 下载文件返回格式不是json
|
|
93
|
+
const contentType = getContentType(response.headers);
|
|
94
|
+
if (contentType !== CONTENT_TYPE.json) {
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
if (typeof response.data === "string") {
|
|
98
|
+
data = JSON.parse(response.data);
|
|
99
|
+
}
|
|
100
|
+
const code = data.code;
|
|
101
|
+
switch (code) {
|
|
102
|
+
case SUCCESS_CODE: {
|
|
103
|
+
if (data?.extInfo?.handleTask) {
|
|
104
|
+
console.log("刷新首页待办:", data?.extInfo?.handleTask);
|
|
105
|
+
window?.top?.getTaskList && window?.top?.getTaskList();
|
|
106
|
+
}
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
case SUCCESS_CODE1: {
|
|
110
|
+
if (data?.extInfo?.handleTask) {
|
|
111
|
+
console.log("刷新首页待办:", data?.extInfo?.handleTask);
|
|
112
|
+
window?.top?.getTaskList && window?.top?.getTaskList();
|
|
113
|
+
}
|
|
114
|
+
return data;
|
|
115
|
+
}
|
|
116
|
+
case NO_SESSION_CODE: {
|
|
117
|
+
_debounce(function () {
|
|
118
|
+
window.sessionNotValidHandler && window.sessionNotValidHandler();
|
|
119
|
+
});
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
default: {
|
|
123
|
+
let msg = data.message || data.msg || "数据请求出错,请稍后尝试";
|
|
124
|
+
if (!response?.config?.url?.includes("manage/error-log/saveErrorLog")) {
|
|
125
|
+
errorLog({
|
|
126
|
+
imsysLogsDesc:
|
|
127
|
+
"服务返回自定义状态码异常:" + axiosResponse2Str(response),
|
|
128
|
+
imsysLogsUrl: response.config.url,
|
|
129
|
+
imsysLogsInput: JSON.stringify(
|
|
130
|
+
response.config.data || response.config.params,
|
|
131
|
+
),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
window.apiErrorHandler && window.apiErrorHandler(msg);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return Promise.reject(data);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function inspectorError(error) {
|
|
141
|
+
if (error?.config?.url?.includes("manage/error-log/saveErrorLog")) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
errorLog({
|
|
145
|
+
imsysLogsDesc: "服务器返回状态码异常:" + axiosResponse2Str(error),
|
|
146
|
+
imsysLogsUrl: error?.config?.url,
|
|
147
|
+
imsysLogsInput: JSON.stringify(error.config.data || error.config.params),
|
|
148
|
+
});
|
|
149
|
+
if (error?.code === "ECONNABORTED") {
|
|
150
|
+
// 超时
|
|
151
|
+
window.apiErrorHandler && window.apiErrorHandler("请求超时,请稍后再试");
|
|
152
|
+
} else if (error?.response?.status !== 200 && error?.message !== "canceled") {
|
|
153
|
+
window.apiErrorHandler && window.apiErrorHandler("请求出错了");
|
|
154
|
+
}
|
|
155
|
+
return Promise.reject(error);
|
|
156
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function getUrlParams() {
|
|
2
|
+
const url = location.search; //获取url中"?"符后的字串
|
|
3
|
+
const theRequest = new Object();
|
|
4
|
+
if (url.indexOf('?') != -1) {
|
|
5
|
+
const str = url.substr(1);
|
|
6
|
+
let strs = str.split('&');
|
|
7
|
+
for (let i = 0; i < strs.length; i++) {
|
|
8
|
+
theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return theRequest;
|
|
12
|
+
}
|