details.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. // subpackagestow/details/details.js
  2. import { models, db, _, client } from '../../utils/cloudbase.js'
  3. Page({
  4. /**
  5. * 页面的初始数据
  6. */
  7. data: {
  8. fileType: 'video',
  9. viewType: 'grid',
  10. courseList: [],
  11. shouchang: '',
  12. shouchangs: '',
  13. show_1: '',
  14. xiazi: '',
  15. xia: '',
  16. itemlist: {},
  17. isCollected: false,
  18. isPlaying: false,
  19. isAudioPlaying: false,
  20. enterTime: null, // 进入时间
  21. },
  22. onLoad(options) {
  23. // 进入时间
  24. const now = new Date();
  25. this.setData({
  26. enterTime: now
  27. });
  28. // 获取传递过来的数据
  29. const itemStr = decodeURIComponent(options.item);
  30. const item = JSON.parse(itemStr);
  31. // 格式化时间
  32. item.createdAtText = this.formatTime(item.createdAt);
  33. // 设置到页面数据中
  34. this.setData({
  35. itemlist: item
  36. }, () => {
  37. // 相关推荐
  38. this.getcourseList()
  39. // 转换云文件ID为临时链接
  40. if (item.url && item.url.length > 0) {
  41. wx.cloud.getTempFileURL({
  42. fileList: [item.url[0]],
  43. success: res => {
  44. if (res.fileList && res.fileList.length > 0) {
  45. this.setData({
  46. 'itemlist.playUrl': res.fileList[0].tempFileURL
  47. });
  48. }
  49. },
  50. fail: err => {
  51. console.error('获取临时链接失败', err);
  52. }
  53. });
  54. }
  55. // 收藏
  56. this.getcollect()
  57. // 加访问量
  58. this.getvisits()
  59. });
  60. // 获取图片
  61. const fileIDs = [
  62. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/shouchang.png',
  63. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/show_1.png',
  64. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/xiazi.png',
  65. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/xia_1.png',
  66. 'cloud://honghgaier-5guiffgcf17a2eea.686f-honghgaier-5guiffgcf17a2eea-1373037829/images/icon/shoucang_s.png'
  67. ];
  68. // 并发下载多个 fileID
  69. Promise.all(
  70. fileIDs.map(fileID => wx.cloud.downloadFile({ fileID }))
  71. ).then(results => {
  72. // 每个 result 对应一个下载结果
  73. const tempFilePaths = results.map(r => r.tempFilePath);
  74. console.log('全部下载成功:', tempFilePaths);
  75. this.setData({
  76. shouchang: tempFilePaths[0],
  77. show_1: tempFilePaths[1],
  78. xiazi: tempFilePaths[2],
  79. xia: tempFilePaths[3],
  80. shouchangs: tempFilePaths[4],
  81. });
  82. }).catch(err => {
  83. console.error('有文件下载失败:', err);
  84. });
  85. },
  86. formatTime(ts) {
  87. const date = new Date(ts);
  88. const y = date.getFullYear();
  89. const m = String(date.getMonth() + 1).padStart(2, '0');
  90. const d = String(date.getDate()).padStart(2, '0');
  91. const hh = String(date.getHours()).padStart(2, '0');
  92. const mm = String(date.getMinutes()).padStart(2, '0');
  93. const ss = String(date.getSeconds()).padStart(2, '0');
  94. return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
  95. },
  96. // 相关课件推荐
  97. async getcourseList() {
  98. const result = await client.callFunction({
  99. name: "database", // 云函数部署名
  100. data: {
  101. page: "recommende",
  102. action: "findFileRangee",
  103. data: {
  104. _id: this.data.itemlist._id,
  105. range: this.data.itemlist.range,
  106. tag_id: this.data.itemlist.tag_id,
  107. pageSize: 20,
  108. pageNum: 1,
  109. },
  110. },
  111. });
  112. console.log(result, 'data++++++---------------');
  113. this.setData({
  114. courseList: result.result.records
  115. })
  116. },
  117. // 下载
  118. goToGoodsLists(event) {
  119. // 获取绑定的数据
  120. const item = event.currentTarget.dataset.item;
  121. // 将数据转换为 JSON 字符串并传递
  122. const itemStr = encodeURIComponent(JSON.stringify(item));
  123. wx.navigateTo({
  124. url: `/subpackagestow/down/down?item=${itemStr}`
  125. });
  126. },
  127. // 相关课件点击详情
  128. goToGoodsList(event) {
  129. // 获取绑定的数据
  130. const item = event.currentTarget.dataset.item;
  131. // 将数据转换为 JSON 字符串并传递
  132. const itemStr = encodeURIComponent(JSON.stringify(item));
  133. wx.navigateTo({
  134. url: `/subpackagestow/details/details?item=${itemStr}`
  135. });
  136. },
  137. // 是否收藏
  138. async getcollect() {
  139. const { data } = await models.wx_collect.get({
  140. filter: {
  141. where: {
  142. file_manager_id: this.data.itemlist._id
  143. }
  144. },
  145. // envType: pre 体验环境, prod 正式环境
  146. envType: "prod",
  147. });
  148. // 返回查询到的数据
  149. console.log(data, '123321');
  150. // 判断是否有值
  151. if (data && Object.keys(data).length > 0) {
  152. this.setData({
  153. isCollected: true // 设置标志为 true
  154. });
  155. } else {
  156. this.setData({
  157. isCollected: false // 设置标志为 false
  158. });
  159. }
  160. },
  161. // 收藏
  162. async goTocollect() {
  163. if (this.data.isCollected) {
  164. const userInfo = wx.getStorageSync('userInfo');
  165. const { data } = await models.wx_collect.delete({
  166. filter: {
  167. where: {
  168. $and: [
  169. {
  170. file_manager_id: {
  171. $eq: this.data.itemlist._id, // 推荐传入_id数据标识进行操作
  172. },
  173. wx_user_id: {
  174. $eq: userInfo._id, // 推荐传入_id数据标识进行操作
  175. },
  176. },
  177. ]
  178. }
  179. },
  180. // envType: pre 体验环境, prod 正式环境
  181. envType: "prod",
  182. });
  183. // 返回删除成功的条数
  184. console.log(data, '删除');
  185. wx.showToast({ title: '取消收藏成功', icon: 'success' });
  186. this.setData({
  187. isCollected: false
  188. })
  189. } else {
  190. const userInfo = wx.getStorageSync('userInfo');
  191. const { data } = await models.wx_collect.create({
  192. data: {
  193. wx_user_id: userInfo._id, // 收藏人_id
  194. file_manager_id: this.data.itemlist._id, // 收藏文件id
  195. remark: "备注备注备注备注备注备注", // 备注
  196. },
  197. // envType: pre 体验环境, prod 正式环境
  198. envType: "prod",
  199. });
  200. // 返回创建的数据 id
  201. console.log(data);
  202. wx.showToast({ title: '收藏成功', icon: 'success' });
  203. this.setData({
  204. isCollected: true // 设置标志为 true
  205. });
  206. }
  207. },
  208. // 预览
  209. previewPDF() {
  210. const cloudUrl = this.data.itemlist.url[0];
  211. if (!cloudUrl) return;
  212. wx.cloud.getTempFileURL({
  213. fileList: [cloudUrl],
  214. success: res => {
  215. if (res.fileList && res.fileList.length > 0) {
  216. const tempUrl = res.fileList[0].tempFileURL;
  217. const extension = tempUrl.substring(tempUrl.lastIndexOf('.') + 1).toLowerCase();
  218. if (['pdf', 'ppt', 'pptx', 'xls', 'xlsx'].includes(extension)) {
  219. // 先下载到本地
  220. wx.downloadFile({
  221. url: tempUrl,
  222. success: dlRes => {
  223. wx.openDocument({
  224. filePath: dlRes.tempFilePath,
  225. fileType: extension,
  226. success: () => console.log('文档打开成功'),
  227. fail: err => console.error('文档打开失败', err)
  228. });
  229. },
  230. fail: err => {
  231. wx.showToast({ title: '下载文件失败', icon: 'none' });
  232. console.error('下载文件失败', err);
  233. }
  234. });
  235. } else if (['mp3', 'aac', 'wav'].includes(extension)) {
  236. this._playAudio(tempUrl);
  237. } else if (['mp4', 'mov'].includes(extension)) {
  238. this.setData({ 'itemlist.playUrl': tempUrl });
  239. this.toggleVideo();
  240. } else {
  241. wx.showToast({ title: '暂不支持该文件类型预览', icon: 'none' });
  242. }
  243. }
  244. },
  245. fail: err => {
  246. wx.showToast({ title: '获取播放链接失败', icon: 'none' });
  247. console.error('获取临时链接失败', err);
  248. }
  249. });
  250. },
  251. // 视频播放还是暂停
  252. toggleVideo() {
  253. const videoContext = wx.createVideoContext('myVideo', this);
  254. if (this.data.isPlaying) {
  255. videoContext.pause();
  256. this.setData({ isPlaying: false });
  257. } else {
  258. videoContext.play();
  259. this.setData({ isPlaying: true });
  260. }
  261. },
  262. // 音频的播放暂停
  263. toggleAudio() {
  264. // 如果已经有临时播放链接,直接用它
  265. if (this.data.itemlist.playUrl) {
  266. this._playAudio(this.data.itemlist.playUrl);
  267. } else {
  268. // 否则判断 url 是否是 cloud:// 开头,需要转临时链接
  269. const cloudUrl = this.data.itemlist.url[0];
  270. if (cloudUrl && cloudUrl.startsWith('cloud://')) {
  271. wx.cloud.getTempFileURL({
  272. fileList: [cloudUrl],
  273. success: res => {
  274. if (res.fileList && res.fileList.length > 0) {
  275. const tempUrl = res.fileList[0].tempFileURL;
  276. this.setData({ 'itemlist.playUrl': tempUrl }, () => {
  277. this._playAudio(tempUrl);
  278. });
  279. }
  280. },
  281. fail: err => {
  282. wx.showToast({ title: '获取播放链接失败', icon: 'none' });
  283. console.error('获取临时链接失败', err);
  284. }
  285. });
  286. } else {
  287. // 不是 cloud:// 开头,直接播放原链接
  288. this._playAudio(cloudUrl);
  289. }
  290. }
  291. },
  292. _playAudio(url) {
  293. if (!this.audioContext) {
  294. this.audioContext = wx.createInnerAudioContext();
  295. this.audioContext.onPlay(() => this.setData({ isAudioPlaying: true }));
  296. this.audioContext.onPause(() => this.setData({ isAudioPlaying: false }));
  297. this.audioContext.onStop(() => this.setData({ isAudioPlaying: false }));
  298. this.audioContext.onEnded(() => this.setData({ isAudioPlaying: false }));
  299. this.audioContext.onError((res) => {
  300. wx.showToast({ title: '音频播放错误', icon: 'none' });
  301. this.setData({ isAudioPlaying: false });
  302. console.error('音频播放错误', res);
  303. });
  304. }
  305. if (this.data.isAudioPlaying) {
  306. this.audioContext.pause();
  307. } else {
  308. this.audioContext.src = url;
  309. this.audioContext.play();
  310. }
  311. },
  312. onUnload() {
  313. if (this.audioContext) {
  314. this.audioContext.stop();
  315. this.audioContext.destroy();
  316. this.audioContext = null;
  317. }
  318. },
  319. onHide() {
  320. if (this.audioContext) {
  321. this.audioContext.pause();
  322. }
  323. },
  324. // 新增浏览量
  325. async getvisits() {
  326. const userInfo = wx.getStorageSync('userInfo');
  327. const userId = userInfo && userInfo._id ? userInfo._id : '';
  328. const schoolId = userInfo && userInfo.school_id ? userInfo.school_id : '';
  329. const fileId = this.data.itemlist._id;
  330. // 先查是否存在
  331. const { data } = await models.microcode.list({
  332. filter: {
  333. where: {
  334. school_id: schoolId,
  335. // user_id: userId,
  336. file_id: fileId
  337. }
  338. },
  339. envType: "prod",
  340. });
  341. console.log(data,'datadatadata');
  342. const datalist = data.records || []
  343. if (datalist.length > 0) {
  344. // 已存在 → 更新 visits + 1
  345. const existItem = datalist[0];
  346. const recordId = String(existItem._id);
  347. console.log(existItem, 'existItem');
  348. await models.microcode.update({
  349. data: {
  350. visits: existItem.visits + 1 , // 访问量
  351. },
  352. filter: {
  353. where: {
  354. $and: [
  355. {
  356. _id: {
  357. $eq: recordId, // 推荐传入_id数据标识进行操作
  358. },
  359. },
  360. ]
  361. }
  362. },
  363. // envType: pre 体验环境, prod 正式环境
  364. envType: "prod",
  365. });
  366. console.log("更新成功:visits + 1");
  367. } else {
  368. // 不存在 → 创建新记录
  369. const { data: newData } = await models.microcode.create({
  370. data: {
  371. visits: 1,
  372. download: 1,
  373. school_id: schoolId,
  374. // user_id: userId,
  375. file_id: fileId,
  376. },
  377. envType: "prod",
  378. });
  379. console.log("创建成功", newData);
  380. }
  381. },
  382. async onUnload() {
  383. await this.saveUserBehavior();
  384. if (this.audioContext) {
  385. this.audioContext.stop();
  386. this.audioContext.destroy();
  387. this.audioContext = null;
  388. }
  389. },
  390. async onHide() {
  391. await this.saveUserBehavior();
  392. if (this.audioContext) {
  393. this.audioContext.pause();
  394. }
  395. },
  396. async saveUserBehavior() {
  397. try {
  398. const userInfo = wx.getStorageSync('userInfo');
  399. const userId = userInfo && userInfo._id ? userInfo._id : '';
  400. const startTime = this.data.enterTime;
  401. if (!startTime) return; // 如果没进入过,不存
  402. const endTime = new Date();
  403. // 转换为时间戳(毫秒 → 秒)
  404. const startTimestamp = new Date(startTime).getTime();
  405. const endTimestamp = new Date().getTime();
  406. const duration = endTimestamp - startTimestamp;
  407. await models.monitor_behavior.create({
  408. data: {
  409. start_time: startTimestamp, // 数字
  410. end_time: endTimestamp, // 数字
  411. duration: duration, // 数字
  412. type: 0, // 固定 0
  413. user_id: userId || 'guest'
  414. },
  415. envType: "prod",
  416. });
  417. console.log("监控数据保存成功:", {
  418. start_time: startTimestamp,
  419. end_time: endTimestamp,
  420. duration,
  421. type: 0,
  422. user_id: userId || 'guest'
  423. });
  424. } catch (err) {
  425. console.error("监控数据保存失败", err);
  426. }
  427. }
  428. })