util.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. function friendlyDate(timestamp) {
  2. var formats = {
  3. 'year': '%n% 年前',
  4. 'month': '%n% 月前',
  5. 'day': '%n% 天前',
  6. 'hour': '%n% 小时前',
  7. 'minute': '%n% 分钟前',
  8. 'second': '%n% 秒前',
  9. };
  10. var now = Date.now();
  11. var seconds = Math.floor((now - timestamp) / 1000);
  12. var minutes = Math.floor(seconds / 60);
  13. var hours = Math.floor(minutes / 60);
  14. var days = Math.floor(hours / 24);
  15. var months = Math.floor(days / 30);
  16. var years = Math.floor(months / 12);
  17. var diffType = '';
  18. var diffValue = 0;
  19. if (years > 0) {
  20. diffType = 'year';
  21. diffValue = years;
  22. } else {
  23. if (months > 0) {
  24. diffType = 'month';
  25. diffValue = months;
  26. } else {
  27. if (days > 0) {
  28. diffType = 'day';
  29. diffValue = days;
  30. } else {
  31. if (hours > 0) {
  32. diffType = 'hour';
  33. diffValue = hours;
  34. } else {
  35. if (minutes > 0) {
  36. diffType = 'minute';
  37. diffValue = minutes;
  38. } else {
  39. diffType = 'second';
  40. diffValue = seconds === 0 ? (seconds = 1) : seconds;
  41. }
  42. }
  43. }
  44. }
  45. }
  46. return formats[diffType].replace('%n%', diffValue);
  47. }
  48. function getStorage(key) {
  49. //#ifdef H5
  50. const value = localStorage.getItem(key);
  51. return value !== null && value !== undefined ? value : undefined;
  52. //#endif
  53. //#ifndef H5
  54. const value = uni.getStorageSync(key);
  55. return value !== null && value !== undefined ? value : undefined;
  56. //#endif
  57. }
  58. function setStorage(key, value) {
  59. //#ifdef H5
  60. localStorage.setItem(key, value);
  61. //#endif
  62. //#ifndef H5
  63. return uni.setStorageSync(key, value);
  64. //#endif
  65. }
  66. function removeStorage(key) {
  67. //#ifdef H5
  68. localStorage.removeItem(key);
  69. //#endif
  70. //#ifndef H5
  71. return uni.removeStorageSync(key);
  72. //#endif
  73. }
  74. // #ifdef APP-PLUS
  75. // 文字换行
  76. function drawtext(text, maxWidth) {
  77. let textArr = text.split("");
  78. let len = textArr.length;
  79. let rowText = [];
  80. let currentLine = "";
  81. let currentWidth = 0;
  82. let lastChineseIndex = -1;
  83. for (let i = 0; i < len; i++) {
  84. let char = textArr[i];
  85. let charWidth = 0;
  86. // 计算字符宽度
  87. if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(char)) {
  88. charWidth = 16; // 汉字宽度
  89. lastChineseIndex = i;
  90. } else if (/[a-zA-Z0-9]/g.test(char)) {
  91. charWidth = 8; // 字母和数字宽度
  92. } else {
  93. charWidth = 16; // 其他字符宽度
  94. }
  95. // 处理换行符
  96. if (char === "\n" || (char === "\\" && textArr[i + 1] === "n")) {
  97. if (currentLine) {
  98. rowText.push({
  99. type: "text",
  100. content: currentLine
  101. });
  102. }
  103. rowText.push({
  104. type: "break",
  105. content: ""
  106. });
  107. currentLine = "";
  108. currentWidth = 0;
  109. lastChineseIndex = -1;
  110. if (char === "\\") i++; // 跳过\n中的n
  111. continue;
  112. }
  113. // 检查是否需要换行
  114. if (currentWidth + charWidth > maxWidth) {
  115. if (currentLine) {
  116. // 如果当前字符是汉字,且不是第一个字符,则在上一个汉字处换行
  117. if (lastChineseIndex > 0 && lastChineseIndex < i) {
  118. rowText.push({
  119. type: "text",
  120. content: currentLine.substring(0, lastChineseIndex + 1)
  121. });
  122. currentLine = currentLine.substring(lastChineseIndex + 1) + char;
  123. currentWidth = currentLine.length * charWidth;
  124. } else {
  125. rowText.push({
  126. type: "text",
  127. content: currentLine
  128. });
  129. currentLine = char;
  130. currentWidth = charWidth;
  131. }
  132. } else {
  133. currentLine = char;
  134. currentWidth = charWidth;
  135. }
  136. } else {
  137. currentLine += char;
  138. currentWidth += charWidth;
  139. }
  140. }
  141. // 添加最后一行
  142. if (currentLine) {
  143. rowText.push({
  144. type: "text",
  145. content: currentLine
  146. });
  147. }
  148. return rowText;
  149. }
  150. // 重写app弹窗
  151. uni.showModal = function(options) {
  152. let optionsObj = Object.assign({
  153. title: "提示",
  154. content: "自定义内容",
  155. paratext: "", //副文本内容
  156. align: "center", // 对齐方式 left/center/right
  157. cancelText: "取消", // 取消按钮的文字
  158. cancelColor: "#8F8F8F", // 取消按钮颜色
  159. confirmText: "确定", // 确认按钮文字
  160. confirmColor: "#1C79D6", // 确认按钮颜色
  161. showCancel: true, // 是否显示取消按钮,默认为 true
  162. }, options);
  163. // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
  164. const screenWidth = plus.screen.resolutionWidth;
  165. const screenHeight = plus.screen.resolutionHeight;
  166. //弹窗容器宽度
  167. const popupViewWidth = screenWidth * 0.8;
  168. // 弹窗容器的Padding
  169. const viewContentPadding = 20;
  170. // 弹窗容器的宽度
  171. const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2));
  172. // 描述的列表
  173. const descriptionList = drawtext(optionsObj.content, viewContentWidth);
  174. // 副文本列表
  175. const paraTextList = optionsObj.paratext ? drawtext(optionsObj.paratext, viewContentWidth) : [];
  176. // 弹窗高度
  177. let popupViewHeight = 168;
  178. // 弹窗遮罩层
  179. let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
  180. top: '0px',
  181. left: '0px',
  182. height: '100%',
  183. width: '100%',
  184. backgroundColor: 'rgba(0,0,0,0.5)'
  185. });
  186. let popupViewContentList = [{
  187. tag: 'font',
  188. id: 'title',
  189. text: optionsObj.title,
  190. textStyles: {
  191. size: '18px',
  192. color: "#333",
  193. weight: "bold",
  194. whiteSpace: "normal"
  195. },
  196. position: {
  197. top: viewContentPadding + "px",
  198. left: viewContentPadding + "px",
  199. width: viewContentWidth + "px",
  200. height: "30px",
  201. }
  202. }];
  203. const textHeight = 22;
  204. let contentTop = 65;
  205. descriptionList.forEach((item, index) => {
  206. if (index > 0) {
  207. popupViewHeight += textHeight;
  208. contentTop += textHeight;
  209. }
  210. popupViewContentList.push({
  211. tag: 'font',
  212. id: 'content' + index + 1,
  213. text: item.content,
  214. textStyles: {
  215. size: '16px',
  216. color: "#333",
  217. lineSpacing: "50%",
  218. align: optionsObj.align
  219. },
  220. position: {
  221. top: contentTop + "px",
  222. left: viewContentPadding + "px",
  223. width: viewContentWidth + "px",
  224. height: textHeight + "px",
  225. }
  226. });
  227. if (item.type == "break") {
  228. contentTop += 10;
  229. popupViewHeight += 10;
  230. }
  231. });
  232. // 添加副文本
  233. if (paraTextList.length > 0) {
  234. contentTop += 25; // 增加与正文的间距
  235. popupViewHeight += 25;
  236. paraTextList.forEach((item, index) => {
  237. if (index > 0) {
  238. popupViewHeight += textHeight - 2;
  239. contentTop += textHeight - 2;
  240. }
  241. popupViewContentList.push({
  242. tag: 'font',
  243. id: 'paratext' + index + 1,
  244. text: item.content,
  245. textStyles: {
  246. size: '14px',
  247. color: "#999",
  248. lineSpacing: "50%",
  249. align: optionsObj.align
  250. },
  251. position: {
  252. top: contentTop + "px",
  253. left: viewContentPadding + "px",
  254. width: viewContentWidth + "px",
  255. height: (textHeight - 2) + "px",
  256. }
  257. });
  258. if (item.type == "break") {
  259. contentTop += 10;
  260. popupViewHeight += 10;
  261. }
  262. });
  263. // 在副文本后增加额外间距
  264. contentTop += 10;
  265. popupViewHeight += 10;
  266. }
  267. popupViewContentList.push({
  268. tag: 'rect',
  269. id: 'lineTop',
  270. rectStyles: {
  271. color: "#f1f1f1",
  272. },
  273. position: {
  274. top: contentTop + 50 + "px",
  275. left: "0px",
  276. width: "100%",
  277. height: "1px",
  278. }
  279. });
  280. if (optionsObj.showCancel) {
  281. popupViewContentList.push({
  282. tag: 'rect',
  283. id: 'line',
  284. rectStyles: {
  285. color: "#f1f1f1",
  286. },
  287. position: {
  288. top: contentTop + 50 + "px",
  289. left: popupViewWidth / 2 + "px",
  290. width: "1px",
  291. height: "50px",
  292. }
  293. });
  294. popupViewContentList.push({
  295. tag: 'font',
  296. id: 'cancelText',
  297. text: optionsObj.cancelText,
  298. textStyles: {
  299. size: '16px',
  300. color: optionsObj.cancelColor,
  301. },
  302. position: {
  303. top: contentTop + 50 + "px",
  304. left: "0px",
  305. width: popupViewWidth / 2 + "px",
  306. height: "50px",
  307. }
  308. });
  309. popupViewContentList.push({
  310. tag: 'font',
  311. id: 'confirmText',
  312. text: optionsObj.confirmText,
  313. textStyles: {
  314. size: '16px',
  315. color: optionsObj.confirmColor,
  316. },
  317. position: {
  318. top: contentTop + 50 + "px",
  319. left: popupViewWidth / 2 + "px",
  320. width: popupViewWidth / 2 + "px",
  321. height: "50px",
  322. }
  323. });
  324. } else {
  325. popupViewContentList.push({
  326. tag: 'font',
  327. id: 'confirmText',
  328. text: optionsObj.confirmText,
  329. textStyles: {
  330. size: '16px',
  331. color: optionsObj.confirmColor,
  332. },
  333. position: {
  334. top: contentTop + 50 + "px",
  335. left: "0px",
  336. width: "100%",
  337. height: "50px",
  338. }
  339. });
  340. }
  341. // 弹窗内容
  342. let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
  343. tag: "rect",
  344. top: (screenHeight - popupViewHeight) / 2 + "px",
  345. left: '10%',
  346. height: popupViewHeight + "px",
  347. width: "80%"
  348. });
  349. // 绘制白色背景
  350. popupView.drawRect({
  351. color: "#FFFFFF",
  352. radius: "8px"
  353. }, {
  354. top: "0px",
  355. height: popupViewHeight + "px",
  356. });
  357. popupView.draw(popupViewContentList);
  358. popupView.addEventListener("click", function(e) {
  359. if (optionsObj.showCancel) {
  360. if (e.clientY > popupViewHeight - 50 && e.clientX < popupViewWidth / 2) {
  361. // 取消
  362. maskLayer.close();
  363. popupView.close();
  364. options.success && options.success({
  365. confirm: false,
  366. cancel: true
  367. });
  368. } else if (e.clientY > popupViewHeight - 50 && e.clientX > popupViewWidth / 2) {
  369. // 确定
  370. maskLayer.close();
  371. popupView.close();
  372. options.success && options.success({
  373. confirm: true,
  374. cancel: false
  375. });
  376. }
  377. } else {
  378. if (e.clientY > popupViewHeight - 50) {
  379. // 确定
  380. maskLayer.close();
  381. popupView.close();
  382. options.success && options.success({
  383. confirm: true,
  384. cancel: false
  385. });
  386. }
  387. }
  388. });
  389. // 显示弹窗
  390. maskLayer.show();
  391. popupView.show();
  392. options.complete && options.complete();
  393. };
  394. // #endif
  395. export {
  396. friendlyDate,
  397. getStorage,
  398. setStorage,
  399. removeStorage
  400. }