index.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /**
  2. * 生成微信小程序码卡片
  3. */
  4. import { Canvas } from "@tarojs/components";
  5. import style from "./index.module.less";
  6. import { getCanvasTempPath, savePicture } from "@/utils/index";
  7. import { checkPermission, showAuthModal } from "@/utils/auth";
  8. import { APP_NAME_TEXT, DEFAULT_AVATAR } from '@/config'
  9. import {
  10. Application,
  11. ImgLoader,
  12. Container,
  13. Image as DuduImage,
  14. RichText,
  15. Text,
  16. } from "@/libs/duducanvas/index";
  17. import Stage from "@/libs/duducanvas/Stage";
  18. import Taro from "@tarojs/taro";
  19. import { genQrcode, getCanvasSize } from './shareCard'
  20. import { forwardRef, useImperativeHandle } from "react";
  21. import { TAgentDetail } from "@/types/agent";
  22. export interface IShareCard {
  23. saveCardToAlbum: () => void;
  24. }
  25. interface Props {
  26. agent: TAgentDetail;
  27. }
  28. export default forwardRef(({ agent }: Props, ref) => {
  29. const { canvasWidth, canvasHeight, rValue } = getCanvasSize();
  30. let stage: Stage|null;
  31. // 保存至相册
  32. const saveCardToAlbum = async () => {
  33. Taro.showLoading();
  34. // 延迟获取 canvas
  35. await initCanvas();
  36. if(!stage){
  37. return
  38. }
  39. let tmpImage = await getCanvasTempPath(stage.canvas, "shareCard");
  40. const authed = await checkPermission("scope.writePhotosAlbum");
  41. if (!authed) {
  42. showAuthModal("需要您相册权限");
  43. return;
  44. }
  45. const res = await savePicture(tmpImage);
  46. if(res){
  47. Taro.showToast({
  48. title: '保存成功'
  49. })
  50. return
  51. }
  52. Taro.showToast({
  53. title: '保存失败'
  54. })
  55. };
  56. const initCanvas = async () => {
  57. // console.log("share:", character);
  58. const app = new Application(
  59. "#shareCard",
  60. { width: canvasWidth, height: canvasHeight },
  61. null
  62. );
  63. stage = await app.init();
  64. if(!stage){
  65. return
  66. }
  67. const avatarImg = agent.avatarLogo ?? DEFAULT_AVATAR
  68. const loader = new ImgLoader(stage.canvas, [
  69. {
  70. id: "avatar",
  71. src: avatarImg,
  72. },
  73. ]);
  74. await loader.load();
  75. const card = new Container();
  76. card.direction = "column";
  77. card.x = 0;
  78. card.y = 0;
  79. card.gap = rValue(24);
  80. card.width = rValue(319);
  81. card.height = rValue(447);
  82. card.backgroundColor = "white";
  83. // 头像&名称框
  84. const view = new Container();
  85. view.justifyContent = "flex-start";
  86. view.gap = rValue(12);
  87. view.width = rValue(271);
  88. view.height = rValue(48);
  89. card.addChild(view);
  90. // 头像
  91. const avatarTexture = loader.get("avatar");
  92. if (avatarTexture) {
  93. const dWidth = 48;
  94. const avatar = new DuduImage({
  95. image: avatarTexture.image,
  96. dWidth: rValue(dWidth),
  97. dHeight: rValue((avatarTexture.height * dWidth/avatarTexture.width)),
  98. });
  99. const avatarWrapper = new Container()
  100. avatarWrapper.width = rValue(dWidth)
  101. avatarWrapper.height = rValue(dWidth)
  102. avatarWrapper.overflowHidden = true
  103. avatarWrapper.borderRadius = rValue(4);
  104. avatarWrapper.addChild(avatar)
  105. view.addChild(avatarWrapper);
  106. }
  107. // 用户名
  108. const name = new RichText({
  109. text: agent?.name ?? "",
  110. fontSize: rValue(18),
  111. color: "black",
  112. fontWeight: 600,
  113. });
  114. name.wrapWidth = rValue(184);
  115. name.lineClamp = 1;
  116. name.height = rValue(26);
  117. view.addChild(name);
  118. const qrcodeView = new Container();
  119. qrcodeView.width = rValue(271);
  120. qrcodeView.height = rValue(251);
  121. // qrcodeView.backgroundColor = "rgba(0,0,0, .2)";
  122. card.addChild(qrcodeView);
  123. const tips = new Text({
  124. text: `扫一扫上面的二维码图案,和我${APP_NAME_TEXT}聊聊吧`,
  125. fontSize: rValue(12),
  126. color: "rgba(0,0,0, .45)",
  127. fontWeight: 400,
  128. });
  129. card.addChild(tips);
  130. stage.addChild(card);
  131. if(agent.agentId){
  132. await genQrcode(agent.agentId, rValue(255), rValue(255), stage, qrcodeView);
  133. }
  134. stage.update();
  135. Taro.hideLoading();
  136. return stage;
  137. };
  138. useImperativeHandle(ref, () => {
  139. return {
  140. saveCardToAlbum,
  141. };
  142. });
  143. return (
  144. <Canvas
  145. type="2d"
  146. id="shareCard"
  147. width={String(canvasWidth)}
  148. height={String(canvasHeight)}
  149. style={`width: ${canvasWidth / 5}px; height: ${canvasHeight / 5}px;`}
  150. className={style.canvas}
  151. />
  152. );
  153. });