浏览代码

海报:完善商品海报分享

puhui999 1 年之前
父节点
当前提交
dabefbe21c

+ 1 - 1
.env

@@ -5,7 +5,7 @@ SHOPRO_VERSION = v1.8.3
 SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn
 SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn
 
 
 # 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
 # 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
-SHOPRO_DEV_BASE_URL = https://192.168.1.105:48080
+SHOPRO_DEV_BASE_URL = http://192.168.2.21:48080
 ### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
 ### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
 
 
 # 后端接口前缀(一般不建议调整)
 # 后端接口前缀(一般不建议调整)

+ 0 - 1
pages/goods/index.vue

@@ -196,7 +196,6 @@
 			title: state.goodsInfo.name,
 			title: state.goodsInfo.name,
 			image: sheep.$url.cdn(state.goodsInfo.picUrl),
 			image: sheep.$url.cdn(state.goodsInfo.picUrl),
 			desc: state.goodsInfo.introduction,
 			desc: state.goodsInfo.introduction,
-      path: 'pages/goods/index',
 			params: {
 			params: {
 				page: '2',
 				page: '2',
 				query: state.goodsInfo.id,
 				query: state.goodsInfo.id,

+ 1 - 0
pages/index/index.vue

@@ -53,6 +53,7 @@
 		// 小程序识别二维码
 		// 小程序识别二维码
 		if (options.scene) {
 		if (options.scene) {
 			const sceneParams = decodeURIComponent(options.scene).split('=');
 			const sceneParams = decodeURIComponent(options.scene).split('=');
+      console.log("sceneParams=>",sceneParams);
 			options[sceneParams[0]] = sceneParams[1];
 			options[sceneParams[0]] = sceneParams[1];
 		}
 		}
 		// #endif
 		// #endif

+ 52 - 27
sheep/components/s-share-modal/canvas-poster/index.vue

@@ -2,15 +2,39 @@
 <template>
 <template>
   <su-popup :show="show" round="10" @close="onClosePoster" type="center" class="popup-box">
   <su-popup :show="show" round="10" @close="onClosePoster" type="center" class="popup-box">
     <view class="ss-flex-col ss-col-center ss-row-center">
     <view class="ss-flex-col ss-col-center ss-row-center">
-      <template v-if="poster.views.length > 0">
-        <l-painter :board="poster" />
-      </template>
+      <view
+        v-if="poster.views.length === 0"
+        class="poster-title ss-flex ss-row-center"
+        :style="{
+          height: poster.height + 'px',
+          width: poster.width + 'px',
+        }"
+      >
+        海报加载中...
+      </view>
+      <!-- v-if 保障等待所有的海报信息都加载完后才开始渲染 -->
+          <template v-if="poster.views.length > 0">
+            <l-painter :board="poster" ref="painterRef"/>
+          </template>
+    </view>
+    <view
+      class="poster-btn-box ss-m-t-20 ss-flex ss-row-between ss-col-center"
+      v-if="poster.views.length > 0"
+    >
+      <button class="cancel-btn ss-reset-button" @tap="onClosePoster">取消</button>
+      <button class="save-btn ss-reset-button ui-BG-Main" @tap="onSavePoster">
+        {{
+          ['wechatOfficialAccount', 'H5'].includes(sheep.$platform.name)
+            ? '长按图片保存'
+            : '保存图片'
+        }}
+      </button>
     </view>
     </view>
   </su-popup>
   </su-popup>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import { getCurrentInstance, reactive } from 'vue';
+  import { reactive, ref } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import { getPosterData } from '@/sheep/components/s-share-modal/canvas-poster/poster';
   import { getPosterData } from '@/sheep/components/s-share-modal/canvas-poster/poster';
 
 
@@ -26,24 +50,22 @@
     },
     },
   });
   });
 
 
-
   const poster = reactive({
   const poster = reactive({
     css: {
     css: {
       // 根节点若无尺寸,自动获取父级节点
       // 根节点若无尺寸,自动获取父级节点
       width: sheep.$platform.device.windowWidth * 0.9,
       width: sheep.$platform.device.windowWidth * 0.9,
-      height: 600,
+      height: 600
     },
     },
     views: [],
     views: [],
   });
   });
 
 
-
   const emits = defineEmits(['success', 'close']);
   const emits = defineEmits(['success', 'close']);
-  const vm = getCurrentInstance();
 
 
   const onClosePoster = () => {
   const onClosePoster = () => {
     emits('close');
     emits('close');
   };
   };
 
 
+  const painterRef = ref()
   // 保存海报图片
   // 保存海报图片
   const onSavePoster = () => {
   const onSavePoster = () => {
     if (['WechatOfficialAccount', 'H5'].includes(sheep.$platform.name)) {
     if (['WechatOfficialAccount', 'H5'].includes(sheep.$platform.name)) {
@@ -51,26 +73,35 @@
       return;
       return;
     }
     }
 
 
-    uni.saveImageToPhotosAlbum({
-      filePath: poster.src,
+    painterRef.value.canvasToTempFilePathSync({
+      fileType: "jpg",
+      // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
+      pathType: 'url',
+      quality: 1,
       success: (res) => {
       success: (res) => {
-        onClosePoster();
-        sheep.$helper.toast('保存成功');
-      },
-      fail: (err) => {
-        sheep.$helper.toast('保存失败');
-        console.log('图片保存失败:', err);
+        console.log(res.tempFilePath);
+        // 非H5 保存到相册
+        uni.saveImageToPhotosAlbum({
+          filePath: res.tempFilePath,
+          success: (res) => {
+            onClosePoster();
+            sheep.$helper.toast('保存成功');
+          },
+          fail: (err) => {
+            sheep.$helper.toast('保存失败');
+            console.log('图片保存失败:', err);
+          },
+        });
       },
       },
     });
     });
   };
   };
 
 
-  // 使用 canvas 生成海报
-  async function getPoster(params) {
-    let drawer = await getPosterData({
-      width: sheep.$platform.device.windowWidth * 0.9,
+  // 获得海报数据
+  async function getPoster() {
+    poster.views = await getPosterData({
+      width: poster.css.width,
       shareInfo: props.shareInfo,
       shareInfo: props.shareInfo,
     });
     });
-    poster.views = drawer;
   }
   }
 
 
   defineExpose({
   defineExpose({
@@ -120,10 +151,4 @@
     border-radius: 20rpx;
     border-radius: 20rpx;
   }
   }
 
 
-  .hideCanvas {
-    position: fixed;
-    top: -99999rpx;
-    left: -99999rpx;
-    z-index: -99999;
-  }
 </style>
 </style>

+ 0 - 1
sheep/components/s-share-modal/canvas-poster/poster/goods.js

@@ -12,7 +12,6 @@ const goods = async (poster) => {
       src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.goods_bg)),
       src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.goods_bg)),
       css: {
       css: {
         width,
         width,
-        background: 'white',
         position: 'fixed',
         position: 'fixed',
         'object-fit': 'contain',
         'object-fit': 'contain',
         top: '0',
         top: '0',

+ 0 - 87
sheep/components/s-share-modal/canvas-poster/useCanvas.js

@@ -1,87 +0,0 @@
-/**
- * Shopro + qs-canvas 绘制海报
- * @version 1.0.0
- * @author lidongtony
- * @param {Object} options - 海报参数
- * @param {Object} vm - 自定义组件实例
- */
-import QSCanvas from 'qs-canvas';
-import { getPosterData } from './poster';
-
-export default async function useCanvas(options, vm) {
-  const width = options.width;
-  const qsc = new QSCanvas(
-    {
-      canvasId: options.canvasId,
-      width: options.width,
-      height: options.height,
-      setCanvasWH: (canvas) => {
-        options.height = canvas.height;
-      },
-    },
-    vm,
-  );
-
-  let drawer = await getPosterData(options);
-  console.log(drawer);
-  // 绘制背景图
-  const background = await qsc.drawImg({
-    type: 'image',
-    val: drawer.background,
-    x: 0,
-    y: 0,
-    width,
-    mode: 'widthFix',
-    zIndex: 0,
-  });
-  await qsc.updateCanvasWH({
-    width: background.width,
-    height: background.bottom,
-  });
-
-  let list = drawer.list;
-
-  for (let i = 0; i < list.length; i++) {
-    let item = list[i];
-    // 绘制文字
-    if (item.type === 'text') {
-      await qsc.drawText(item);
-    }
-    // 绘制图片
-    if (item.type === 'image') {
-      if (item.d) {
-        qsc.setCircle({
-          x: item.x,
-          y: item.y,
-          d: item.d,
-          clip: true,
-        });
-      }
-
-      if (item.r) {
-        qsc.setRect({
-          x: item.x,
-          y: item.y,
-          height: item.height,
-          width: item.width,
-          r: item.r,
-          clip: true,
-        });
-      }
-      await qsc.drawImg(item);
-      qsc.restore();
-    }
-
-    // 绘制二维码
-    if (item.type === 'qrcode') {
-      await qsc.drawQrCode(item);
-    }
-  }
-
-  await qsc.draw();
-  // 延迟执行, 防止不稳定
-  setTimeout(async () => {
-    options.src = await qsc.toImage();
-  }, 100);
-  return options;
-}

+ 8 - 7
sheep/platform/share.js

@@ -19,7 +19,6 @@ const getShareInfo = (
     title: '', // 自定义分享标题
     title: '', // 自定义分享标题
     desc: '', // 自定义描述
     desc: '', // 自定义描述
     image: '', // 自定义分享图片
     image: '', // 自定义分享图片
-    path: '', // 页面基础路径,不要以 / 开头
     params: {}, // 自定义分享参数
     params: {}, // 自定义分享参数
   },
   },
   poster = {
   poster = {
@@ -46,6 +45,8 @@ const getShareInfo = (
 
 
   // 配置分享链接地址
   // 配置分享链接地址
   shareInfo.link = buildSpmLink(query, shareConfig.linkAddress);
   shareInfo.link = buildSpmLink(query, shareConfig.linkAddress);
+  // 配置页面地址带参数
+  shareInfo.path = buildSpmPath(query);
 
 
   // 配置转发参数
   // 配置转发参数
   if (shareConfig.methods.includes('forward')) {
   if (shareConfig.methods.includes('forward')) {
@@ -59,8 +60,7 @@ const getShareInfo = (
     shareInfo.desc = scene.desc || shareConfig.forwardInfo.subtitle;
     shareInfo.desc = scene.desc || shareConfig.forwardInfo.subtitle;
     shareInfo.path = buildSpmPath(scene.path, query);
     shareInfo.path = buildSpmPath(scene.path, query);
   }
   }
-  shareInfo.path = scene.path;
-  console.log('shareInfo', shareInfo);
+
   return shareInfo;
   return shareInfo;
 };
 };
 
 
@@ -70,7 +70,6 @@ const buildSpmQuery = (params) => {
   let shareId = '0'; // 设置分享者用户ID
   let shareId = '0'; // 设置分享者用户ID
   if (typeof params.shareId === 'undefined') {
   if (typeof params.shareId === 'undefined') {
     if (user.isLogin) {
     if (user.isLogin) {
-      // todo @芋艿 id为空
       shareId = user.userInfo.id;
       shareId = user.userInfo.id;
     }
     }
   }
   }
@@ -91,9 +90,11 @@ const buildSpmQuery = (params) => {
   return `spm=${shareId}.${page}.${query}.${platform}.${from}`;
   return `spm=${shareId}.${page}.${query}.${platform}.${from}`;
 };
 };
 
 
-// 构造页面分享参数
-const buildSpmPath = (path, query) => {
-  return `/${path}?${query}`;
+// 构造页面分享参数: 所有的分享都先到首页进行 spm 参数解析
+const buildSpmPath = (query) => {
+  // 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,
+  // 不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置
+  return `pages/index/index`;
 };
 };
 
 
 // 构造分享链接
 // 构造分享链接

+ 1 - 2
sheep/store/user.js

@@ -1,7 +1,6 @@
 import {
 import {
 	defineStore
 	defineStore
 } from 'pinia';
 } from 'pinia';
-// import userApi from '@/sheep/api/user';
 import $share from '@/sheep/platform/share';
 import $share from '@/sheep/platform/share';
 import {
 import {
 	isEmpty,
 	isEmpty,
@@ -184,4 +183,4 @@ const user = defineStore({
 	},
 	},
 });
 });
 
 
-export default user;
+export default user;