|
@@ -0,0 +1,178 @@
|
|
|
+import html2canvas from "html2canvas";
|
|
|
+import { uploadBase64 } from "./uploadImg";
|
|
|
+import wx from "weixin-js-sdk";
|
|
|
+
|
|
|
+function detectRuntimeEnvironment() {
|
|
|
+ // Node.js环境
|
|
|
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
|
+ return "nodejs";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 微信小程序环境
|
|
|
+ if (typeof wx !== "undefined" && wx && wx.getSystemInfo) {
|
|
|
+ return "wechat-miniprogram";
|
|
|
+ }
|
|
|
+
|
|
|
+ // WebView环境
|
|
|
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
|
+ // 检查是否在微信内置浏览器中
|
|
|
+ const ua = navigator.userAgent.toLowerCase();
|
|
|
+ if (ua.match(/micromessenger/i)) {
|
|
|
+ return "wechat-webview";
|
|
|
+ }
|
|
|
+
|
|
|
+ return "browser";
|
|
|
+ }
|
|
|
+
|
|
|
+ // React Native环境
|
|
|
+ if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
|
+ return "react-native";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 未知环境
|
|
|
+ return "unknown";
|
|
|
+}
|
|
|
+
|
|
|
+// 深拷贝
|
|
|
+function deepClone(obj) {
|
|
|
+ if (typeof obj !== "object" || obj === null) {
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+ const target = obj.constructor === Array ? [] : {};
|
|
|
+ for (var key in obj) {
|
|
|
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
|
+ if (typeof obj[key] === "object") {
|
|
|
+ target[key] = deepClone(obj[key]);
|
|
|
+ } else {
|
|
|
+ target[key] = obj[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return target;
|
|
|
+}
|
|
|
+
|
|
|
+function extractCoordinates(input) {
|
|
|
+ // 使用正则表达式匹配括号内的内容
|
|
|
+ const match = input.match(/\(([^)]+)\)/);
|
|
|
+
|
|
|
+ if (match) {
|
|
|
+ // 如果找到了匹配项,match[1] 将包含括号内的内容
|
|
|
+ // 然后我们按照空格分割这个字符串来获取坐标
|
|
|
+ const coordinates = match[1].split(" ").map(Number); // 将每个坐标转换为数字
|
|
|
+ return coordinates;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果没有找到匹配项,返回null或其他合适的值
|
|
|
+ return null;
|
|
|
+}
|
|
|
+
|
|
|
+// 节流 => 一定时间内只调用一次函数
|
|
|
+function throttle(func, wait) {
|
|
|
+ let timeout = null;
|
|
|
+ let lastRun = 0;
|
|
|
+
|
|
|
+ return function (...args) {
|
|
|
+ const now = new Date().getTime();
|
|
|
+
|
|
|
+ if (!lastRun) {
|
|
|
+ // 如果 lastRun 没有被设置,表示这是第一次调用
|
|
|
+ func.apply(this, args);
|
|
|
+ lastRun = now;
|
|
|
+ } else {
|
|
|
+ clearTimeout(timeout);
|
|
|
+ // 设置一个新的超时,在 wait 时间后再次运行函数
|
|
|
+ timeout = setTimeout(() => {
|
|
|
+ if (now - lastRun >= wait) {
|
|
|
+ func.apply(this, args);
|
|
|
+ lastRun = now;
|
|
|
+ }
|
|
|
+ }, wait - (now - lastRun));
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// 下载图片的函数
|
|
|
+async function downloadImage(downDom) {
|
|
|
+ if (downDom) {
|
|
|
+ const canvas = await html2canvas(downDom, {
|
|
|
+ useCORS: true, // 支持跨域图片
|
|
|
+ // scale: 2, // 提高生成图片分辨率
|
|
|
+ });
|
|
|
+ // 2. 创建最终合成的 Canvas
|
|
|
+ const finalCanvas = document.createElement("canvas");
|
|
|
+ const ctx = finalCanvas.getContext("2d");
|
|
|
+
|
|
|
+ // 设置最终图片大小
|
|
|
+ finalCanvas.width = canvas.width;
|
|
|
+ finalCanvas.height = canvas.height;
|
|
|
+
|
|
|
+ // 绘制 DOM 转换的内容
|
|
|
+ ctx.drawImage(canvas, 0, 0);
|
|
|
+
|
|
|
+ // 3. 加载本地二维码图片
|
|
|
+ const qrImage = new Image();
|
|
|
+ // qrImage.src = require("@/assets/img/weather_index/code.png"); // 本地二维码路径
|
|
|
+
|
|
|
+ // 等待二维码图片加载完成后绘制到 Canvas
|
|
|
+ qrImage.onload = () => {
|
|
|
+ const qrWidth = 48 * 3; // 二维码宽度
|
|
|
+ const qrHeight = 74 * 3; // 二维码高度
|
|
|
+ const padding = 8 * 3; // 边距
|
|
|
+
|
|
|
+ // 绘制二维码到最终 Canvas 的右上角
|
|
|
+ ctx.drawImage(
|
|
|
+ qrImage,
|
|
|
+ canvas.width - qrWidth - padding, // 右边距
|
|
|
+ padding, // 上边距
|
|
|
+ qrWidth,
|
|
|
+ qrHeight
|
|
|
+ );
|
|
|
+
|
|
|
+ const image = finalCanvas.toDataURL("image/png");
|
|
|
+
|
|
|
+ try {
|
|
|
+ uploadBase64(image);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("上传失败:", error);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // // 创建下载链接
|
|
|
+ // const link = document.createElement("a");
|
|
|
+ // link.href = image;
|
|
|
+ // link.download = "每日三问.png";
|
|
|
+ // link.click();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function convertImage(imgUrl) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ fetch(imgUrl)
|
|
|
+ .then((response) => {
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error(`HTTP 错误:${response.status}`);
|
|
|
+ }
|
|
|
+ return response.blob(); // 获取图片的二进制数据
|
|
|
+ })
|
|
|
+ .then((blob) => {
|
|
|
+ const reader = new FileReader();
|
|
|
+
|
|
|
+ reader.onload = () => {
|
|
|
+ // 转换成功后返回 Base64 数据
|
|
|
+ resolve(reader.result); // 通过 resolve 返回 Base64 数据
|
|
|
+ };
|
|
|
+
|
|
|
+ reader.onerror = (error) => {
|
|
|
+ console.error("文件读取失败:", error);
|
|
|
+ reject(error); // 出现错误时通过 reject 抛出错误
|
|
|
+ };
|
|
|
+
|
|
|
+ reader.readAsDataURL(blob); // 将 Blob 数据转换为 Base64
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error("图片转换失败:", error);
|
|
|
+ reject(error); // 捕获错误并通过 reject 抛出
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+export { deepClone, extractCoordinates, throttle, downloadImage, convertImage, detectRuntimeEnvironment };
|