index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /**
  2. * 生成微信分享给聊天框内的图片卡片
  3. */
  4. import { Canvas } from "@tarojs/components";
  5. import style from './index.module.less'
  6. import { getCanvasTempPath } from "@/utils/index";
  7. import {
  8. Application,
  9. ImgLoader,
  10. Container,
  11. Image as DuduImage,
  12. RichText,
  13. } from "../../libs/duducanvas/index";
  14. import Taro, { useShareAppMessage, useShareTimeline } from "@tarojs/taro";
  15. import { getSharePromise } from "./shareUtils";
  16. import Stage from "@/libs/duducanvas/Stage";
  17. import { TAgentDetail } from "@/types/agent";
  18. import { DEFAULT_AVATAR_SHARE_BG } from "@/config";
  19. import { useIsLogin } from "@/xiaolanbenlib/hooks/data/useAuth";
  20. const getCanvasSize = () => {
  21. // 根据屏幕宽度计算 canvas 宽度
  22. const windowInfo = Taro.getWindowInfo();
  23. const screenWidth = windowInfo.windowWidth;
  24. // console.log(windowInfo, 'WindowInfo');
  25. // 设计宽度是 210*170 ,实际需要放大到 占满屏宽 375 * 300
  26. const designWidth = 375;
  27. const designHeight = 300;
  28. // 为了清晰度,宽高放大一倍
  29. const canvasWidth = screenWidth * 2;
  30. const canvasHeight = (screenWidth / designWidth) * designHeight * 2;
  31. // 放大系数
  32. const ratio = canvasWidth / 210;
  33. return {
  34. canvasWidth,
  35. canvasHeight,
  36. ratio,
  37. };
  38. };
  39. interface Props {
  40. agent: TAgentDetail;
  41. }
  42. export default (props: Props) => {
  43. const { canvasWidth, canvasHeight, ratio } = getCanvasSize();
  44. const isLogin = useIsLogin()
  45. let stage: Stage|null;
  46. // character = useCurrentCharacter
  47. const agent = props.agent
  48. const initCanvas = async () => {
  49. // console.log('share:', character)
  50. if(!agent){
  51. return
  52. }
  53. const app = new Application(
  54. "#myShareCanvas",
  55. { width: canvasWidth, height: canvasHeight },
  56. null
  57. );
  58. stage = await app.init();
  59. if(!stage){
  60. return;
  61. }
  62. let avatarImg = agent.avatarLogo ?? DEFAULT_AVATAR_SHARE_BG
  63. stage.backgroundColor = 'white'
  64. // 如果有头像,加载头像图片先
  65. const imgArr = [
  66. {
  67. id: "avatar",
  68. src: avatarImg,
  69. },
  70. {
  71. id: "blurBg",
  72. src: 'https://cdn.wehome.cn/cmn/png/221/META-H8UKXHWU-X0WXBKY1C0G0QA1DIH762-NSP5OMEM-IK.png',
  73. },
  74. ]
  75. const loader = new ImgLoader(stage.canvas, imgArr);
  76. await loader.load();
  77. // 头像
  78. const avatarTexture = loader.get("avatar");
  79. const avatar = new DuduImage({
  80. image: avatarTexture.image,
  81. dWidth: canvasWidth,
  82. dHeight: (canvasWidth / avatarTexture.width) * avatarTexture.height,
  83. });
  84. // 如果有头像,则需要上提,以显示出头像,如果是默认图则无需上提
  85. // if(agent.avatarLogo){
  86. // avatar.y = ;
  87. // }
  88. const avatarWrapper = new Container()
  89. avatarWrapper.width = canvasWidth
  90. avatarWrapper.height = 100
  91. avatarWrapper.overflowHidden = true
  92. avatarWrapper.addChild(avatar)
  93. stage.addChild(avatar)
  94. const blurBgTexture = loader.get("blurBg");
  95. // 毛玻璃背景
  96. const dHeight = 56 * ratio
  97. const blurBg = new DuduImage({
  98. image: blurBgTexture.image,
  99. dWidth: canvasWidth + (4 * ratio),
  100. dHeight: dHeight,
  101. });
  102. blurBg.y = canvasHeight - dHeight
  103. // 延出来一点边,需要往两边延申遮一下
  104. blurBg.x = (-2 * ratio)
  105. stage.addChild(blurBg)
  106. // 名称与公司名容器
  107. const offsetPadding = 12 * ratio
  108. const infoList = new Container();
  109. infoList.y = blurBg.y + offsetPadding;
  110. infoList.x = offsetPadding;
  111. infoList.direction = "column";
  112. infoList.alignItems = 'flex-start'
  113. infoList.gap = 8 * ratio;
  114. infoList.width = canvasWidth - offsetPadding
  115. infoList.height = dHeight - offsetPadding;
  116. // 用户名
  117. const name = new RichText({
  118. text: agent.name ?? '',
  119. fontSize: 14 * ratio,
  120. color: "rgba(17,17,17, 1)",
  121. fontFamily: "PingFangSC-Medium",
  122. fontWeight: 500,
  123. });
  124. name.wrapWidth = 186 * ratio;
  125. name.lineClamp = 1;
  126. infoList.addChild(name);
  127. // 单位名
  128. if(agent.entName){
  129. const companyName = new RichText();
  130. companyName.lineClamp = 1;
  131. companyName.fontFamily = "PingFangSC-Regular";
  132. companyName.text = agent?.entName ?? '';
  133. companyName.wrapWidth = name.wrapWidth;
  134. companyName.fontSize = 12 * ratio;
  135. companyName.color = "rgba(17,17,17, .65)";
  136. infoList.addChild(companyName);
  137. }
  138. stage.addChild(infoList)
  139. stage.update();
  140. };
  141. // 您好,这是xxx的智能体主页!
  142. const shareTitle = '快和我的智能体聊聊吧' // '想了解我?快和我的AI聊聊吧',
  143. useShareAppMessage(async () => {
  144. const agentId = agent?.agentId;
  145. const path = `/pages/profile/index?agentId=${agentId}`
  146. console.log(agent)
  147. if(!agentId){
  148. return {
  149. title: shareTitle,
  150. path,
  151. }
  152. }
  153. Taro.showLoading()
  154. await initCanvas();
  155. Taro.hideLoading()
  156. let tmpImage = ''
  157. if(stage){
  158. tmpImage = await getCanvasTempPath(stage.canvas, "myShareCanvas");
  159. }
  160. if(!isLogin){
  161. return {
  162. title: shareTitle,
  163. imageUrl: tmpImage,
  164. path
  165. }
  166. }
  167. const reponse = await getSharePromise(agentId, shareTitle, tmpImage)
  168. return reponse;
  169. });
  170. useShareTimeline(() => {
  171. const agentId = agent?.agentId;
  172. const o = {
  173. title: shareTitle,
  174. query: `agentId=${agentId}`,
  175. };
  176. return o;
  177. });
  178. return (
  179. <Canvas
  180. type="2d"
  181. id="myShareCanvas"
  182. width={String(canvasWidth)}
  183. height={String(canvasHeight)}
  184. style={`width: ${canvasWidth / 2}px; height: ${canvasHeight / 2}px;`}
  185. className={style.canvas}
  186. />
  187. );
  188. };