与牧同行-兽医端小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

567 lines
14 KiB

  1. import http from '../../../utils/api'
  2. const baseUrl = require('../../../utils/baseUrl')
  3. Page({
  4. /**
  5. * 页面的初始数据
  6. */
  7. data: {
  8. diagnosisData: {},
  9. replies: [],
  10. baseUrl: baseUrl,
  11. refreshing: false,
  12. // 新增回复相关数据
  13. showReplyInput: true,
  14. replyContent: '',
  15. replyImages: [],
  16. replyImagesTemp: [], // 本地临时路径,用于预览
  17. uploadingImage: false,
  18. submittingReply: false,
  19. isUploading: false // 防止重复上传
  20. },
  21. /**
  22. * 生命周期函数--监听页面加载
  23. */
  24. onLoad(options) {
  25. if (options.data) {
  26. // 根据id加载兽医回复数据
  27. const data = JSON.parse(decodeURIComponent(options.data));
  28. // 处理用户图片 - 确保是数组格式
  29. if (data.images) {
  30. if (typeof data.images === 'string') {
  31. data.images = data.images.split(',')
  32. }
  33. console.log('用户图片:', data.images);
  34. } else {
  35. data.images = [];
  36. }
  37. this.setData({
  38. diagnosisData: data,
  39. })
  40. this.loadDiagnosisData(data.formId);
  41. }
  42. },
  43. /**
  44. * 加载问诊数据兽医回复
  45. * @param {string} id - 问诊ID
  46. */
  47. loadDiagnosisData(id) {
  48. console.log('加载问诊数据:', id);
  49. wx.showLoading({
  50. title: '加载中...',
  51. mask: true
  52. });
  53. http.wzdxq({
  54. data: {
  55. consultationId: id
  56. },
  57. success: res => {
  58. wx.hideLoading();
  59. // 处理兽医回复的图片
  60. let replies = [];
  61. if (res && res.rows) {
  62. replies = res.rows || [];
  63. // 遍历每个回复,处理图片字段
  64. for (let i = 0; i < replies.length; i++) {
  65. const item = replies[i];
  66. // 处理图片 - 确保是数组格式
  67. if (item.images) {
  68. if (typeof item.images === 'string') {
  69. // 如果是空字符串,设为空数组
  70. if (item.images.trim() === '') {
  71. item.images = [];
  72. } else {
  73. // 按逗号分割字符串
  74. item.images = item.images.split(',');
  75. }
  76. } else if (Array.isArray(item.images)) {
  77. // 已经是数组,但需要过滤空值
  78. item.images = item.images.filter(img => img && img.trim() !== '');
  79. } else {
  80. item.images = [];
  81. }
  82. } else {
  83. item.images = [];
  84. }
  85. console.log(`兽医回复[${i}]图片:`, item.images);
  86. }
  87. }
  88. console.log('兽医回复数据:', replies);
  89. this.setData({
  90. replies: replies
  91. })
  92. },
  93. fail: err => {
  94. wx.hideLoading();
  95. console.error('加载回复失败:', err);
  96. wx.showToast({
  97. title: '加载失败',
  98. icon: 'none'
  99. });
  100. }
  101. })
  102. },
  103. /**
  104. * 回复内容输入
  105. */
  106. onReplyContentInput(e) {
  107. this.setData({
  108. replyContent: e.detail.value
  109. });
  110. },
  111. /**
  112. * 清空所有图片
  113. */
  114. clearAllImages() {
  115. if (this.data.replyImages.length === 0) return;
  116. wx.showModal({
  117. title: '提示',
  118. content: '确定要清空所有已选图片吗?',
  119. success: (res) => {
  120. if (res.confirm) {
  121. this.setData({
  122. replyImages: [],
  123. replyImagesTemp: []
  124. });
  125. }
  126. }
  127. });
  128. },
  129. /**
  130. * 选择回复图片 - 优化后的版本
  131. */
  132. chooseReplyImage() {
  133. if (this.data.isUploading) {
  134. wx.showToast({
  135. title: '正在上传中,请稍候',
  136. icon: 'none'
  137. });
  138. return;
  139. }
  140. if (this.data.replyImages.length >= 9) {
  141. wx.showToast({
  142. title: '最多上传9张图片',
  143. icon: 'none'
  144. });
  145. return;
  146. }
  147. wx.chooseMedia({
  148. count: 9 - this.data.replyImages.length,
  149. mediaType: ['image'],
  150. sourceType: ['album', 'camera'],
  151. sizeType: ['compressed'],
  152. success: (res) => {
  153. if (res.tempFiles && res.tempFiles.length > 0) {
  154. this.setData({
  155. isUploading: true
  156. });
  157. // 显示加载提示
  158. wx.showLoading({
  159. title: '上传图片中...',
  160. mask: true
  161. });
  162. // 获取临时文件路径列表
  163. const tempPaths = res.tempFiles.map(file => file.tempFilePath);
  164. // 保存临时路径用于预览
  165. const newTempPaths = [...this.data.replyImagesTemp, ...tempPaths];
  166. this.setData({
  167. replyImagesTemp: newTempPaths
  168. });
  169. // 逐张上传图片
  170. this.uploadImages(tempPaths);
  171. }
  172. }
  173. });
  174. },
  175. /**
  176. * 上传多张图片 - 优化后的版本
  177. */
  178. uploadImages(filePaths) {
  179. const uploadTasks = filePaths.map(path => {
  180. return new Promise((resolve, reject) => {
  181. wx.uploadFile({
  182. url: baseUrl + '/common/upload',
  183. filePath: path,
  184. name: 'file',
  185. header: {
  186. 'Authorization': 'Bearer ' + wx.getStorageSync('token')
  187. },
  188. success: (res) => {
  189. try {
  190. const data = JSON.parse(res.data);
  191. if (data.code === 200 || data.fileName) {
  192. const imagePath = data.fileName || data.url;
  193. resolve(imagePath);
  194. } else {
  195. reject(new Error(data.msg || '上传失败'));
  196. }
  197. } catch (e) {
  198. reject(e);
  199. }
  200. },
  201. fail: (err) => {
  202. reject(err);
  203. }
  204. });
  205. });
  206. });
  207. Promise.all(uploadTasks)
  208. .then((imagePaths) => {
  209. wx.hideLoading();
  210. // 将新上传的图片添加到现有图片数组中
  211. const newReplyImages = [...this.data.replyImages, ...imagePaths];
  212. this.setData({
  213. replyImages: newReplyImages,
  214. isUploading: false
  215. });
  216. wx.showToast({
  217. title: '上传成功',
  218. icon: 'success'
  219. });
  220. })
  221. .catch((err) => {
  222. wx.hideLoading();
  223. console.error('上传失败:', err);
  224. // 上传失败时,移除对应的临时预览图片
  225. const failedCount = filePaths.length;
  226. const currentTempPaths = [...this.data.replyImagesTemp];
  227. for (let i = 0; i < failedCount; i++) {
  228. currentTempPaths.pop();
  229. }
  230. this.setData({
  231. replyImagesTemp: currentTempPaths,
  232. isUploading: false
  233. });
  234. wx.showToast({
  235. title: '上传失败,请重试',
  236. icon: 'none'
  237. });
  238. });
  239. },
  240. /**
  241. * 移除单张回复图片
  242. */
  243. removeReplyImage(e) {
  244. const index = e.currentTarget.dataset.index;
  245. const replyImages = this.data.replyImages.filter((_, i) => i !== index);
  246. const replyImagesTemp = this.data.replyImagesTemp.filter((_, i) => i !== index);
  247. this.setData({
  248. replyImages: replyImages,
  249. replyImagesTemp: replyImagesTemp
  250. });
  251. },
  252. /**
  253. * 提交回复 - 优化后的版本
  254. */
  255. submitReply() {
  256. const content = this.data.replyContent.trim();
  257. const images = this.data.replyImages;
  258. // 检查内容
  259. if (!content && images.length === 0) {
  260. wx.showToast({
  261. title: '请输入回复内容或上传图片',
  262. icon: 'none'
  263. });
  264. return;
  265. }
  266. if (this.data.submittingReply || this.data.isUploading) {
  267. wx.showToast({
  268. title: this.data.isUploading ? '图片上传中,请稍后' : '提交中,请稍后',
  269. icon: 'none'
  270. });
  271. return;
  272. }
  273. this.setData({ submittingReply: true });
  274. // 显示加载提示
  275. wx.showLoading({
  276. title: '发送中...',
  277. mask: true
  278. });
  279. // 准备提交数据
  280. const submitData = {
  281. consultationId: this.data.diagnosisData.formId,
  282. content: content
  283. };
  284. // 如果有图片,将图片数组转为逗号分隔的字符串
  285. if (images.length > 0) {
  286. submitData.images = images.join(',');
  287. }
  288. console.log('提交回复数据:', submitData);
  289. // 调用回复接口
  290. http.wzdAdd({
  291. data: submitData,
  292. success: res => {
  293. wx.hideLoading();
  294. if (res.code === 200 || res.success) {
  295. // 清空输入
  296. this.setData({
  297. replyContent: '',
  298. replyImages: [],
  299. replyImagesTemp: [],
  300. submittingReply: false
  301. });
  302. wx.showToast({
  303. title: '回复成功',
  304. icon: 'success'
  305. });
  306. // 重新加载回复列表
  307. this.loadDiagnosisData(this.data.diagnosisData.formId);
  308. // 滚动到底部
  309. setTimeout(() => {
  310. wx.createSelectorQuery().select('.page-content').boundingClientRect(rect => {
  311. wx.pageScrollTo({
  312. scrollTop: rect.height,
  313. duration: 300
  314. });
  315. }).exec();
  316. }, 500);
  317. } else {
  318. this.setData({ submittingReply: false });
  319. wx.showToast({
  320. title: res.message || '回复失败',
  321. icon: 'none'
  322. });
  323. }
  324. },
  325. fail: err => {
  326. wx.hideLoading();
  327. this.setData({ submittingReply: false });
  328. console.error('回复失败:', err);
  329. wx.showToast({
  330. title: '网络错误,请重试',
  331. icon: 'none'
  332. });
  333. }
  334. });
  335. },
  336. /**
  337. * 返回上一页
  338. */
  339. goBack() {
  340. wx.navigateBack();
  341. },
  342. /**
  343. * 分享
  344. */
  345. onShare() {
  346. wx.showActionSheet({
  347. itemList: ['分享给好友', '保存到相册'],
  348. success: (res) => {
  349. if (res.tapIndex === 0) {
  350. wx.showToast({
  351. title: '已分享',
  352. icon: 'success'
  353. });
  354. }
  355. }
  356. });
  357. },
  358. /**
  359. * 下拉刷新
  360. */
  361. onRefresh() {
  362. this.setData({
  363. refreshing: true
  364. });
  365. if (this.data.diagnosisData && this.data.diagnosisData.formId) {
  366. this.loadDiagnosisData(this.data.diagnosisData.formId)
  367. }
  368. setTimeout(() => {
  369. this.setData({
  370. refreshing: false
  371. });
  372. wx.showToast({
  373. title: '刷新成功',
  374. icon: 'success'
  375. });
  376. }, 1000);
  377. },
  378. /**
  379. * 预览用户图片
  380. */
  381. previewImage(e) {
  382. const dataset = e.currentTarget.dataset;
  383. const current = dataset.url;
  384. const urls = dataset.urls || [];
  385. // 构建完整URL数组
  386. const urlsArray = urls.map(item => {
  387. if (typeof item === 'string' && (item.startsWith('http://') || item.startsWith('https://'))) {
  388. return item;
  389. }
  390. return baseUrl + item;
  391. });
  392. console.log('预览用户图片:', urlsArray);
  393. wx.previewImage({
  394. current: current,
  395. urls: urlsArray
  396. });
  397. },
  398. /**
  399. * 预览兽医回复图片
  400. */
  401. previewReplyImage(e) {
  402. const dataset = e.currentTarget.dataset;
  403. const currentFileName = dataset.url;
  404. const currentFullUrl = dataset.fullurl;
  405. const urlsArray = dataset.urls || [];
  406. const currentIndex = dataset.currentIndex || 0;
  407. const replyIndex = dataset.replyIndex;
  408. console.log('预览兽医图片 - 数据集:', dataset);
  409. // 从replies数据中获取当前回复的图片列表
  410. let targetUrls = [];
  411. let targetCurrentUrl = '';
  412. if (replyIndex !== undefined && this.data.replies[replyIndex]) {
  413. const reply = this.data.replies[replyIndex];
  414. if (reply.images && reply.images.length > 0) {
  415. targetUrls = reply.images;
  416. const fullUrls = targetUrls.map(img => {
  417. if (typeof img === 'string' && (img.startsWith('http://') || img.startsWith('https://'))) {
  418. return img;
  419. }
  420. return baseUrl + img;
  421. });
  422. if (currentIndex < fullUrls.length) {
  423. targetCurrentUrl = fullUrls[currentIndex];
  424. } else if (currentFullUrl) {
  425. targetCurrentUrl = currentFullUrl;
  426. } else if (currentFileName) {
  427. targetCurrentUrl = baseUrl + currentFileName;
  428. }
  429. console.log('预览兽医回复图片:', fullUrls, '当前:', targetCurrentUrl);
  430. wx.previewImage({
  431. current: targetCurrentUrl,
  432. urls: fullUrls
  433. });
  434. return;
  435. }
  436. }
  437. // 使用dataset中的数据
  438. if (urlsArray && urlsArray.length > 0) {
  439. const fullUrls = urlsArray.map(item => {
  440. if (typeof item === 'string' && (item.startsWith('http://') || item.startsWith('https://'))) {
  441. return item;
  442. }
  443. return baseUrl + item;
  444. });
  445. let currentUrl = '';
  446. if (currentFullUrl) {
  447. currentUrl = currentFullUrl;
  448. } else if (currentIndex < fullUrls.length) {
  449. currentUrl = fullUrls[currentIndex];
  450. } else if (currentFileName) {
  451. currentUrl = baseUrl + currentFileName;
  452. }
  453. console.log('预览兽医回复图片(从dataset):', fullUrls, '当前:', currentUrl);
  454. wx.previewImage({
  455. current: currentUrl,
  456. urls: fullUrls
  457. });
  458. return;
  459. }
  460. // 预览单张图片
  461. if (currentFullUrl) {
  462. console.log('预览单张兽医图片:', [currentFullUrl]);
  463. wx.previewImage({
  464. current: currentFullUrl,
  465. urls: [currentFullUrl]
  466. });
  467. } else if (currentFileName) {
  468. const fullUrl = baseUrl + currentFileName;
  469. console.log('预览单张兽医图片(拼接后):', [fullUrl]);
  470. wx.previewImage({
  471. current: fullUrl,
  472. urls: [fullUrl]
  473. });
  474. } else {
  475. wx.showToast({
  476. title: '图片预览失败',
  477. icon: 'none'
  478. });
  479. }
  480. },
  481. /**
  482. * 生命周期函数--监听页面显示
  483. */
  484. onShow() {
  485. // 如果已经有数据,刷新列表
  486. if (this.data.diagnosisData && this.data.diagnosisData.formId) {
  487. this.loadDiagnosisData(this.data.diagnosisData.formId);
  488. }
  489. },
  490. /**
  491. * 生命周期函数--监听页面卸载
  492. */
  493. onUnload() {
  494. // 页面卸载时重置状态
  495. this.setData({
  496. submittingReply: false,
  497. isUploading: false
  498. });
  499. }
  500. });