common-utils-kit 1.1.4 → 1.1.18
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/.editorconfig +7 -0
- package/.eslintrc.js +42 -0
- package/.vscode/extensions.json +14 -0
- package/.vscode/settings.json +6 -0
- package/README.md +112 -25
- package/lib/demo.html +1 -0
- package/lib/utils-kit.common.js +14409 -0
- package/lib/utils-kit.css +179 -0
- package/lib/utils-kit.css.map +1 -0
- package/lib/utils-kit.umd.js +14420 -0
- package/lib/utils-kit.umd.min.js +1 -0
- package/package.json +59 -12
- package/index.js +0 -15
- package/src/directives.js +0 -248
- package/src/files.js +0 -109
- package/src/format.js +0 -248
- package/src/test.js +0 -153
- package/src/tool.js +0 -55
package/src/directives.js
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
// 自定义指令基础配置
|
|
3
|
-
const directives = {
|
|
4
|
-
debounce: { // 按钮或者输入框防抖
|
|
5
|
-
// 例子 <el-input v-model="aa" v-debounce="[reset,`input`,1000]" placeholder="输入框数组防抖" />
|
|
6
|
-
// <el-button v-debounce="[reset,`click`,1000]">刷新</el-button>
|
|
7
|
-
inserted: function(el, binding) {
|
|
8
|
-
const [fn, event = "click", time = 1000] = binding.value;
|
|
9
|
-
let timer;
|
|
10
|
-
let flag = true; // 输入法标记
|
|
11
|
-
if (event === "input") {
|
|
12
|
-
el.addEventListener("compositionstart", () => { // 监听中文输入开始
|
|
13
|
-
flag = false;
|
|
14
|
-
});
|
|
15
|
-
el.addEventListener("compositionend", () => { // 监听中文输入结束
|
|
16
|
-
flag = true;
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
el.addEventListener(event, () => {
|
|
20
|
-
timer && clearTimeout(timer);
|
|
21
|
-
timer = setTimeout(() => {
|
|
22
|
-
if (flag) fn();
|
|
23
|
-
}, time);
|
|
24
|
-
});
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
inputDebounce: { // 输入框防抖
|
|
28
|
-
inserted: function (el, binding) {
|
|
29
|
-
const fn = binding.value;
|
|
30
|
-
const time = binding.arg || 500;
|
|
31
|
-
let timer;
|
|
32
|
-
let flag = true; // 输入法标记
|
|
33
|
-
el.addEventListener("compositionstart", () => { // 监听中文输入开始
|
|
34
|
-
flag = false;
|
|
35
|
-
});
|
|
36
|
-
el.addEventListener("compositionend", () => { // 监听中文输入结束
|
|
37
|
-
flag = true;
|
|
38
|
-
});
|
|
39
|
-
el.addEventListener('input', () => {
|
|
40
|
-
timer && clearTimeout(timer);
|
|
41
|
-
timer = setTimeout(() => {
|
|
42
|
-
if (flag) fn();
|
|
43
|
-
}, time);
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
btnDebounce: { // 按钮防抖
|
|
48
|
-
inserted: (el, binding) => {
|
|
49
|
-
const time = binding.arg || 1000; // 防抖时间
|
|
50
|
-
let debounce = null;
|
|
51
|
-
el.addEventListener('click', event => {
|
|
52
|
-
if (debounce !== null) {
|
|
53
|
-
clearTimeout(debounce)
|
|
54
|
-
event && event.stopImmediatePropagation();
|
|
55
|
-
}
|
|
56
|
-
debounce = setTimeout(() => {
|
|
57
|
-
debounce = null
|
|
58
|
-
}, time)
|
|
59
|
-
}, true);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
btnThrottle: { // 按钮节流
|
|
63
|
-
inserted: (el, binding) => {
|
|
64
|
-
const time = binding.arg || 1000; // 间隔时间
|
|
65
|
-
let cbFun;
|
|
66
|
-
el.addEventListener('click', event => {
|
|
67
|
-
if (!cbFun) { // 第一次执行
|
|
68
|
-
cbFun = setTimeout(() => {
|
|
69
|
-
cbFun = null;
|
|
70
|
-
}, time);
|
|
71
|
-
} else {
|
|
72
|
-
event && event.stopImmediatePropagation();
|
|
73
|
-
}
|
|
74
|
-
}, true);
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
relativeTime: { // 时间转换
|
|
78
|
-
bind(el, binding) {
|
|
79
|
-
var intervalTime = 60000
|
|
80
|
-
var Time = {
|
|
81
|
-
getUnix: function () { // 获取当前时间戳
|
|
82
|
-
var date = new Date();
|
|
83
|
-
return date.getTime();
|
|
84
|
-
},
|
|
85
|
-
getTodayUnix: function () { // 获取今天0点0分0秒的时间戳
|
|
86
|
-
var date = new Date();
|
|
87
|
-
date.setHours(0);
|
|
88
|
-
date.setMinutes(0);
|
|
89
|
-
date.setSeconds(0);
|
|
90
|
-
date.setMilliseconds(0);
|
|
91
|
-
return date.getTime();
|
|
92
|
-
},
|
|
93
|
-
getYearUnix: function () { // 获取今年1月1日0点0分0秒的时间戳
|
|
94
|
-
var date = new Date();
|
|
95
|
-
date.setMonth(0);
|
|
96
|
-
date.setDate(1);
|
|
97
|
-
date.setHours(0);
|
|
98
|
-
date.setMinutes(0);
|
|
99
|
-
date.setSeconds(0);
|
|
100
|
-
date.setMilliseconds(0);
|
|
101
|
-
return date.getTime();
|
|
102
|
-
},
|
|
103
|
-
getLastDate: function () { // 获取标准年月日
|
|
104
|
-
var date = new Date();
|
|
105
|
-
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
|
|
106
|
-
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
|
|
107
|
-
return date.getFullYear() + '-' + month + '-' + day;
|
|
108
|
-
},
|
|
109
|
-
getFormatTime: function (timestamp) { // 转换时间
|
|
110
|
-
var now = this.getUnix();// 当前时间戳
|
|
111
|
-
var today = this.getTodayUnix();// 今天0点时间戳
|
|
112
|
-
var timer = (now - timestamp) / 1000;// 转换为妙级别时间戳
|
|
113
|
-
var tip = '';
|
|
114
|
-
if (timer <= 0) {
|
|
115
|
-
tip = '刚刚';
|
|
116
|
-
} else if (Math.floor(timer / 60) <= 0) {
|
|
117
|
-
tip = '刚刚';
|
|
118
|
-
} else if (timer < 3600) {
|
|
119
|
-
tip = Math.floor(timer / 60) + '分钟前';
|
|
120
|
-
} else if (timer >= 3600 && (timestamp - today >= 0)) {
|
|
121
|
-
tip = Math.floor(timer / 3600) + '小时前';
|
|
122
|
-
intervalTime = 3600000;
|
|
123
|
-
} else if (timer / 86400 <= 31) {
|
|
124
|
-
tip = Math.ceil(timer / 86400) + '天前';
|
|
125
|
-
intervalTime = 3600000 * 24;
|
|
126
|
-
} else {
|
|
127
|
-
tip = this.getLastDate(timestamp);
|
|
128
|
-
intervalTime = 3600000 * 24;
|
|
129
|
-
}
|
|
130
|
-
return tip;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
el.innerHTML = Time.getFormatTime(binding.value)
|
|
134
|
-
el.__timeout__ = setInterval(() => {
|
|
135
|
-
el.innerHTML = Time.getFormatTime(binding.value)
|
|
136
|
-
}, intervalTime)
|
|
137
|
-
},
|
|
138
|
-
unbind(el) {
|
|
139
|
-
clearInterval(el.innerHTML)
|
|
140
|
-
delete el.__timeout__
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
replace: {//限制input输入内容
|
|
144
|
-
inserted: function (el, binding, vnode) {
|
|
145
|
-
const element = el.tagName === "INPUT" ? el : el.querySelector("input");
|
|
146
|
-
let flag = true; // 输入法标记
|
|
147
|
-
element.addEventListener("compositionstart", () => {
|
|
148
|
-
flag = false;
|
|
149
|
-
}); // 监听中文输入开始
|
|
150
|
-
element.addEventListener("compositionend", () => {
|
|
151
|
-
flag = true;
|
|
152
|
-
}); // 监听中文输入结束
|
|
153
|
-
element.addEventListener("keyup", () => {
|
|
154
|
-
// 监听中文输入结束
|
|
155
|
-
if (flag) {
|
|
156
|
-
switch (binding.arg) {
|
|
157
|
-
case "price": // 正负的两位小数金额 -和.只能出现一次 并且-只能在首位
|
|
158
|
-
element.value = element.value.replace(/^([-+])?\D*(\d*(?:\.\d{0,2})?).*$/, "$1$2");
|
|
159
|
-
break;
|
|
160
|
-
case "plusPrice": // 验证正的两位小数金额
|
|
161
|
-
element.value = element.value.replace(/^\D*(\d*(?:\.\d{0,2})?).*$/g, "$1");
|
|
162
|
-
break;
|
|
163
|
-
case "num": // 只能输入正整数
|
|
164
|
-
element.value = element.value.replace(/[^\d]|^[0]/g, "");
|
|
165
|
-
break;
|
|
166
|
-
case "natural": // 只能输入自然数
|
|
167
|
-
element.value = element.value.replace(/[^\d]/g, "");
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
elDragDialog: {
|
|
175
|
-
bind(el, binding, vnode) {
|
|
176
|
-
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
|
177
|
-
const dragDom = el.querySelector('.el-dialog')
|
|
178
|
-
dialogHeaderEl.style.cssText += ';cursor:move;'
|
|
179
|
-
dragDom.style.cssText += ';top:0px;'
|
|
180
|
-
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
|
181
|
-
const getStyle = (function () {
|
|
182
|
-
if (window.document.currentStyle) {
|
|
183
|
-
return (dom, attr) => dom.currentStyle[attr]
|
|
184
|
-
} else {
|
|
185
|
-
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
|
186
|
-
}
|
|
187
|
-
})()
|
|
188
|
-
dialogHeaderEl.onmousedown = (e) => {
|
|
189
|
-
// 鼠标按下,计算当前元素距离可视区的距离
|
|
190
|
-
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
|
191
|
-
const disY = e.clientY - dialogHeaderEl.offsetTop
|
|
192
|
-
const dragDomWidth = dragDom.offsetWidth
|
|
193
|
-
const dragDomHeight = dragDom.offsetHeight
|
|
194
|
-
const screenWidth = document.body.clientWidth
|
|
195
|
-
const screenHeight = document.body.clientHeight
|
|
196
|
-
const minDragDomLeft = dragDom.offsetLeft
|
|
197
|
-
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
|
|
198
|
-
const minDragDomTop = dragDom.offsetTop
|
|
199
|
-
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
|
|
200
|
-
// 获取到的值带px 正则匹配替换
|
|
201
|
-
let styL = getStyle(dragDom, 'left')
|
|
202
|
-
let styT = getStyle(dragDom, 'top')
|
|
203
|
-
if (styL.includes('%')) {
|
|
204
|
-
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
|
205
|
-
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
|
206
|
-
} else {
|
|
207
|
-
styL = +styL.replace(/\px/g, '')
|
|
208
|
-
styT = +styT.replace(/\px/g, '')
|
|
209
|
-
}
|
|
210
|
-
document.onmousemove = function (e) {
|
|
211
|
-
// 通过事件委托,计算移动的距离
|
|
212
|
-
let left = e.clientX - disX
|
|
213
|
-
let top = e.clientY - disY
|
|
214
|
-
// 边界处理
|
|
215
|
-
if (-(left) > minDragDomLeft) {
|
|
216
|
-
left = -minDragDomLeft
|
|
217
|
-
} else if (left > maxDragDomLeft) {
|
|
218
|
-
left = maxDragDomLeft
|
|
219
|
-
}
|
|
220
|
-
if (-(top) > minDragDomTop) {
|
|
221
|
-
top = -minDragDomTop
|
|
222
|
-
} else if (top > maxDragDomTop) {
|
|
223
|
-
top = maxDragDomTop
|
|
224
|
-
}
|
|
225
|
-
// 移动当前元素
|
|
226
|
-
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
|
227
|
-
// emit onDrag event
|
|
228
|
-
vnode.child.$emit('dragDialog')
|
|
229
|
-
}
|
|
230
|
-
document.onmouseup = function (e) {
|
|
231
|
-
document.onmousemove = null
|
|
232
|
-
document.onmouseup = null
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
// 批量注册自定义指令
|
|
240
|
-
export default {
|
|
241
|
-
install(Vue) {
|
|
242
|
-
Object.keys(directives).forEach((key) => {
|
|
243
|
-
const name = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
244
|
-
Vue.directive(name, directives[key]);
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
};
|
|
248
|
-
|
package/src/files.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 下载 base64 编码的文件
|
|
3
|
-
* @param {string} url - base64 编码的数据
|
|
4
|
-
* @param {string} type - 文件类型的后缀名
|
|
5
|
-
* @param {string} name - 文件名
|
|
6
|
-
* @returns {Promise<string>} - Promise 对象,包含文件下载成功时的消息或失败时的错误信息
|
|
7
|
-
* @example
|
|
8
|
-
* const base64Data = "data:image/png;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=";
|
|
9
|
-
* downloadBase64File(base64Data, "png", "myImage").then((message) => {
|
|
10
|
-
* console.log(message); // 文件下载成功
|
|
11
|
-
* }).catch((error) => {
|
|
12
|
-
* console.error(error); // 文件下载失败或其他错误信息
|
|
13
|
-
* });
|
|
14
|
-
*/
|
|
15
|
-
export function downloadBase64File(url, type = "pdf", name = "文件" + Date.now()) {
|
|
16
|
-
return new Promise((resolve, reject) => {
|
|
17
|
-
if (!url) return reject('文件不存在');
|
|
18
|
-
const imgType = ["png", "jpg", "gif", "jpeg", "webp", "bmp", "tif", "pcx", "tga", "exif", "fpx", "svg", "psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "WMF",];
|
|
19
|
-
const createBlob = (data, mimeType) => {
|
|
20
|
-
try {
|
|
21
|
-
return new Blob([data], { type: mimeType });
|
|
22
|
-
} catch (e) {
|
|
23
|
-
reject('创建 Blob 失败');
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
let myBlob = null;
|
|
27
|
-
if (imgType.includes(type)) {
|
|
28
|
-
const arr = url.split(",");
|
|
29
|
-
const mime = arr[0].match(/:(.*?);/)[1];
|
|
30
|
-
const bstr = atob(arr[1]);
|
|
31
|
-
const u8arr = new Uint8Array(bstr.length);
|
|
32
|
-
let n = bstr.length;
|
|
33
|
-
for (let i = 0; i < bstr.length; i++) {
|
|
34
|
-
u8arr[i] = bstr.charCodeAt(i);
|
|
35
|
-
}
|
|
36
|
-
myBlob = createBlob(u8arr, mime);
|
|
37
|
-
} else {
|
|
38
|
-
const bstr = atob(url);
|
|
39
|
-
const u8arr = new Uint8Array(bstr.length);
|
|
40
|
-
for (let i = 0; i < bstr.length; i++) {
|
|
41
|
-
u8arr[i] = bstr.charCodeAt(i);
|
|
42
|
-
}
|
|
43
|
-
myBlob = createBlob(u8arr, type);
|
|
44
|
-
}
|
|
45
|
-
const myUrl = URL.createObjectURL(myBlob);
|
|
46
|
-
const a = document.createElement("a");
|
|
47
|
-
a.setAttribute("href", myUrl);
|
|
48
|
-
const fileName = name;
|
|
49
|
-
a.setAttribute("download", fileName);
|
|
50
|
-
a.setAttribute("target", "_blank");
|
|
51
|
-
const clickEvent = document.createEvent("MouseEvents");
|
|
52
|
-
clickEvent.initEvent("click", true, true);
|
|
53
|
-
a.addEventListener("click", () => {
|
|
54
|
-
window.requestAnimationFrame(() => {
|
|
55
|
-
setTimeout(() => {
|
|
56
|
-
URL.revokeObjectURL(myUrl);
|
|
57
|
-
resolve('文件下载成功');
|
|
58
|
-
}, 0);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
a.dispatchEvent(clickEvent);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 文件地址下载文件
|
|
66
|
-
* @param {string} url - 文件地址
|
|
67
|
-
* @param {string} filename - 下载后的文件名
|
|
68
|
-
* @returns {Promise<boolean>} - Promise 对象,表示下载成功(true)或失败(false)
|
|
69
|
-
* @example
|
|
70
|
-
* const fileUrl = "https://example.com/file/document.pdf";
|
|
71
|
-
* const customFileName = "myDocument";
|
|
72
|
-
* downloadFiles(fileUrl, customFileName).then((message) => {
|
|
73
|
-
* console.log(message); // 文件下载成功
|
|
74
|
-
* }).catch((error) => {
|
|
75
|
-
* console.error(error); // 文件下载失败或其他错误信息
|
|
76
|
-
* });
|
|
77
|
-
*/
|
|
78
|
-
export function downloadFiles(url, filename) {
|
|
79
|
-
return new Promise((resolve, reject) => {
|
|
80
|
-
const xhr = new XMLHttpRequest();
|
|
81
|
-
xhr.open("GET", url, true);
|
|
82
|
-
xhr.responseType = "blob";
|
|
83
|
-
xhr.onload = () => {
|
|
84
|
-
if (xhr.status === 200) {
|
|
85
|
-
const decodedUrl = decodeURIComponent(url);
|
|
86
|
-
const matches = decodedUrl.match(/\/([^\/?#]+)[^\/]*$/);
|
|
87
|
-
const newFileName = filename ? (filename.includes('.') ? filename : `${filename}.${matches[1].split('.').pop()}`) : matches[1]
|
|
88
|
-
if (window.navigator.msSaveOrOpenBlob) {
|
|
89
|
-
navigator.msSaveBlob(xhr.response, newFileName);
|
|
90
|
-
} else {
|
|
91
|
-
const link = document.createElement("a");
|
|
92
|
-
link.href = window.URL.createObjectURL(xhr.response);
|
|
93
|
-
link.download = newFileName;
|
|
94
|
-
link.style.position = "absolute";
|
|
95
|
-
link.style.opacity = "0";
|
|
96
|
-
link.style.pointerEvents = "none";
|
|
97
|
-
document.body.appendChild(link);
|
|
98
|
-
link.click();
|
|
99
|
-
document.body.removeChild(link);
|
|
100
|
-
window.URL.revokeObjectURL(link.href);
|
|
101
|
-
}
|
|
102
|
-
resolve("文件下载成功")
|
|
103
|
-
} else {
|
|
104
|
-
reject("文件下载失败")
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
xhr.send();
|
|
108
|
-
});
|
|
109
|
-
}
|
package/src/format.js
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 获取对象属性值,支持可选链操作符的形式
|
|
3
|
-
* @param {Object} obj - 要获取属性值的对象
|
|
4
|
-
* @param {string} key - 属性路径,可以包含点号('.')表示深层嵌套属性
|
|
5
|
-
* @returns {*} - 返回属性值,如果属性不存在则返回 undefined
|
|
6
|
-
* @example
|
|
7
|
-
* const data = {
|
|
8
|
-
* parent: {
|
|
9
|
-
* child: {
|
|
10
|
-
* value: 'Hello, World!'
|
|
11
|
-
* }
|
|
12
|
-
* }
|
|
13
|
-
* };
|
|
14
|
-
* const nestedValue = getProperty(data, 'parent.child.value');
|
|
15
|
-
* console.log(nestedValue); // 输出: Hello, World!
|
|
16
|
-
*/
|
|
17
|
-
export function getProperty(obj, key) {
|
|
18
|
-
if (!obj) { return }
|
|
19
|
-
if (typeof key !== 'string' || key === '') {
|
|
20
|
-
return ''
|
|
21
|
-
}
|
|
22
|
-
if (key.indexOf('.') !== -1) {
|
|
23
|
-
const keys = key.split('.')
|
|
24
|
-
let firstObj = obj[keys[0]] || {}
|
|
25
|
-
for (let i = 1; i < keys.length; i++) {
|
|
26
|
-
if (firstObj) {
|
|
27
|
-
firstObj = firstObj[keys[i]]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return firstObj
|
|
31
|
-
}
|
|
32
|
-
return obj[key]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @description 数组对象去重
|
|
37
|
-
* @param {array} data 需要去重的原数组对象
|
|
38
|
-
* @param {string} parameter 去重数组的唯一码(关键字)
|
|
39
|
-
* @returns {Array} - 返回去重后的数组对象
|
|
40
|
-
* @example
|
|
41
|
-
* // 使用示例
|
|
42
|
-
* const data = [{ id: 1, name: 'John' },{ id: 2, name: 'Jane' },{ id: 1, name: 'John' },{ id: 3, name: 'Doe' }];
|
|
43
|
-
* const uniqueData = unrepeated(data, 'id');
|
|
44
|
-
* console.log(uniqueData); // 输出: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }, { id: 3, name: 'Doe' }]
|
|
45
|
-
*/
|
|
46
|
-
export function unrepeated(data, parameter) {
|
|
47
|
-
var temp = {};
|
|
48
|
-
var tempData = JSON.parse(JSON.stringify(data)); // 深拷贝原来的数据
|
|
49
|
-
var newData = tempData.reduce((pre, cur) => {
|
|
50
|
-
if (!temp[cur[parameter]] && cur[parameter]) {
|
|
51
|
-
temp[cur[parameter]] = true;
|
|
52
|
-
pre.push(cur);
|
|
53
|
-
}
|
|
54
|
-
return pre;
|
|
55
|
-
}, []);
|
|
56
|
-
return newData;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @description 将树形数据转化为一维数组
|
|
61
|
-
* @param {Array} previous - 树形结构数据
|
|
62
|
-
* @param {string} bind - 树形结构中下级节点的绑定属性,默认为 'children'
|
|
63
|
-
* @returns {Array} - 一维数组
|
|
64
|
-
* @example
|
|
65
|
-
* const treeData = [{ id: 1,
|
|
66
|
-
* label: 'parent 1',
|
|
67
|
-
* children: [{ id: 2, label: 'child 1' },{ id: 3, label: 'child 2' }]
|
|
68
|
-
* },{id: 4,
|
|
69
|
-
* label: 'parent 2',
|
|
70
|
-
* children: [{ id: 5, label: 'child 3' },{ id: 6, label: 'child 4' }]
|
|
71
|
-
* }];
|
|
72
|
-
* const flatArray = treeToFlat(treeData,'children');
|
|
73
|
-
* console.log(flatArray);
|
|
74
|
-
* // 输出:[ { id: 1, label: 'parent 1' },{ id: 2, label: 'child 1' }, { id: 3, label: 'child 2' }, { id: 4, label: 'parent 2' },{ id: 5, label: 'child 3' },{ id: 6, label: 'child 4' }]
|
|
75
|
-
*/
|
|
76
|
-
export function treeToFlat(previous=[], bind = 'children') {
|
|
77
|
-
const result = []
|
|
78
|
-
previous.forEach(item => {
|
|
79
|
-
const clonedItem = { ...item };
|
|
80
|
-
if (clonedItem[bind]) {
|
|
81
|
-
result.push(clonedItem)
|
|
82
|
-
if (Array.isArray(previous) && clonedItem[bind].length > 0) {
|
|
83
|
-
result.push(...treeToFlat(clonedItem[bind]))
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
result.push(clonedItem)
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
return result
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* @description 将一维数组转树形结构
|
|
94
|
-
* @param {Array} flatArray - 树形结构数据
|
|
95
|
-
* @param {string} [rootValue=null] - 树形结构一级父 id,默认为 null
|
|
96
|
-
* @param {string} [bind="pid"] - 父 id 的属性,默认为 "pid"
|
|
97
|
-
* @returns {Array} - 树形结构
|
|
98
|
-
* @example
|
|
99
|
-
* const flatArray = [
|
|
100
|
-
* { id: 1, label: 'Node 1', pid: null },
|
|
101
|
-
* { id: 2, label: 'Node 2', pid: 1 },
|
|
102
|
-
* { id: 3, label: 'Node 3', pid: 1 },
|
|
103
|
-
* { id: 4, label: 'Node 4', pid: 2 },
|
|
104
|
-
* { id: 5, label: 'Node 5', pid: 2 },
|
|
105
|
-
* { id: 6, label: 'Node 6', pid: 3 },
|
|
106
|
-
* { id: 7, label: 'Node 7', pid: null },
|
|
107
|
-
* { id: 8, label: 'Node 8', pid: 3 },
|
|
108
|
-
* ];
|
|
109
|
-
* const treeData = flatToTree(flatArray);
|
|
110
|
-
* console.log(treeData);
|
|
111
|
-
* // 输出: [
|
|
112
|
-
* // {
|
|
113
|
-
* // id: 1,
|
|
114
|
-
* // label: 'Node 1',
|
|
115
|
-
* // pid: null,
|
|
116
|
-
* // children: [
|
|
117
|
-
* // { id: 2, label: 'Node 2', pid: 1, children: [ { id: 4, label: 'Node 4', pid: 2 }, { id: 5, label: 'Node 5', pid: 2 } ] },
|
|
118
|
-
* // { id: 3, label: 'Node 3', pid: 1, children: [ { id: 6, label: 'Node 6', pid: 3, children: [ { id: 8, label: 'Node 8', pid: 6 } ] } ] },
|
|
119
|
-
* // ],
|
|
120
|
-
* // },
|
|
121
|
-
* // { id: 7, label: 'Node 7', pid: null },
|
|
122
|
-
* // ]
|
|
123
|
-
*/
|
|
124
|
-
export function flatToTree(flatArray, rootValue = null, bind = "pid") {
|
|
125
|
-
const tree = [];
|
|
126
|
-
flatArray.forEach(item => {
|
|
127
|
-
if (item[bind] === rootValue) {
|
|
128
|
-
const children = flatToTree(flatArray, item.id);
|
|
129
|
-
if (children.length) {
|
|
130
|
-
item.children = children;
|
|
131
|
-
}
|
|
132
|
-
tree.push(item);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
return tree.length > 0 ? tree : null; // 处理不存在的根节点
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* 递归封装
|
|
140
|
-
* @param {Array} data - 待处理的数据
|
|
141
|
-
* @param {Function} funName - 处理每个节点的方法
|
|
142
|
-
* @param {string} [bind="children"] - 子节点绑定属性的名称,默认为 "children"
|
|
143
|
-
* @returns {Array} - 处理后的树形结构数据
|
|
144
|
-
* @example
|
|
145
|
-
* // 数据结构
|
|
146
|
-
* const treeData = [{ id: 1,
|
|
147
|
-
* label: 'parent 1',
|
|
148
|
-
* children: [{ id: 2, label: 'child 1' },{ id: 3, label: 'child 2' }]
|
|
149
|
-
* },{id: 4,
|
|
150
|
-
* label: 'parent 2',
|
|
151
|
-
* children: [{ id: 5, label: 'child 3' },{ id: 6, label: 'child 4' }]
|
|
152
|
-
* }];
|
|
153
|
-
*
|
|
154
|
-
* // 处理逻辑函数,
|
|
155
|
-
* function processFunction(node) {
|
|
156
|
-
* return { label: node.label.toUpperCase() };
|
|
157
|
-
* }
|
|
158
|
-
* // 使用递归封装方法
|
|
159
|
-
* const processedTree = recursionFunction(treeData, processFunction);
|
|
160
|
-
*/
|
|
161
|
-
export function recursionFunction(data, processFunction, bind = 'children') {
|
|
162
|
-
function internalRecursion(previous=[], initial) {
|
|
163
|
-
return previous.map((element, i) => {
|
|
164
|
-
const menus = initial[i] ? processFunction(initial[i]) : {};
|
|
165
|
-
const children = element[bind] && Array.isArray(element[bind]) && element[bind].length > 0
|
|
166
|
-
? internalRecursion(element[bind], initial[i][bind])
|
|
167
|
-
: [];
|
|
168
|
-
return { ...menus,[bind]: children };
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
return internalRecursion(data, data);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* 解析给定函数中switch case语句中的数据并返回提取出值的数组对象。
|
|
176
|
-
* @param {function} filterMethod - 包含带有条件和标签的 case 的函数。
|
|
177
|
-
* @returns {Array} - 包含提取出的值和标签的对象数组。
|
|
178
|
-
* @example
|
|
179
|
-
* const filterMethod = (item) => {
|
|
180
|
-
* switch (item) {
|
|
181
|
-
* case 1://若是字符串请使用单引号
|
|
182
|
-
* return "是";
|
|
183
|
-
* case 2://若是字符串请使用单引号
|
|
184
|
-
* return "否";
|
|
185
|
-
* default:
|
|
186
|
-
* return "数据异常";
|
|
187
|
-
* }
|
|
188
|
-
* };
|
|
189
|
-
* 使用
|
|
190
|
-
* filterData(filterMethod)//[{label:"是",value:1},{label:"否",value:2}]
|
|
191
|
-
*/
|
|
192
|
-
export function filterData(filterMethod) {
|
|
193
|
-
const funStrArr = filterMethod.toString().split("case");
|
|
194
|
-
if (funStrArr.length < 1) return []
|
|
195
|
-
const list = [];
|
|
196
|
-
for (let i = 1; i < funStrArr.length; i++) {
|
|
197
|
-
const condition = funStrArr[i].split(":")[0].replace(/\s*/g, "").replace(/(\"*)/g, "");
|
|
198
|
-
const value = JSON.parse(condition.replace(/'/g, '"'))
|
|
199
|
-
const label = funStrArr[i].split("return")[1].split(";")[0].replace(/\s*/g, "").replace(/(\"*)/g, "");
|
|
200
|
-
if (value || value === 0 || value === false) {
|
|
201
|
-
list.push({ value, label });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return list;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* @description 计算时间差(单位:天)
|
|
208
|
-
* @param {Date} startDate 开始时间 默认当前时间
|
|
209
|
-
* @param {Date} endDate 结束时间 默认当前时间
|
|
210
|
-
* @returns {number} 时间差(天)
|
|
211
|
-
* @example DateDiff(开始时间,结束时间)
|
|
212
|
-
*/
|
|
213
|
-
export function dateDiff(startDate = new Date(), endDate = new Date()) {
|
|
214
|
-
const MS_PER_DAY = 24 * 60 * 60 * 1000; // 一天的毫秒数
|
|
215
|
-
const startTimestamp = new Date(startDate).setHours(0, 0, 0, 0);
|
|
216
|
-
const endTimestamp = new Date(endDate).setHours(0, 0, 0, 0);
|
|
217
|
-
const timeDiff = endTimestamp - startTimestamp;
|
|
218
|
-
const daysDiff = Math.floor(timeDiff / MS_PER_DAY);
|
|
219
|
-
return daysDiff;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* @description 获取当前时间(年月日)
|
|
223
|
-
* @returns {string} 当前时间字符串,格式为 "YYYY-MM-DD"
|
|
224
|
-
* @example getNowDate()
|
|
225
|
-
*/
|
|
226
|
-
export function getNowDate() {
|
|
227
|
-
const timeOne = new Date();
|
|
228
|
-
const year = timeOne.getFullYear();
|
|
229
|
-
const month = String(timeOne.getMonth() + 1).padStart(2, '0');
|
|
230
|
-
const day = String(timeOne.getDate()).padStart(2, '0');
|
|
231
|
-
return `${year}-${month}-${day}`;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* @description form的下拉框 级联选择器等数据赋值
|
|
236
|
-
* @param {Array} columns - form的columns数据
|
|
237
|
-
* @param {String} targetLabel - 需要赋值的columns[i]的label
|
|
238
|
-
* @param {Array} newData - 想要赋值的数据
|
|
239
|
-
* @returns {Array} 包含data的Columns数据
|
|
240
|
-
* @example setFormColumnsData(this.columns, '下单医生', result.data)
|
|
241
|
-
*/
|
|
242
|
-
export function setFormColumnsData(columns, targetLabel, newData) {
|
|
243
|
-
var targetIndex = columns.findIndex(item => item.label === targetLabel);
|
|
244
|
-
if (targetIndex !== -1) {
|
|
245
|
-
columns[targetIndex].data = newData;
|
|
246
|
-
}
|
|
247
|
-
return columns;
|
|
248
|
-
}
|