liyong
2025-04-25 14eef62db43d4d1b7a5bada04032faaecffecb9e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
// [z-paging]工具类
 
import zLocalConfig from '../config/index'
import c from './z-paging-constant'
 
const storageKey = 'Z-PAGING-REFRESHER-TIME-STORAGE-KEY';
let config = null;
let configLoaded = false;
let cachedSystemInfo = null;
const timeoutMap = {};
 
// 获取默认配置信息
function gc(key, defaultValue) {
    // 这里return一个函数以解决在vue3+appvue中,props默认配置读取在main.js之前执行导致uni.$zp全局配置无效的问题。相当于props的default中传入一个带有返回值的函数
    return () => {
        // 处理z-paging全局配置
        _handleDefaultConfig();
        // 如果全局配置不存在,则返回默认值
        if (!config) return defaultValue;
        const value = config[key];
        // 如果全局配置存在但对应的配置项不存在,则返回默认值;反之返回配置项
        return value === undefined ? defaultValue : value;
    };
}
 
// 获取最终的touch位置
function getTouch(e) {
    let touch = null;
    if (e.touches && e.touches.length) {
        touch = e.touches[0];
    } else if (e.changedTouches && e.changedTouches.length) {
        touch = e.changedTouches[0];
    } else if (e.datail && e.datail != {}) {
        touch = e.datail;
    } else {
        return { touchX: 0, touchY: 0 }
    }
    return {
        touchX: touch.clientX,
        touchY: touch.clientY
    };
}
 
// 判断当前手势是否在z-paging内触发
function getTouchFromZPaging(target) {
    if (target && target.tagName && target.tagName !== 'BODY' && target.tagName !== 'UNI-PAGE-BODY') {
        const classList = target.classList;
        if (classList && classList.contains('z-paging-content')) {
            // 此处额外记录当前z-paging是否是页面滚动、是否滚动到了顶部、是否是聊天记录模式以传给renderjs。避免不同z-paging组件renderjs内部判断数据互相影响导致的各种问题
            return {
                isFromZp: true,
                isPageScroll: classList.contains('z-paging-content-page'),
                isReachedTop: classList.contains('z-paging-reached-top'),
                isUseChatRecordMode: classList.contains('z-paging-use-chat-record-mode')
            };
        } else {
            return getTouchFromZPaging(target.parentNode);
        }
    } else {
        return { isFromZp: false };
    }
}
 
// 递归获取z-paging所在的parent,如果查找不到则返回null
function getParent(parent) {
    if (!parent) return null;
    if (parent.$refs.paging) return parent;
    return getParent(parent.$parent);
}
 
// 打印错误信息
function consoleErr(err) {
    console.error(`[z-paging]${err}`);
}
 
// 延时操作,如果key存在,调用时清除对应key之前的延时操作
function delay(callback, ms = c.delayTime, key) {
    const timeout = setTimeout(callback, ms);;
    if (!!key) {
        timeoutMap[key] && clearTimeout(timeoutMap[key]);
        timeoutMap[key] = timeout;
    }
    return timeout;
}
 
// 设置下拉刷新时间
function setRefesrherTime(time, key) {
    const datas = getRefesrherTime() || {};
    datas[key] = time;
    uni.setStorageSync(storageKey, datas);
}
 
// 获取下拉刷新时间
function getRefesrherTime() {
    return uni.getStorageSync(storageKey);
}
 
// 通过下拉刷新标识key获取下拉刷新时间
function getRefesrherTimeByKey(key) {
    const datas = getRefesrherTime();
    return datas && datas[key] ? datas[key] : null;
}
 
// 通过下拉刷新标识key获取下拉刷新时间(格式化之后)
function getRefesrherFormatTimeByKey(key, textMap) {
    const time = getRefesrherTimeByKey(key);
    const timeText = time ? _timeFormat(time, textMap) : textMap.none;
    return `${textMap.title}${timeText}`;
}
 
// 将文本的px或者rpx转为px的值
function convertToPx(text) {
    const dataType = Object.prototype.toString.call(text);
    if (dataType === '[object Number]') return text;
    let isRpx = false;
    if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) {
        text = text.replace('rpx', '').replace('upx', '');
        isRpx = true;
    } else if (text.indexOf('px') !== -1) {
        text = text.replace('px', '');
    }
    if (!isNaN(text)) {
        if (isRpx) return Number(rpx2px(text));
        return Number(text);
    }
    return 0;
}
 
// rpx => px,预留的兼容处理
function rpx2px(rpx) {
    return uni.upx2px(rpx);
}
 
// 同步获取系统信息,兼容不同平台
function getSystemInfoSync(useCache = false) {
    if (useCache && cachedSystemInfo) {
        return cachedSystemInfo;
    }
    // 目前只用到了deviceInfo、appBaseInfo和windowInfo中的信息,因此仅整合这两个信息数据
    const infoTypes = ['DeviceInfo', 'AppBaseInfo', 'WindowInfo'];
    const { deviceInfo, appBaseInfo, windowInfo } = infoTypes.reduce((acc, key) => {
        const method = `get${key}`;
        if (uni[method] && uni.canIUse(method)) {
            acc[key.charAt(0).toLowerCase() + key.slice(1)] = uni[method]();
        }
        return acc;
    }, {});
    // 如果deviceInfo、appBaseInfo和windowInfo都可以从各自专属的api中获取,则整合它们的数据
    if (deviceInfo && appBaseInfo && windowInfo) {
        cachedSystemInfo = { ...deviceInfo, ...appBaseInfo, ...windowInfo };
    } else {
        // 使用uni.getSystemInfoSync兜底,确保能获取到最终的系统信息
        cachedSystemInfo = uni.getSystemInfoSync();
    }
    return cachedSystemInfo;
}
 
// 获取当前时间
function getTime() {
    return (new Date()).getTime();
}
 
// 获取z-paging实例id,随机生成10位数字+字母
function getInstanceId() {
    const s = [];
    const hexDigits = "0123456789abcdef";
    for (let i = 0; i < 10; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    return s.join('') + getTime();
}
 
// 等待一段时间
function wait(ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms);
    });
}
 
// 是否是promise
function isPromise(func) {
    return Object.prototype.toString.call(func) === '[object Promise]';
}
 
// 添加单位
function addUnit(value, unit) {
    if (Object.prototype.toString.call(value) === '[object String]') {
        let tempValue = value;
        tempValue = tempValue.replace('rpx', '').replace('upx', '').replace('px', '');
        if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1 && value.indexOf('px') !== -1) {
            tempValue = parseFloat(tempValue) * 2;
        }
        value = tempValue;
    }
    return unit === 'rpx' ? value + 'rpx' : (value / 2) + 'px';
}
 
// 深拷贝
function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) return obj;
    let newObj = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = deepCopy(obj[key]);
        }
    }
    return newObj;
}
 
// ------------------ 私有方法 ------------------------
// 处理全局配置
function _handleDefaultConfig() {
    // 确保只加载一次全局配置
    if (configLoaded) return;
    // 优先从config.js中读取
    if (zLocalConfig && Object.keys(zLocalConfig).length) {
        config = zLocalConfig;
    }
    // 如果在config.js中读取不到,则尝试到uni.$zp读取
    if (!config && uni.$zp) {
        config = uni.$zp.config;
    }
    // 将config中的短横线写法全部转为驼峰写法,使得读取配置时可以直接通过key去匹配,而非读取每个配置时候再去转,减少不必要的性能开支
    config = config ? Object.keys(config).reduce((result, key) => {
        result[_toCamelCase(key)] = config[key];
        return result;
    }, {}) : null;
    configLoaded = true;
}
 
// 时间格式化
function _timeFormat(time, textMap) {
    const date = new Date(time);
    const currentDate = new Date();
    // 设置time对应的天,去除时分秒,使得可以直接比较日期
    const dateDay = new Date(time).setHours(0, 0, 0, 0);
    // 设置当前的天,去除时分秒,使得可以直接比较日期
    const currentDateDay = new Date().setHours(0, 0, 0, 0);
    const disTime = dateDay - currentDateDay;
    let dayStr = '';
    const timeStr = _dateTimeFormat(date);
    if (disTime === 0) {
        dayStr = textMap.today;
    } else if (disTime === -86400000) {
        dayStr = textMap.yesterday;
    } else {
        dayStr = _dateDayFormat(date, date.getFullYear() !== currentDate.getFullYear());
    }
    return `${dayStr} ${timeStr}`;
}
 
// date格式化为年月日
function _dateDayFormat(date, showYear = true) {
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    return showYear ? `${year}-${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}` : `${_fullZeroToTwo(month)}-${_fullZeroToTwo(day)}`;
}
 
// data格式化为时分
function _dateTimeFormat(date) {
    const hour = date.getHours();
    const minute = date.getMinutes();
    return `${_fullZeroToTwo(hour)}:${_fullZeroToTwo(minute)}`;
}
 
// 不满2位在前面填充0
function _fullZeroToTwo(str) {
    str = str.toString();
    return str.length === 1 ? '0' + str : str;
}
 
// 驼峰转短横线
function _toKebab(value) {
    return value.replace(/([A-Z])/g, "-$1").toLowerCase();
}
 
// 短横线转驼峰
function _toCamelCase(value) {
    return value.replace(/-([a-z])/g, (_, group1) => group1.toUpperCase());
}
 
 
export default {
    gc,
    setRefesrherTime,
    getRefesrherFormatTimeByKey,
    getTouch,
    getTouchFromZPaging,
    getParent,
    convertToPx,
    getTime,
    getInstanceId,
    consoleErr,
    delay,
    wait,
    isPromise,
    addUnit,
    deepCopy,
    rpx2px,
    getSystemInfoSync
};