| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- /**
- * 跳转到指定页面
- * @param {String} url
- * @param {Boolean} isNeedLogin
- * @param {Object} options
- * @returns
- */
- export const navigateTo = async (url, options = {}) => {
- // console.log('navigateTo = ' , url)
- if (!url) {
- return;
- }
- try {
- await uni.navigateTo({
- url,
- ...options,
- });
- // console.log('res = ' , res)
- // if (!res) {
- // uni.reLaunch({
- // url,
- // })
- // }
- } catch (error) {
- console.log("error = ", error);
- uni.reLaunch({
- url,
- });
- //TODO handle the exception
- }
- };
- /**
- * 关闭当前页面跳转到指定页面
- * @param {String} url
- * @param {Boolean} isNeedLogin
- * @returns
- */
- export const redirectTo = async (url) => {
- if (!url) {
- return;
- }
- const res = await uni
- .redirectTo({
- url,
- })
- .catch(console.log);
- if (!res) {
- uni.reLaunch({
- url,
- });
- }
- };
- /**
- * 弹窗展示成功信息
- * @param {String} title 超过 7 个汉字会截断
- * @param {Number} millisecond
- */
- export const successToast = (title, millisecond = 1500) => {
- uni.showToast({
- title,
- });
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve();
- }, millisecond);
- });
- };
- /**
- * 弹窗展示错误信息
- * @param {String} title
- * @param {Number} millisecond
- */
- export const errorToast = (title, millisecond = 1500) => {
- uni.showToast({
- title,
- icon: "none",
- });
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve();
- }, millisecond);
- });
- };
- /**
- * 弹窗确认操作
- * @param {String} content
- * @param {String} title
- * @param {Object} options
- */
- export const confirmModal = (content, title = "提示", options) =>
- new Promise((resolve, reject) => {
- uni.showModal({
- ...options,
- title,
- content,
- success: (modal) => {
- resolve(modal.confirm);
- },
- fail: (err) => {
- reject(err);
- },
- });
- });
- // 日期格式化
- export const parseTime = (time, pattern) => {
- if (!time) {
- return null;
- }
- const format = pattern || "{y}-{m}-{d} {h}:{i}:{s}";
- let date;
- if (typeof time === "object") {
- date = time;
- } else {
- if (typeof time === "string" && /^[0-9]+$/.test(time)) {
- time = parseInt(time);
- } else if (typeof time === "string") {
- time = time
- .replace(new RegExp(/-/gm), "/")
- .replace("T", " ")
- .replace(new RegExp(/\.[\d]{3}/gm), "");
- }
- if (typeof time === "number" && time.toString().length === 10) {
- time = time * 1000;
- }
- date = new Date(time);
- }
- const formatObj = {
- y: date.getFullYear(),
- m: date.getMonth() + 1,
- d: date.getDate(),
- h: date.getHours(),
- i: date.getMinutes(),
- s: date.getSeconds(),
- a: date.getDay(),
- };
- return format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
- let value = formatObj[key];
- // Note: getDay() returns 0 on Sunday
- if (key === "a") {
- return ["日", "一", "二", "三", "四", "五", "六"][value];
- }
- if (result.length > 0 && value < 10) {
- value = "0" + value;
- }
- return value || 0;
- });
- };
- // 处理 微信小程序 图片 视频 表格自适应
- // 处理后的内容(优化图片显示)
- export const processedContent = (value) => {
- if (!value) return "";
- // 处理富文本内容,优化图片自适应
- let content = value;
- // 为图片添加样式,确保自适应
- content = content.replace(/<img([^>]*)>/gi, function (match, attrs) {
- // 移除原有的 width 和 height 属性
- attrs = attrs.replace(/\s*(width|height)\s*=\s*["'][^"']*["']/gi, "");
- // 添加自适应样式
- return `<img${attrs} style="max-width: 100%; width: auto; height: auto; display: block; object-fit: contain;" />`;
- });
- // 为视频添加自适应样式
- content = content.replace(/<video([^>]*)>/gi, function (match, attrs) {
- attrs = attrs.replace(/\s*(width|height)\s*=\s*["'][^"']*["']/gi, "");
- return `<video${attrs} style="max-width: 100%; width: auto; height: auto; display: block; margin: 16rpx auto;" />`;
- });
- // 处理表格自适应
- content = content.replace(
- /<table([^>]*)>/gi,
- '<table$1 style="width: 100%; border-collapse: collapse; font-size: 24rpx; overflow-x: auto; display: block; white-space: nowrap;" />'
- );
- return content;
- };
- /**
- * 取富文本内容的第一段文本
- * */
- export const getFirstParagraph = (htmlString) => {
- if (!htmlString || typeof htmlString !== 'string') return '';
- // 匹配第一个 <p> 标签(兼容 <p>、<p class="..."> 等)
- const pRegex = /<p[^>]*>(.*?)<\/p>/is;
- const match = htmlString.match(pRegex);
- if (!match || !match[1]) return '';
- // 提取到的内容,去除所有标签,保留纯文本
- const innerHTML = match[1];
- const text = innerHTML.replace(/<[^>]+>/g, '').trim(); // 去除所有标签
- return text;
- }
- // 获取标题
- export const getLabel = (val, list) => {
- for (let item of list) {
- if (item.value === val) {
- return item.label || item.text;
- }
- }
- }
- /***
- * 文件下载功能,自动判断环境,h5环境直接打开文件,小程序环境下载到本地
- * @param {String} url
- * @returns {Promise}
- * @description 下载文件到本地,并打开文件
- * */
- export const downloadFile = (url) => {
- if (!url) {
- uni.showToast({ title: "文件地址为空", icon: "none" });
- return Promise.reject(new Error("url is required"));
- }
- const cleanUrl = String(url).split("#")[0].split("?")[0];
- const fileNameFromUrl = cleanUrl.split("/").pop() || "";
- const ext = (fileNameFromUrl.split(".").pop() || "").toLowerCase();
- const isDoc = ["pdf", "docx", "doc", "ppt", "pptx", "xls", "xlsx"].includes(ext);
- const isImage = ["png", "jpeg", "jpg"].includes(ext);
- const fallbackName = ext ? `download.${ext}` : "download";
- const downloadName = fileNameFromUrl || fallbackName;
- uni.showLoading({ title: "文件处理中...", mask: true });
- // #ifdef H5
- return (async () => {
- try {
- if (isImage) {
- window.open(url, "_blank");
- return;
- }
- const response = await fetch(url);
- if (!response.ok) throw new Error(`download failed: ${response.status}`);
- const blob = await response.blob();
- const blobUrl = window.URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.href = blobUrl;
- a.download = downloadName;
- a.style.display = "none";
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- window.URL.revokeObjectURL(blobUrl);
- uni.showToast({ title: "开始下载", icon: "none" });
- } catch (e) {
- try {
- window.open(url, "_blank");
- } catch (_) {}
- uni.showToast({ title: "已在新窗口打开", icon: "none" });
- } finally {
- uni.hideLoading();
- }
- })();
- // #endif
- // #ifndef H5
- return new Promise((resolve, reject) => {
- uni.downloadFile({
- url,
- success: (res) => {
- if (res.statusCode !== 200 || !res.tempFilePath) {
- uni.hideLoading();
- uni.showToast({ title: "下载失败", icon: "none" });
- reject(res);
- return;
- }
- const tempFilePath = res.tempFilePath;
- if (isImage) {
- uni.previewImage({ urls: [tempFilePath] });
- if (!uni.saveImageToPhotosAlbum) {
- uni.hideLoading();
- resolve({ tempFilePath });
- return;
- }
- uni.saveImageToPhotosAlbum({
- filePath: tempFilePath,
- success: () => {
- uni.showToast({ title: "已保存到相册", icon: "none" });
- resolve({ tempFilePath });
- },
- fail: (err) => {
- const errMsg = (err && err.errMsg) || "";
- if (/auth|permission|authorize|denied/i.test(errMsg)) {
- uni.showToast({ title: "请授权保存到相册", icon: "none" });
- } else {
- uni.showToast({ title: "保存相册失败", icon: "none" });
- }
- resolve({ tempFilePath, err });
- },
- complete: () => {
- uni.hideLoading();
- },
- });
- return;
- }
- if (isDoc && uni.openDocument) {
- uni.saveFile({
- tempFilePath,
- success: (saveRes) => {
- uni.openDocument({
- filePath: saveRes.savedFilePath,
- showMenu: true,
- success: () => {
- resolve({ savedFilePath: saveRes.savedFilePath });
- },
- fail: (err) => {
- uni.hideLoading();
- uni.showToast({ title: "文件打开失败", icon: "none" });
- reject(err);
- },
- complete: () => {
- uni.hideLoading();
- },
- });
- },
- fail: (err) => {
- uni.hideLoading();
- uni.showToast({ title: "文件保存失败", icon: "none" });
- reject(err);
- },
- });
- return;
- }
- if (uni.saveFile) {
- uni.saveFile({
- tempFilePath,
- success: (saveRes) => {
- uni.hideLoading();
- uni.showToast({ title: "下载完成", icon: "none" });
- resolve({ savedFilePath: saveRes.savedFilePath });
- },
- fail: () => {
- uni.hideLoading();
- uni.showToast({ title: "下载完成", icon: "none" });
- resolve({ tempFilePath });
- },
- });
- return;
- }
- uni.hideLoading();
- uni.showToast({ title: "下载完成", icon: "none" });
- resolve({ tempFilePath });
- },
- fail: (err) => {
- uni.hideLoading();
- uni.showToast({ title: "下载失败", icon: "none" });
- reject(err);
- },
- });
- });
- // #endif
- };
- /**
- * 保留指定位数小数
- * @param {string|number} value - 要处理的值
- * @param {number} n - 保留的小数位数,默认为2位
- * @returns {string} 处理后的值
- */
- export const retainDecimals = (value, n = 2) => {
- // 确保 n 是正整数
- const decimalPlaces = Math.max(0, Math.floor(n));
- // 转换为字符串处理
- const stringValue = String(value);
- // 移除非数字和小数点的字符
- let cleanValue = stringValue.replace(/[^\d.]/g, "");
- // 处理多个小数点的情况,保留第一个小数点
- const firstDotIndex = cleanValue.indexOf('.');
- if (firstDotIndex !== -1) {
- // 保留第一个小数点前的部分和第一个小数点
- const beforeDot = cleanValue.substring(0, firstDotIndex + 1);
- // 移除第一个小数点后所有的小数点,只保留数字
- const afterDot = cleanValue.substring(firstDotIndex + 1).replace(/\./g, '');
- // 根据参数 n 限制小数点后的位数
- const limitedAfterDot = afterDot.substring(0, decimalPlaces);
- // 如果小数点后没有数字,去除小数点
- if (limitedAfterDot === '') {
- cleanValue = beforeDot.substring(0, firstDotIndex);
- } else {
- cleanValue = beforeDot + limitedAfterDot;
- }
- }
- return cleanValue;
- };
- /**
- * 移除监听
- *
- * */
- export const onOffLine = (eventName = 'popupChange', callback) => {
- uni.$off(eventName, callback)
- };
|