function friendlyDate(timestamp) { var formats = { 'year': '%n% 年前', 'month': '%n% 月前', 'day': '%n% 天前', 'hour': '%n% 小时前', 'minute': '%n% 分钟前', 'second': '%n% 秒前', }; var now = Date.now(); var seconds = Math.floor((now - timestamp) / 1000); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); var days = Math.floor(hours / 24); var months = Math.floor(days / 30); var years = Math.floor(months / 12); var diffType = ''; var diffValue = 0; if (years > 0) { diffType = 'year'; diffValue = years; } else { if (months > 0) { diffType = 'month'; diffValue = months; } else { if (days > 0) { diffType = 'day'; diffValue = days; } else { if (hours > 0) { diffType = 'hour'; diffValue = hours; } else { if (minutes > 0) { diffType = 'minute'; diffValue = minutes; } else { diffType = 'second'; diffValue = seconds === 0 ? (seconds = 1) : seconds; } } } } } return formats[diffType].replace('%n%', diffValue); } function getStorage(key) { //#ifdef H5 const value = localStorage.getItem(key); return value !== null && value !== undefined ? value : undefined; //#endif //#ifndef H5 const value = uni.getStorageSync(key); return value !== null && value !== undefined ? value : undefined; //#endif } function setStorage(key, value) { //#ifdef H5 localStorage.setItem(key, value); //#endif //#ifndef H5 return uni.setStorageSync(key, value); //#endif } function removeStorage(key) { //#ifdef H5 localStorage.removeItem(key); //#endif //#ifndef H5 return uni.removeStorageSync(key); //#endif } // #ifdef APP-PLUS // 文字换行 function drawtext(text, maxWidth) { let textArr = text.split(""); let len = textArr.length; let rowText = []; let currentLine = ""; let currentWidth = 0; let lastChineseIndex = -1; for (let i = 0; i < len; i++) { let char = textArr[i]; let charWidth = 0; // 计算字符宽度 if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(char)) { charWidth = 16; // 汉字宽度 lastChineseIndex = i; } else if (/[a-zA-Z0-9]/g.test(char)) { charWidth = 8; // 字母和数字宽度 } else { charWidth = 16; // 其他字符宽度 } // 处理换行符 if (char === "\n" || (char === "\\" && textArr[i + 1] === "n")) { if (currentLine) { rowText.push({ type: "text", content: currentLine }); } rowText.push({ type: "break", content: "" }); currentLine = ""; currentWidth = 0; lastChineseIndex = -1; if (char === "\\") i++; // 跳过\n中的n continue; } // 检查是否需要换行 if (currentWidth + charWidth > maxWidth) { if (currentLine) { // 如果当前字符是汉字,且不是第一个字符,则在上一个汉字处换行 if (lastChineseIndex > 0 && lastChineseIndex < i) { rowText.push({ type: "text", content: currentLine.substring(0, lastChineseIndex + 1) }); currentLine = currentLine.substring(lastChineseIndex + 1) + char; currentWidth = currentLine.length * charWidth; } else { rowText.push({ type: "text", content: currentLine }); currentLine = char; currentWidth = charWidth; } } else { currentLine = char; currentWidth = charWidth; } } else { currentLine += char; currentWidth += charWidth; } } // 添加最后一行 if (currentLine) { rowText.push({ type: "text", content: currentLine }); } return rowText; } // 重写app弹窗 uni.showModal = function(options) { let optionsObj = Object.assign({ title: "提示", content: "自定义内容", paratext: "", //副文本内容 align: "center", // 对齐方式 left/center/right cancelText: "取消", // 取消按钮的文字 cancelColor: "#8F8F8F", // 取消按钮颜色 confirmText: "确定", // 确认按钮文字 confirmColor: "#1C79D6", // 确认按钮颜色 showCancel: true, // 是否显示取消按钮,默认为 true }, options); // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心 const screenWidth = plus.screen.resolutionWidth; const screenHeight = plus.screen.resolutionHeight; //弹窗容器宽度 const popupViewWidth = screenWidth * 0.8; // 弹窗容器的Padding const viewContentPadding = 20; // 弹窗容器的宽度 const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2)); // 描述的列表 const descriptionList = drawtext(optionsObj.content, viewContentWidth); // 副文本列表 const paraTextList = optionsObj.paratext ? drawtext(optionsObj.paratext, viewContentWidth) : []; // 弹窗高度 let popupViewHeight = 168; // 弹窗遮罩层 let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层 top: '0px', left: '0px', height: '100%', width: '100%', backgroundColor: 'rgba(0,0,0,0.5)' }); let popupViewContentList = [{ tag: 'font', id: 'title', text: optionsObj.title, textStyles: { size: '18px', color: "#333", weight: "bold", whiteSpace: "normal" }, position: { top: viewContentPadding + "px", left: viewContentPadding + "px", width: viewContentWidth + "px", height: "30px", } }]; const textHeight = 22; let contentTop = 65; descriptionList.forEach((item, index) => { if (index > 0) { popupViewHeight += textHeight; contentTop += textHeight; } popupViewContentList.push({ tag: 'font', id: 'content' + index + 1, text: item.content, textStyles: { size: '16px', color: "#333", lineSpacing: "50%", align: optionsObj.align }, position: { top: contentTop + "px", left: viewContentPadding + "px", width: viewContentWidth + "px", height: textHeight + "px", } }); if (item.type == "break") { contentTop += 10; popupViewHeight += 10; } }); // 添加副文本 if (paraTextList.length > 0) { contentTop += 25; // 增加与正文的间距 popupViewHeight += 25; paraTextList.forEach((item, index) => { if (index > 0) { popupViewHeight += textHeight - 2; contentTop += textHeight - 2; } popupViewContentList.push({ tag: 'font', id: 'paratext' + index + 1, text: item.content, textStyles: { size: '14px', color: "#999", lineSpacing: "50%", align: optionsObj.align }, position: { top: contentTop + "px", left: viewContentPadding + "px", width: viewContentWidth + "px", height: (textHeight - 2) + "px", } }); if (item.type == "break") { contentTop += 10; popupViewHeight += 10; } }); // 在副文本后增加额外间距 contentTop += 10; popupViewHeight += 10; } popupViewContentList.push({ tag: 'rect', id: 'lineTop', rectStyles: { color: "#f1f1f1", }, position: { top: contentTop + 50 + "px", left: "0px", width: "100%", height: "1px", } }); if (optionsObj.showCancel) { popupViewContentList.push({ tag: 'rect', id: 'line', rectStyles: { color: "#f1f1f1", }, position: { top: contentTop + 50 + "px", left: popupViewWidth / 2 + "px", width: "1px", height: "50px", } }); popupViewContentList.push({ tag: 'font', id: 'cancelText', text: optionsObj.cancelText, textStyles: { size: '16px', color: optionsObj.cancelColor, }, position: { top: contentTop + 50 + "px", left: "0px", width: popupViewWidth / 2 + "px", height: "50px", } }); popupViewContentList.push({ tag: 'font', id: 'confirmText', text: optionsObj.confirmText, textStyles: { size: '16px', color: optionsObj.confirmColor, }, position: { top: contentTop + 50 + "px", left: popupViewWidth / 2 + "px", width: popupViewWidth / 2 + "px", height: "50px", } }); } else { popupViewContentList.push({ tag: 'font', id: 'confirmText', text: optionsObj.confirmText, textStyles: { size: '16px', color: optionsObj.confirmColor, }, position: { top: contentTop + 50 + "px", left: "0px", width: "100%", height: "50px", } }); } // 弹窗内容 let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单 tag: "rect", top: (screenHeight - popupViewHeight) / 2 + "px", left: '10%', height: popupViewHeight + "px", width: "80%" }); // 绘制白色背景 popupView.drawRect({ color: "#FFFFFF", radius: "8px" }, { top: "0px", height: popupViewHeight + "px", }); popupView.draw(popupViewContentList); popupView.addEventListener("click", function(e) { if (optionsObj.showCancel) { if (e.clientY > popupViewHeight - 50 && e.clientX < popupViewWidth / 2) { // 取消 maskLayer.close(); popupView.close(); options.success && options.success({ confirm: false, cancel: true }); } else if (e.clientY > popupViewHeight - 50 && e.clientX > popupViewWidth / 2) { // 确定 maskLayer.close(); popupView.close(); options.success && options.success({ confirm: true, cancel: false }); } } else { if (e.clientY > popupViewHeight - 50) { // 确定 maskLayer.close(); popupView.close(); options.success && options.success({ confirm: true, cancel: false }); } } }); // 显示弹窗 maskLayer.show(); popupView.show(); options.complete && options.complete(); }; // #endif export { friendlyDate, getStorage, setStorage, removeStorage }