index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. // pages/guicangDetails/index.js
  2. import drawQrcode from 'weapp-qrcode';
  3. import { getwxml, style } from './shareJson.js';
  4. const { request, cosBaseUrl, fileBaseURL } = require('../../utils/newServices');
  5. Page({
  6. data: {
  7. id: null,
  8. itemDetail: null,
  9. h5Url: 'https://test.4dmuseum.cn/swkzModel/index.html',
  10. boxTop: 0,
  11. windowHeight: 0,
  12. isFullScreen: false,
  13. startY: 0,
  14. moveY: 0,
  15. showSharePopup: false,
  16. shareUrl: 'https://test.4dmuseum.cn/swkzModel/index.html',
  17. qrCodeUrl: '',
  18. shareImagePath: '',
  19. width: 0,
  20. height: 0,
  21. container: null,
  22. showAppBanner: true, // 控制下载APP提示栏显示
  23. },
  24. onLoad: function(options) {
  25. if (options.id) {
  26. this.setData({
  27. id: options.id
  28. });
  29. this.loadItemDetail(options.id);
  30. }
  31. // 获取屏幕高度
  32. const systemInfo = wx.getSystemInfoSync();
  33. const windowHeight = systemInfo.windowHeight;
  34. this.setData({
  35. windowHeight: windowHeight,
  36. boxTop: windowHeight * 0.8 // 初始位置在屏幕60%的位置
  37. });
  38. },
  39. // 初始化 wxml-to-canvas
  40. initCanvas: function() {
  41. const that = this;
  42. that.widget = this.selectComponent('.widget');
  43. this.generateShareImage();
  44. },
  45. // 加载详情数据
  46. loadItemDetail: function(id) {
  47. if (!id) return;
  48. // 显示加载状态
  49. wx.showLoading({
  50. title: '加载中...'
  51. });
  52. // 调用详情接口
  53. request.getAntiqueDetail(
  54. {},
  55. 'GET',
  56. (res) => {
  57. wx.hideLoading();
  58. console.log('详情数据加载成功:', res);
  59. if (res.data && res.data.data) {
  60. const detail = res.data.data;
  61. const itemDetail = {
  62. id: detail.id,
  63. title: detail.name,
  64. date: detail.createTime ? detail.createTime.split(' ')[0] : '',
  65. source: detail.source || '归藏',
  66. description: detail.description || '',
  67. dimensions: detail.dimensions || detail.size,
  68. material: detail.material,
  69. imageUrl: cosBaseUrl + detail.coverImgUrl,
  70. file: cosBaseUrl + detail.fileList.find(file => file.name.includes('usdz')).url,
  71. h5Url: `${fileBaseURL}?m=${cosBaseUrl + detail.fileList.find(file => file.name.includes('usdz')).url}`,
  72. shareUrl: `${fileBaseURL}?m=${cosBaseUrl + detail.fileList.find(file => file.name.includes('usdz')).url}`,
  73. };
  74. console.log(itemDetail);
  75. this.setData({
  76. itemDetail: itemDetail
  77. });
  78. }
  79. },
  80. (err) => {
  81. wx.hideLoading();
  82. console.error('详情数据加载失败:', err);
  83. }
  84. );
  85. },
  86. // 打开H5页面
  87. openH5Page: function() {
  88. // 使用web-view内嵌打开H5页面
  89. wx.navigateTo({
  90. url: `/pages/webview/index?url=${encodeURIComponent(this.data.itemDetail.h5Url)}`
  91. });
  92. },
  93. // 触摸开始事件
  94. touchStart: function(e) {
  95. this.setData({
  96. startY: e.touches[0].clientY
  97. });
  98. },
  99. // 触摸移动事件
  100. touchMove: function(e) {
  101. const moveY = e.touches[0].clientY;
  102. const diff = moveY - this.data.startY;
  103. // 计算新的boxTop位置
  104. let newBoxTop = this.data.boxTop + diff;
  105. // 限制上下边界
  106. if (newBoxTop < this.data.windowHeight * 0.1) {
  107. newBoxTop = this.data.windowHeight * 0.1;
  108. } else if (newBoxTop > this.data.windowHeight * 0.7) {
  109. newBoxTop = this.data.windowHeight * 0.7;
  110. }
  111. this.setData({
  112. boxTop: newBoxTop,
  113. startY: moveY
  114. });
  115. },
  116. // 触摸结束事件
  117. touchEnd: function(e) {
  118. // 判断是否切换到全屏模式
  119. if (this.data.boxTop < this.data.windowHeight * 0.4) {
  120. this.setData({
  121. boxTop: this.data.windowHeight * 0.1,
  122. isFullScreen: true
  123. });
  124. } else {
  125. this.setData({
  126. boxTop: this.data.windowHeight * 0.8,
  127. isFullScreen: false
  128. });
  129. }
  130. },
  131. // 分享功能
  132. onShareAppMessage: function() {
  133. return {
  134. title: this.data.itemDetail ? this.data.itemDetail.title : '文物详情',
  135. path: '/pages/guicangDetails/index?id=' + this.data.id
  136. };
  137. },
  138. // 分享按钮点击事件
  139. shareItem: function() {
  140. this.setData({
  141. showSharePopup: true
  142. });
  143. this.showQRCode();
  144. setTimeout(() => {
  145. this.initCanvas();
  146. }, 1000)
  147. },
  148. // 关闭分享弹窗
  149. closeSharePopup: function() {
  150. this.setData({
  151. showSharePopup: false,
  152. shareImagePath: '',
  153. });
  154. },
  155. // 生成分享图片
  156. generateShareImage: function() {
  157. const that = this;
  158. if (!that.widget) {
  159. wx.showToast({
  160. title: 'wxml-to-canvas 组件未初始化',
  161. icon: 'none'
  162. });
  163. console.error('wxml-to-canvas 组件未初始化');
  164. return;
  165. }
  166. let wxml = getwxml(that.data.qrcodeUrl, this.data.itemDetail.title, this.data.itemDetail.imageUrl);
  167. console.log(wxml, 'wxml');
  168. // 设置要绘制的 WXML 节点
  169. that.widget.renderToCanvas({wxml, style}).then((res) => {
  170. // 将 canvas 转为图片
  171. that.container = res
  172. that.extraImage()
  173. }).catch((err) => {
  174. console.error('渲染 canvas 失败', err);
  175. wx.showToast({
  176. title: `${err}`,
  177. icon: 'none'
  178. });
  179. });
  180. },
  181. extraImage() {
  182. const p2 = this.widget.canvasToTempFilePath()
  183. p2.then(res => {
  184. this.setData({
  185. shareImagePath: res.tempFilePath,
  186. })
  187. })
  188. },
  189. // 生成二维码
  190. showQRCode() {
  191. let that = this;
  192. let url = 'https://3d-usdz.4dkankan.com/index.html?m=13719751007/captureModel/202503131501024131/data'
  193. drawQrcode({
  194. width: 72,
  195. height: 72,
  196. canvasId: 'myQrcode',
  197. text: url,
  198. correctLevel: 3
  199. })
  200. // 创建一个选择器查询对象
  201. const query = wx.createSelectorQuery();
  202. // 执行查询并获取 canvas 节点的实例
  203. query.select('#myQrcode').boundingClientRect()
  204. // 查询结束后执行回调函数
  205. query.exec((res) => {
  206. if (res[0]) {
  207. // res[0] 是 canvas 节点信息,确保节点存在
  208. wx.canvasToTempFilePath({
  209. canvasId: 'myQrcode',
  210. success(res) {
  211. const tempFilePath = res.tempFilePath;
  212. console.log(tempFilePath);
  213. that.setData({
  214. qrcodeUrl: tempFilePath
  215. })
  216. },
  217. fail(err) {
  218. console.error( err);
  219. }
  220. });
  221. } else {
  222. console.error('未能找到对应的 canvas 节点');
  223. }
  224. });
  225. },
  226. // 保存图片到本地
  227. saveToLocal: function() {
  228. const that = this;
  229. if (!that.data.shareImagePath) {
  230. wx.showToast({
  231. title: '图片生成中,请稍候',
  232. icon: 'none'
  233. });
  234. return;
  235. }
  236. // 获取保存图片到相册的权限
  237. wx.getSetting({
  238. success: function(res) {
  239. if (!res.authSetting['scope.writePhotosAlbum']) {
  240. wx.authorize({
  241. scope: 'scope.writePhotosAlbum',
  242. success: function() {
  243. that.saveImageToAlbum();
  244. },
  245. fail: function() {
  246. wx.showModal({
  247. title: '提示',
  248. content: '需要您授权保存图片到相册',
  249. showCancel: false,
  250. success: function() {
  251. wx.openSetting();
  252. }
  253. });
  254. }
  255. });
  256. } else {
  257. that.saveImageToAlbum();
  258. }
  259. }
  260. });
  261. },
  262. // 保存图片到相册
  263. saveImageToAlbum: function() {
  264. const that = this;
  265. wx.saveImageToPhotosAlbum({
  266. filePath: that.data.shareImagePath,
  267. success: function() {
  268. wx.showToast({
  269. title: '保存成功',
  270. icon: 'success'
  271. });
  272. },
  273. fail: function() {
  274. wx.showToast({
  275. title: '保存失败',
  276. icon: 'none'
  277. });
  278. }
  279. });
  280. },
  281. // 复制链接
  282. copyLink: function() {
  283. wx.setClipboardData({
  284. data: this.data.shareUrl,
  285. success: function() {
  286. wx.showToast({
  287. title: '链接已复制',
  288. icon: 'success'
  289. });
  290. }
  291. });
  292. },
  293. // 分享到微信好友
  294. shareToWechat: function() {
  295. if (!this.data.shareImagePath) {
  296. wx.showToast({
  297. title: '图片生成中,请稍候',
  298. icon: 'none'
  299. });
  300. return;
  301. }
  302. wx.showShareImageMenu({
  303. path: this.data.shareImagePath
  304. })
  305. },
  306. // 分享到朋友圈
  307. shareToTimeline: function() {
  308. if (!this.data.shareImagePath) {
  309. wx.showToast({
  310. title: '图片生成中,请稍候',
  311. icon: 'none'
  312. });
  313. return;
  314. }
  315. wx.showShareMenu({
  316. withShareTicket: true,
  317. menus: ['shareTimeline']
  318. });
  319. },
  320. // 分享给朋友(小程序自带分享功能)
  321. onShareAppMessage: function() {
  322. return {
  323. title: this.data.itemDetail ? this.data.itemDetail.title : '文物详情',
  324. path: '/pages/guicangDetails/index?id=' + this.data.id,
  325. imageUrl: this.data.shareImagePath || ''
  326. };
  327. },
  328. // 关闭下载APP提示栏
  329. closeAppBanner: function() {
  330. this.setData({
  331. showAppBanner: false
  332. });
  333. },
  334. // 下载APP - 跳转到苹果商店
  335. downloadApp: function() {
  336. // 苹果商店链接,需要替换为实际的App Store链接
  337. const appStoreUrl = 'https://apps.apple.com/cn/app/%E5%BE%AE%E4%BF%A1/id414478124';
  338. // 使用 wx.miniapp.openUrl 直接打开第三方App
  339. wx.miniapp.openUrl({
  340. url: appStoreUrl,
  341. success: () => {
  342. console.log('成功打开App Store');
  343. },
  344. fail: (err) => {
  345. console.log('打开App Store失败:', err);
  346. // 如果直接打开失败,则使用备用方案
  347. wx.showModal({
  348. title: '下载APP',
  349. content: '即将跳转到App Store下载归藏APP',
  350. confirmText: '前往下载',
  351. cancelText: '取消',
  352. success: (res) => {
  353. if (res.confirm) {
  354. wx.setClipboardData({
  355. data: appStoreUrl,
  356. success: () => {
  357. wx.showToast({
  358. title: '链接已复制,请在浏览器中打开',
  359. icon: 'none',
  360. duration: 3000
  361. });
  362. }
  363. });
  364. }
  365. }
  366. });
  367. }
  368. });
  369. }
  370. })