gio-miniprogram-sdk 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +4 -0
- package/.eslintignore +11 -0
- package/.eslintrc.js +120 -0
- package/.github/workflows/greetings.yml +13 -0
- package/.github/workflows/publish.yml +43 -0
- package/.prettierignore +19 -0
- package/.prettierrc.js +9 -0
- package/LICENSE +674 -0
- package/README.md +103 -0
- package/babel.config.js +6 -0
- package/bin/build/all.sh +38 -0
- package/bin/build/full.sh +32 -0
- package/bin/build/jd.sh +14 -0
- package/bin/build/ks.sh +14 -0
- package/bin/build/my.sh +14 -0
- package/bin/build/plugins.sh +5 -0
- package/bin/build/qq.sh +14 -0
- package/bin/build/quickapp.sh +14 -0
- package/bin/build/swan.sh +14 -0
- package/bin/build/taro.sh +18 -0
- package/bin/build/tb.sh +18 -0
- package/bin/build/tt.sh +14 -0
- package/bin/build/uniapp.sh +18 -0
- package/bin/build/wx.sh +14 -0
- package/dist/alipay.js +1 -0
- package/dist/baidu.js +1 -0
- package/dist/bytedance.js +1 -0
- package/dist/jingdong.js +1 -0
- package/dist/kuaishou.js +1 -0
- package/dist/plugins/gioABTest.js +1 -0
- package/dist/plugins/gioCompress.js +1 -0
- package/dist/plugins/gioEventAutoTracking.js +1 -0
- package/dist/plugins/gioImpressionTracking.js +1 -0
- package/dist/qq.js +1 -0
- package/dist/quickapp.js +1 -0
- package/dist/taobao.js +1 -0
- package/dist/taro.js +1 -0
- package/dist/uniapp.js +1 -0
- package/dist/wechat.js +1 -0
- package/package.json +144 -0
- package/rollup.config.js +92 -0
- package/rollup.plugins.config.js +76 -0
- package/src/constants/config.ts +136 -0
- package/src/constants/regex.ts +4 -0
- package/src/core/dataStore/eventContextBuilder.ts +70 -0
- package/src/core/dataStore/eventHooks/appEffects.ts +220 -0
- package/src/core/dataStore/eventHooks/index.ts +403 -0
- package/src/core/dataStore/eventHooks/minipPage.ts +132 -0
- package/src/core/dataStore/eventHooks/pageEffects.ts +168 -0
- package/src/core/dataStore/index.ts +543 -0
- package/src/core/growingIO.ts +433 -0
- package/src/core/plugins.ts +152 -0
- package/src/core/uploader.ts +219 -0
- package/src/core/userStore.ts +203 -0
- package/src/index.ts +68 -0
- package/src/minipInstance/base.ts +287 -0
- package/src/minipInstance/framework.ts +22 -0
- package/src/minipInstance/jd.ts +11 -0
- package/src/minipInstance/ks.ts +12 -0
- package/src/minipInstance/my.ts +53 -0
- package/src/minipInstance/qq.ts +12 -0
- package/src/minipInstance/quickapp.ts +230 -0
- package/src/minipInstance/swan.ts +20 -0
- package/src/minipInstance/tb.ts +53 -0
- package/src/minipInstance/tt.ts +12 -0
- package/src/minipInstance/wx.ts +12 -0
- package/src/platformConfig/base.ts +86 -0
- package/src/platformConfig/framework.ts +29 -0
- package/src/platformConfig/jd.ts +11 -0
- package/src/platformConfig/ks.ts +11 -0
- package/src/platformConfig/my.ts +15 -0
- package/src/platformConfig/qq.ts +13 -0
- package/src/platformConfig/quickapp.ts +48 -0
- package/src/platformConfig/swan.ts +11 -0
- package/src/platformConfig/tb.ts +29 -0
- package/src/platformConfig/tt.ts +11 -0
- package/src/platformConfig/wx.ts +20 -0
- package/src/pluginsOut/README.md +50 -0
- package/src/pluginsOut/frameworks/gioTaobaoAdapter.ts +195 -0
- package/src/pluginsOut/frameworks/gioTaroAdapter.ts +358 -0
- package/src/pluginsOut/frameworks/gioUniAppAdapter.ts +220 -0
- package/src/pluginsOut/ordinary/gioABTest.ts +254 -0
- package/src/pluginsOut/ordinary/gioCompress.ts +251 -0
- package/src/pluginsOut/ordinary/gioCustomTracking.ts +71 -0
- package/src/pluginsOut/ordinary/gioEventAutoTracking.ts +164 -0
- package/src/pluginsOut/ordinary/gioImpressionTracking.ts +298 -0
- package/src/types/base.ts +150 -0
- package/src/types/dataStore.ts +43 -0
- package/src/types/eventHooks.ts +141 -0
- package/src/types/gioCustomTracking.ts +9 -0
- package/src/types/gioEventTracking.ts +10 -0
- package/src/types/gioPerformance.ts +8 -0
- package/src/types/growingIO.ts +102 -0
- package/src/types/minipInstance.ts +126 -0
- package/src/types/platforms.ts +65 -0
- package/src/types/plugins.ts +24 -0
- package/src/types/uploader.ts +26 -0
- package/src/types/userStore.ts +22 -0
- package/src/utils/glodash.ts +423 -0
- package/src/utils/tools.ts +384 -0
- package/src/utils/verifiers.ts +76 -0
- package/tsconfig.json +32 -0
- package/typings/global.d.ts +92 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
export const isNil = (o: any): boolean =>
|
|
2
|
+
['undefined', 'null'].includes(typeOf(o));
|
|
3
|
+
|
|
4
|
+
export const isString = (o: any): boolean => typeOf(o) === 'string';
|
|
5
|
+
|
|
6
|
+
export const isNaN = (value: any) => toString(Number(value)) === 'NaN';
|
|
7
|
+
|
|
8
|
+
export const isNumber = (o: any): boolean => typeOf(o) === 'number';
|
|
9
|
+
|
|
10
|
+
export const isBoolean = (o: any): boolean => typeOf(o) === 'boolean';
|
|
11
|
+
|
|
12
|
+
export const isObject = (o: any): boolean =>
|
|
13
|
+
Object.prototype.toString.call(o) === '[object Object]' && !isNil(o);
|
|
14
|
+
|
|
15
|
+
export const isRegExp = (o: any): boolean =>
|
|
16
|
+
Object.prototype.toString.call(o) === '[object RegExp]';
|
|
17
|
+
|
|
18
|
+
export const isFunction = (o: any): boolean =>
|
|
19
|
+
['function', 'asyncfunction'].includes(typeOf(o));
|
|
20
|
+
|
|
21
|
+
export const isArray = (o: any): boolean =>
|
|
22
|
+
Array.isArray(o) && typeOf(o) === 'array';
|
|
23
|
+
|
|
24
|
+
export const isDate = (o: any): boolean => typeOf(o) === 'date';
|
|
25
|
+
|
|
26
|
+
// Number
|
|
27
|
+
/**
|
|
28
|
+
* 格式化数字,四舍五入取指定小数点后位数
|
|
29
|
+
* @param o number 需要被格式化的数字
|
|
30
|
+
* @param n number 指定格式化位数
|
|
31
|
+
* @returns number
|
|
32
|
+
*/
|
|
33
|
+
export const fixed = (o: any, n?: number): number => {
|
|
34
|
+
if (isNumber(o)) {
|
|
35
|
+
return Number(o.toFixed(isNumber(n) ? n : 2));
|
|
36
|
+
} else if (isString(o) && toString(Number(o)) !== 'NaN') {
|
|
37
|
+
return Number(Number(o).toFixed(isNumber(n) ? n : 2));
|
|
38
|
+
} else {
|
|
39
|
+
return o;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Array
|
|
44
|
+
/**
|
|
45
|
+
* 获取数组第一个元素(类数组无法使用,例:arguments)
|
|
46
|
+
* @param o array
|
|
47
|
+
* @returns target | undefined
|
|
48
|
+
*/
|
|
49
|
+
export const head = (o: any): any => {
|
|
50
|
+
try {
|
|
51
|
+
return Array.from(o)[0];
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 获取数组最后一个元素
|
|
59
|
+
* @param o array
|
|
60
|
+
* @returns target | undefined
|
|
61
|
+
*/
|
|
62
|
+
export const last = (o: any): any => {
|
|
63
|
+
try {
|
|
64
|
+
const ar = Array.from(o);
|
|
65
|
+
return ar[ar.length - 1];
|
|
66
|
+
} catch (error) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 移除数组前n个元素,默认1
|
|
73
|
+
* @param o array
|
|
74
|
+
* @param n ?number
|
|
75
|
+
* @returns new array
|
|
76
|
+
*/
|
|
77
|
+
export const drop = (o: any, n = 1): any =>
|
|
78
|
+
isArray(o) && isNumber(n) ? o.slice(n > 0 ? n : 1, o.length) : o;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 移除数组符合条件的元素
|
|
82
|
+
* @param o array
|
|
83
|
+
* @param fn function,需返回条件
|
|
84
|
+
* @returns new array
|
|
85
|
+
*/
|
|
86
|
+
export const dropWhile = (o: any, fn: (currentValue: any) => boolean): any => {
|
|
87
|
+
if (isArray(o)) {
|
|
88
|
+
return o.filter((c: any) => !fn(c));
|
|
89
|
+
} else {
|
|
90
|
+
return o;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 移除数组中非法数据(undefined、null、0、{}、[]、false)
|
|
96
|
+
* @param o array
|
|
97
|
+
* @returns new array
|
|
98
|
+
*/
|
|
99
|
+
export const compact = (o: any): any => {
|
|
100
|
+
if (isArray(o)) {
|
|
101
|
+
let resIndex = 0;
|
|
102
|
+
const result: any = [];
|
|
103
|
+
for (const value of o) {
|
|
104
|
+
if (value && !isEmpty(value)) {
|
|
105
|
+
result[resIndex++] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
} else {
|
|
110
|
+
return o;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 查找数组中符合条件的元素
|
|
116
|
+
* @param o array
|
|
117
|
+
* @param fn function,需返回条件
|
|
118
|
+
* @returns target | undefined
|
|
119
|
+
*/
|
|
120
|
+
export const find = (o: any, fn: (currentValue: any) => any): any => {
|
|
121
|
+
if (isArray(o)) {
|
|
122
|
+
const i = o.findIndex(fn);
|
|
123
|
+
return i >= 0 ? o[i] : undefined;
|
|
124
|
+
} else {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 判断两个数组中的元素是否一致
|
|
131
|
+
* @param a array1
|
|
132
|
+
* @param b array2
|
|
133
|
+
* @returns boolean
|
|
134
|
+
*/
|
|
135
|
+
export const isEqualArray = (a: any, b: any): boolean => {
|
|
136
|
+
if (!isArray(a) || !isArray(b) || a.length !== b.length) {
|
|
137
|
+
return false;
|
|
138
|
+
} else {
|
|
139
|
+
return a.every((o, i) => o === b[i]);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// String
|
|
144
|
+
/**
|
|
145
|
+
* 将undefined和null以外的数据转为字符串
|
|
146
|
+
* @param o any
|
|
147
|
+
* @returns '' | string
|
|
148
|
+
*/
|
|
149
|
+
export const toString = (o: any): string => (isNil(o) ? '' : `${o}`);
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 将字符串按指定分隔符分隔为数组
|
|
153
|
+
* @param s string
|
|
154
|
+
* @param separator 分隔符
|
|
155
|
+
* @returns array
|
|
156
|
+
*/
|
|
157
|
+
export const split = (s: any, separator?: string): string[] | any =>
|
|
158
|
+
typeOf(s) === 'string' ? s.split(separator) : s;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 将字符串第一个字符转为小写
|
|
162
|
+
* @param s string
|
|
163
|
+
* @returns string
|
|
164
|
+
*/
|
|
165
|
+
export const lowerFirst = (s: any): string | any => {
|
|
166
|
+
if (isString(s)) {
|
|
167
|
+
const sa = split(s, '');
|
|
168
|
+
return `${(head(sa) as string).toLowerCase()}${drop(sa).join('')}`;
|
|
169
|
+
} else {
|
|
170
|
+
return s;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 将字符串第一个字符转为大写
|
|
176
|
+
* @param s string
|
|
177
|
+
* @returns string
|
|
178
|
+
*/
|
|
179
|
+
export const upperFirst = (s: any): string | any => {
|
|
180
|
+
if (isString(s)) {
|
|
181
|
+
const sa = split(s, '');
|
|
182
|
+
return `${(head(sa) as string).toUpperCase()}${drop(sa).join('')}`;
|
|
183
|
+
} else {
|
|
184
|
+
return s;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 判断字符串是否以指定字符开头
|
|
190
|
+
* @param s string
|
|
191
|
+
* @param target string
|
|
192
|
+
* @returns boolean
|
|
193
|
+
*/
|
|
194
|
+
export const startsWith = (s: string, target: string): boolean =>
|
|
195
|
+
s.slice(0, target.length) === target;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 判断字符串是否以指定字符结尾
|
|
199
|
+
* @param s string
|
|
200
|
+
* @param target string
|
|
201
|
+
* @returns boolean
|
|
202
|
+
*/
|
|
203
|
+
export const endsWith = (s: string, target: string): boolean => {
|
|
204
|
+
const { length } = s;
|
|
205
|
+
let position = length;
|
|
206
|
+
if (position > length) {
|
|
207
|
+
position = length;
|
|
208
|
+
}
|
|
209
|
+
const end = position;
|
|
210
|
+
position -= target.length;
|
|
211
|
+
return position >= 0 && s.slice(position, end) === target;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Object
|
|
215
|
+
export const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
216
|
+
/**
|
|
217
|
+
* 判断对象中是否存在指定属性
|
|
218
|
+
* @param o object
|
|
219
|
+
* @param key string
|
|
220
|
+
* @returns boolean
|
|
221
|
+
*/
|
|
222
|
+
export const has = (o: object, key: string): boolean =>
|
|
223
|
+
!isNil(o) && hasOwnProperty.call(o, key);
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 获取对象中所有的属性名
|
|
227
|
+
* @param o object
|
|
228
|
+
* @returns array
|
|
229
|
+
*/
|
|
230
|
+
export const keys = (o: any): string[] => (isObject(o) ? Object.keys(o) : []);
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* 对象遍历
|
|
234
|
+
* @param o object
|
|
235
|
+
* @param fn 遍历回调
|
|
236
|
+
*/
|
|
237
|
+
export const forEach = (
|
|
238
|
+
o: any,
|
|
239
|
+
fn: (value: any, key: string) => void
|
|
240
|
+
): void => {
|
|
241
|
+
keys(o).forEach((k: string) => fn(o[k], k));
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 判断两个对象显式属性与对应值是否相等
|
|
246
|
+
* @param o1 object
|
|
247
|
+
* @param o2 object
|
|
248
|
+
* @returns boolean
|
|
249
|
+
*/
|
|
250
|
+
export const isEqual = (o1: any, o2: any): boolean => {
|
|
251
|
+
const ks = keys(o1);
|
|
252
|
+
if (!isObject(o1) || !isObject(o2) || ks.length !== keys(o2).length) {
|
|
253
|
+
return false;
|
|
254
|
+
} else {
|
|
255
|
+
return !ks
|
|
256
|
+
.map((k, i) => {
|
|
257
|
+
if (isObject(o1[k])) {
|
|
258
|
+
return isEqual(o1[k], o2[k]);
|
|
259
|
+
} else {
|
|
260
|
+
return o1[k] === o2[k];
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
.includes(false);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 获取对象中指定路径的值
|
|
269
|
+
* @param o object
|
|
270
|
+
* @param path string
|
|
271
|
+
* @param defaultValue any
|
|
272
|
+
* @returns target | defaultValue | undefined
|
|
273
|
+
*/
|
|
274
|
+
export const get = (o: any, path: string, defaultValue?: any): any => {
|
|
275
|
+
let target = o;
|
|
276
|
+
if (!isObject(o)) return defaultValue;
|
|
277
|
+
const keys = path.split('.');
|
|
278
|
+
keys.forEach((k: string) => {
|
|
279
|
+
if (target) {
|
|
280
|
+
target = target[k];
|
|
281
|
+
} else {
|
|
282
|
+
target = defaultValue;
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
return target;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 移除对象中指定属性
|
|
290
|
+
* @param o object
|
|
291
|
+
* @param targetProp string | string[] | RegExp
|
|
292
|
+
* @returns boolean | boolean[]
|
|
293
|
+
*/
|
|
294
|
+
export const unset = (
|
|
295
|
+
o: any,
|
|
296
|
+
targetProp: string | string[] | RegExp
|
|
297
|
+
): boolean | boolean[] => {
|
|
298
|
+
if (isObject(o)) {
|
|
299
|
+
try {
|
|
300
|
+
if (typeOf(targetProp) === 'string') {
|
|
301
|
+
// 本来要用Reflect.deleteProperty,但是IE不支持,就用delete
|
|
302
|
+
return delete o[targetProp as string];
|
|
303
|
+
} else if (typeOf(targetProp) === 'array') {
|
|
304
|
+
return (targetProp as string[]).map((s) => delete o[s as string]);
|
|
305
|
+
} else if (
|
|
306
|
+
typeOf(targetProp) === 'object' &&
|
|
307
|
+
targetProp.constructor === RegExp
|
|
308
|
+
) {
|
|
309
|
+
keys(o).forEach((k) => {
|
|
310
|
+
if (targetProp.test(k)) {
|
|
311
|
+
unset(o, k);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
} catch (error) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// Function
|
|
324
|
+
/**
|
|
325
|
+
* 节流函数
|
|
326
|
+
* @param callback function 回调函数
|
|
327
|
+
* @param delay number(ms) 默认250
|
|
328
|
+
* @param noTrailing boolean 如果 noTrailing 为 true,则回调将仅delay在调用节流函数时每delay ms执行一次。如果 noTrailing 为 false 或未指定,回调将在最后一次节流函数调用后执行最后一次。
|
|
329
|
+
* @param debounceMode boolean 如果debounceMode为 true,则安排clear在delay ms之后执行。如果debounceMode为 false,则安排callback在delay ms之后执行 。
|
|
330
|
+
* @returns function
|
|
331
|
+
*/
|
|
332
|
+
export const throttle = (callback, delay = 250, noTrailing, debounceMode?) => {
|
|
333
|
+
let timeoutID;
|
|
334
|
+
let cancelled = false;
|
|
335
|
+
let lastExec = 0;
|
|
336
|
+
function clearExistingTimeout() {
|
|
337
|
+
if (timeoutID) {
|
|
338
|
+
clearTimeout(timeoutID);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (typeOf(noTrailing) !== 'boolean') {
|
|
342
|
+
debounceMode = callback;
|
|
343
|
+
callback = noTrailing;
|
|
344
|
+
noTrailing = undefined;
|
|
345
|
+
}
|
|
346
|
+
function wrapper(...arguments_) {
|
|
347
|
+
let self = this;
|
|
348
|
+
let elapsed = Date.now() - lastExec;
|
|
349
|
+
if (cancelled) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
function exec() {
|
|
353
|
+
lastExec = Date.now();
|
|
354
|
+
callback.apply(self, arguments_);
|
|
355
|
+
}
|
|
356
|
+
function clear() {
|
|
357
|
+
timeoutID = undefined;
|
|
358
|
+
}
|
|
359
|
+
if (debounceMode && !timeoutID) {
|
|
360
|
+
exec();
|
|
361
|
+
}
|
|
362
|
+
clearExistingTimeout();
|
|
363
|
+
if (debounceMode === undefined && elapsed > delay) {
|
|
364
|
+
exec();
|
|
365
|
+
} else if (noTrailing !== true) {
|
|
366
|
+
timeoutID = setTimeout(
|
|
367
|
+
debounceMode ? clear : exec,
|
|
368
|
+
debounceMode === undefined ? delay - elapsed : delay
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return wrapper;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* 判断目标值是否为空([]、{}、''、0、false)
|
|
377
|
+
* @param o any
|
|
378
|
+
* @returns boolean
|
|
379
|
+
*/
|
|
380
|
+
export const isEmpty = (o: any): boolean => {
|
|
381
|
+
if (isArray(o)) {
|
|
382
|
+
return o.length === 0;
|
|
383
|
+
} else if (isObject(o)) {
|
|
384
|
+
return keys(o).length === 0;
|
|
385
|
+
} else {
|
|
386
|
+
return !o;
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* 判断类型
|
|
392
|
+
* @param o any
|
|
393
|
+
* @returns string
|
|
394
|
+
*/
|
|
395
|
+
export const typeOf = (o: any): string => {
|
|
396
|
+
return Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* 格式化时间
|
|
401
|
+
* @param o any
|
|
402
|
+
* @returns string
|
|
403
|
+
*/
|
|
404
|
+
export const formatDate = (e) => {
|
|
405
|
+
function t(e) {
|
|
406
|
+
return e < 10 ? '0' + e : e;
|
|
407
|
+
}
|
|
408
|
+
return (
|
|
409
|
+
e.getFullYear() +
|
|
410
|
+
'-' +
|
|
411
|
+
t(e.getMonth() + 1) +
|
|
412
|
+
'-' +
|
|
413
|
+
t(e.getDate()) +
|
|
414
|
+
' ' +
|
|
415
|
+
t(e.getHours()) +
|
|
416
|
+
':' +
|
|
417
|
+
t(e.getMinutes()) +
|
|
418
|
+
':' +
|
|
419
|
+
t(e.getSeconds()) +
|
|
420
|
+
'.' +
|
|
421
|
+
t(e.getMilliseconds())
|
|
422
|
+
);
|
|
423
|
+
};
|