util.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. align: "center", // 对齐方式 left/center/right
  156. cancelText: "取消", // 取消按钮的文字
  157. cancelColor: "#8F8F8F", // 取消按钮颜色
  158. confirmText: "确定", // 确认按钮文字
  159. confirmColor: "#1C79D6", // 确认按钮颜色
  160. showCancel: true, // 是否显示取消按钮,默认为 true
  161. }, options);
  162. // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
  163. const screenWidth = plus.screen.resolutionWidth;
  164. const screenHeight = plus.screen.resolutionHeight;
  165. //弹窗容器宽度
  166. const popupViewWidth = screenWidth * 0.8;
  167. // 弹窗容器的Padding
  168. const viewContentPadding = 20;
  169. // 弹窗容器的宽度
  170. const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2));
  171. // 描述的列表
  172. const descriptionList = drawtext(optionsObj.content, viewContentWidth);
  173. // 弹窗高度
  174. let popupViewHeight = 168;
  175. // 弹窗遮罩层
  176. let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
  177. top: '0px',
  178. left: '0px',
  179. height: '100%',
  180. width: '100%',
  181. backgroundColor: 'rgba(0,0,0,0.5)'
  182. });
  183. let popupViewContentList = [{
  184. tag: 'font',
  185. id: 'title',
  186. text: optionsObj.title,
  187. textStyles: {
  188. size: '18px',
  189. color: "#333",
  190. weight: "bold",
  191. whiteSpace: "normal"
  192. },
  193. position: {
  194. top: viewContentPadding + "px",
  195. left: viewContentPadding + "px",
  196. width: viewContentWidth + "px",
  197. height: "30px",
  198. }
  199. }];
  200. const textHeight = 22;
  201. let contentTop = 65;
  202. descriptionList.forEach((item, index) => {
  203. if (index > 0) {
  204. popupViewHeight += textHeight;
  205. contentTop += textHeight;
  206. }
  207. popupViewContentList.push({
  208. tag: 'font',
  209. id: 'content' + index + 1,
  210. text: item.content,
  211. textStyles: {
  212. size: '16px',
  213. color: "#333",
  214. lineSpacing: "50%",
  215. align: optionsObj.align
  216. },
  217. position: {
  218. top: contentTop + "px",
  219. left: viewContentPadding + "px",
  220. width: viewContentWidth + "px",
  221. height: textHeight + "px",
  222. }
  223. });
  224. if (item.type == "break") {
  225. contentTop += 10;
  226. popupViewHeight += 10;
  227. }
  228. });
  229. popupViewContentList.push({
  230. tag: 'rect',
  231. id: 'lineTop',
  232. rectStyles: {
  233. color: "#f1f1f1",
  234. },
  235. position: {
  236. top: contentTop + 50 + "px",
  237. left: "0px",
  238. width: "100%",
  239. height: "1px",
  240. }
  241. });
  242. if (optionsObj.showCancel) {
  243. popupViewContentList.push({
  244. tag: 'rect',
  245. id: 'line',
  246. rectStyles: {
  247. color: "#f1f1f1",
  248. },
  249. position: {
  250. top: contentTop + 50 + "px",
  251. left: popupViewWidth / 2 + "px",
  252. width: "1px",
  253. height: "50px",
  254. }
  255. });
  256. popupViewContentList.push({
  257. tag: 'font',
  258. id: 'cancelText',
  259. text: optionsObj.cancelText,
  260. textStyles: {
  261. size: '16px',
  262. color: optionsObj.cancelColor,
  263. },
  264. position: {
  265. top: contentTop + 50 + "px",
  266. left: "0px",
  267. width: popupViewWidth / 2 + "px",
  268. height: "50px",
  269. }
  270. });
  271. popupViewContentList.push({
  272. tag: 'font',
  273. id: 'confirmText',
  274. text: optionsObj.confirmText,
  275. textStyles: {
  276. size: '16px',
  277. color: optionsObj.confirmColor,
  278. },
  279. position: {
  280. top: contentTop + 50 + "px",
  281. left: popupViewWidth / 2 + "px",
  282. width: popupViewWidth / 2 + "px",
  283. height: "50px",
  284. }
  285. });
  286. } else {
  287. popupViewContentList.push({
  288. tag: 'font',
  289. id: 'confirmText',
  290. text: optionsObj.confirmText,
  291. textStyles: {
  292. size: '16px',
  293. color: optionsObj.confirmColor,
  294. },
  295. position: {
  296. top: contentTop + 50 + "px",
  297. left: "0px",
  298. width: "100%",
  299. height: "50px",
  300. }
  301. });
  302. }
  303. // 弹窗内容
  304. let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
  305. tag: "rect",
  306. top: (screenHeight - popupViewHeight) / 2 + "px",
  307. left: '10%',
  308. height: popupViewHeight + "px",
  309. width: "80%"
  310. });
  311. // 绘制白色背景
  312. popupView.drawRect({
  313. color: "#FFFFFF",
  314. radius: "8px"
  315. }, {
  316. top: "0px",
  317. height: popupViewHeight + "px",
  318. });
  319. popupView.draw(popupViewContentList);
  320. popupView.addEventListener("click", function(e) {
  321. if (optionsObj.showCancel) {
  322. if (e.clientY > popupViewHeight - 50 && e.clientX < popupViewWidth / 2) {
  323. // 取消
  324. maskLayer.close();
  325. popupView.close();
  326. options.success && options.success({
  327. confirm: false,
  328. cancel: true
  329. });
  330. } else if (e.clientY > popupViewHeight - 50 && e.clientX > popupViewWidth / 2) {
  331. // 确定
  332. maskLayer.close();
  333. popupView.close();
  334. options.success && options.success({
  335. confirm: true,
  336. cancel: false
  337. });
  338. }
  339. } else {
  340. if (e.clientY > popupViewHeight - 50) {
  341. // 确定
  342. maskLayer.close();
  343. popupView.close();
  344. options.success && options.success({
  345. confirm: true,
  346. cancel: false
  347. });
  348. }
  349. }
  350. });
  351. // 显示弹窗
  352. maskLayer.show();
  353. popupView.show();
  354. options.complete && options.complete();
  355. };
  356. // #endif
  357. export {
  358. friendlyDate,
  359. getStorage,
  360. setStorage,
  361. removeStorage
  362. }