与牧同行-小程序用户端
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.

476 lines
11 KiB

  1. import http from '../../../utils/api'
  2. const baseUrl = require('../../../utils/baseUrl')
  3. Page({
  4. data: {
  5. // 帖子列表相关
  6. posts: [],
  7. baseUrl: baseUrl,
  8. loading: false,
  9. searchLoading: false,
  10. initialLoading: true,
  11. loadingMore: false,
  12. refreshing: false,
  13. hasMore: true,
  14. page: 1,
  15. pageSize: 10,
  16. searchKeyword: '',
  17. lastSearchKeyword: '', // 新增:记录上次搜索关键词
  18. scrollTop: 0,
  19. showBackToTop: false,
  20. scrollThreshold: 300,
  21. // 发布帖子相关
  22. showPostModal: false,
  23. postTitle: '',
  24. postContent: '',
  25. postImages: [],
  26. isSubmitting: false
  27. },
  28. onLoad: function () {
  29. this.loadPosts(true);
  30. },
  31. onShow: function () {
  32. // 每次显示页面时刷新数据
  33. this.refreshData();
  34. },
  35. // 加载帖子列表
  36. loadPosts: function (reset = false) {
  37. // 防止重复请求
  38. if (reset) {
  39. this.setData({
  40. page: 1,
  41. hasMore: true,
  42. loading: true,
  43. searchLoading: !!this.data.searchKeyword
  44. });
  45. } else if (this.data.loadingMore) {
  46. return;
  47. }
  48. this.setData({
  49. loading: reset || this.data.page === 1,
  50. loadingMore: !reset && this.data.page > 1
  51. });
  52. // 准备请求参数
  53. const params = {
  54. page: this.data.page,
  55. pageSize: this.data.pageSize
  56. };
  57. // 如果有搜索关键词,添加搜索参数
  58. const searchKeyword = this.data.searchKeyword.trim();
  59. if (searchKeyword) {
  60. params.searchKey = searchKeyword;
  61. }
  62. // 记录当前搜索关键词
  63. this.setData({
  64. lastSearchKeyword: searchKeyword
  65. });
  66. // 调用接口获取数据
  67. http.forumList({
  68. data: params,
  69. success: (res) => {
  70. if (res.code === 200) {
  71. let postsData = res.rows || [];
  72. // 处理图片字段(分割字符串为数组)
  73. postsData = postsData.map(item => {
  74. if (item.images && typeof item.images === 'string') {
  75. item.images = item.images.split(',').filter(img => img.trim() !== '');
  76. } else {
  77. item.images = [];
  78. }
  79. return item;
  80. });
  81. if (reset) {
  82. this.setData({
  83. posts: postsData,
  84. loading: false,
  85. searchLoading: false,
  86. initialLoading: false,
  87. hasMore: postsData.length === this.data.pageSize
  88. });
  89. } else {
  90. this.setData({
  91. posts: [...this.data.posts, ...postsData],
  92. loading: false,
  93. initialLoading: false,
  94. loadingMore: false,
  95. hasMore: postsData.length === this.data.pageSize
  96. });
  97. }
  98. } else {
  99. wx.showToast({
  100. title: res.msg || '加载失败',
  101. icon: 'none'
  102. });
  103. this.setData({
  104. loading: false,
  105. searchLoading: false,
  106. initialLoading: false,
  107. loadingMore: false
  108. });
  109. }
  110. if (this.data.refreshing) {
  111. wx.stopPullDownRefresh();
  112. this.setData({
  113. refreshing: false
  114. });
  115. }
  116. },
  117. fail: (err) => {
  118. wx.showToast({
  119. title: '网络错误',
  120. icon: 'none'
  121. });
  122. this.setData({
  123. loading: false,
  124. searchLoading: false,
  125. initialLoading: false,
  126. loadingMore: false,
  127. refreshing: false
  128. });
  129. }
  130. });
  131. },
  132. // 下拉刷新
  133. onRefresh: function () {
  134. this.setData({
  135. refreshing: true
  136. });
  137. this.loadPosts(true);
  138. },
  139. // 加载更多
  140. loadMore: function () {
  141. if (!this.data.hasMore || this.data.loadingMore) return;
  142. this.setData({
  143. page: this.data.page + 1
  144. }, () => {
  145. this.loadPosts();
  146. });
  147. },
  148. // 搜索输入(防抖)
  149. onSearchInput: function (e) {
  150. const keyword = e.detail.value;
  151. this.setData({
  152. searchKeyword: keyword
  153. });
  154. // 防抖搜索
  155. clearTimeout(this.searchTimer);
  156. // 如果输入框为空,立即重置搜索
  157. if (!keyword.trim()) {
  158. this.setData({
  159. searchKeyword: ''
  160. });
  161. // 清空搜索时立即重新加载数据
  162. this.loadPosts(true);
  163. return;
  164. }
  165. this.searchTimer = setTimeout(() => {
  166. // 只有当有搜索词且与上次不同时才搜索
  167. if (keyword.trim() && keyword.trim() !== this.data.lastSearchKeyword) {
  168. this.loadPosts(true);
  169. }
  170. }, 500);
  171. },
  172. // 搜索确认
  173. onSearchConfirm: function (e) {
  174. const keyword = e.detail.value.trim();
  175. this.setData({
  176. searchKeyword: keyword
  177. });
  178. // 如果搜索词为空,加载所有帖子
  179. if (!keyword) {
  180. this.loadPosts(true);
  181. } else {
  182. // 只有当搜索词与上次不同时才搜索
  183. if (keyword !== this.data.lastSearchKeyword) {
  184. this.loadPosts(true);
  185. }
  186. }
  187. },
  188. // 清空搜索 - 优化版
  189. clearSearch: function () {
  190. // 如果当前已经有搜索词,才执行清空操作
  191. if (this.data.searchKeyword) {
  192. this.setData({
  193. searchKeyword: ''
  194. }, () => {
  195. // 清空后立即加载所有帖子
  196. this.loadPosts(true);
  197. });
  198. }
  199. },
  200. // 跳转到详情页
  201. goToDetail: function (e) {
  202. const postId = e.currentTarget.dataset.id;
  203. wx.navigateTo({
  204. url: `/pagesB/pages/onlineAsk/onlineAsk?id=${postId}`
  205. });
  206. },
  207. // 图片预览功能
  208. previewImage: function (e) {
  209. const postIndex = e.currentTarget.dataset.postindex;
  210. const imageIndex = e.currentTarget.dataset.imageindex;
  211. const post = this.data.posts[postIndex];
  212. if (!post || !post.images || post.images.length === 0) return;
  213. // 构建完整的图片URL数组
  214. const urls = post.images.map(img => this.data.baseUrl + img);
  215. wx.previewImage({
  216. current: urls[imageIndex], // 当前显示图片的链接
  217. urls: urls // 需要预览的图片链接列表
  218. });
  219. },
  220. // 显示发布模态框
  221. createPost: function () {
  222. // 检查登录状态(如果需要)
  223. // 这里可以添加登录检查逻辑
  224. this.setData({
  225. showPostModal: true
  226. });
  227. },
  228. // 隐藏发布模态框
  229. hidePostModal: function () {
  230. if (this.data.isSubmitting) return;
  231. this.setData({
  232. showPostModal: false,
  233. postTitle: '',
  234. postContent: '',
  235. postImages: []
  236. });
  237. },
  238. // 阻止事件冒泡
  239. stopPropagation: function () {},
  240. // 标题输入
  241. onPostTitleInput: function (e) {
  242. this.setData({
  243. postTitle: e.detail.value
  244. });
  245. },
  246. // 内容输入
  247. onPostContentInput: function (e) {
  248. this.setData({
  249. postContent: e.detail.value
  250. });
  251. },
  252. // 选择图片
  253. chooseImage: function () {
  254. const remaining = 3 - this.data.postImages.length;
  255. if (remaining <= 0) {
  256. wx.showToast({
  257. title: '最多上传3张图片',
  258. icon: 'none'
  259. });
  260. return;
  261. }
  262. wx.chooseMedia({
  263. count: remaining,
  264. mediaType: ['image'],
  265. sizeType: ['compressed'],
  266. sourceType: ['album', 'camera'],
  267. success: (res) => {
  268. const tempFiles = res.tempFiles;
  269. const newImages = tempFiles.map(file => file.tempFilePath);
  270. const postImages = [...this.data.postImages, ...newImages];
  271. this.setData({
  272. postImages: postImages.slice(0, 3) // 确保不超过3张
  273. });
  274. },
  275. fail: (err) => {
  276. console.error('选择图片失败:', err);
  277. }
  278. });
  279. },
  280. // 移除图片
  281. removeImage: function (e) {
  282. const index = e.currentTarget.dataset.index;
  283. const postImages = [...this.data.postImages];
  284. postImages.splice(index, 1);
  285. this.setData({
  286. postImages
  287. });
  288. },
  289. // 提交帖子
  290. submitPost: function () {
  291. const { postTitle, postContent, postImages } = this.data;
  292. // 验证输入
  293. if (!postTitle.trim()) {
  294. wx.showToast({
  295. title: '请输入标题',
  296. icon: 'none'
  297. });
  298. return;
  299. }
  300. if (!postContent.trim()) {
  301. wx.showToast({
  302. title: '请输入内容',
  303. icon: 'none'
  304. });
  305. return;
  306. }
  307. this.setData({
  308. isSubmitting: true
  309. });
  310. // 如果有图片,先上传图片
  311. const uploadPromises = postImages.map(imagePath => {
  312. return new Promise((resolve, reject) => {
  313. wx.uploadFile({
  314. url: baseUrl+'/common/upload',
  315. header: {
  316. 'Authorization': 'Bearer ' + wx.getStorageSync('token')
  317. },
  318. filePath: imagePath,
  319. name: 'file',
  320. success: (res) => {
  321. const data = JSON.parse(res.data);
  322. console.log(data);
  323. if (data.code === 200) {
  324. resolve(data.fileName); // 假设返回的图片路径在data.url中
  325. } else {
  326. reject(new Error('图片上传失败'));
  327. }
  328. },
  329. fail: (err) => {
  330. reject(err);
  331. }
  332. });
  333. });
  334. });
  335. // 处理图片上传
  336. Promise.all(uploadPromises)
  337. .then((imageUrls) => {
  338. // 所有图片上传成功,提交帖子数据
  339. const postData = {
  340. title: postTitle,
  341. content: postContent,
  342. images: imageUrls.join(',') // 将图片URL用逗号拼接
  343. };
  344. return http.forumAdd({
  345. data: postData,
  346. success:res=>{
  347. console.log(1111,res);
  348. if (res.code === 200) {
  349. // 发布成功
  350. this.setData({
  351. showPostModal: false,
  352. postTitle: '',
  353. postContent: '',
  354. postImages: [],
  355. isSubmitting: false
  356. });
  357. wx.showToast({
  358. title: '发布成功',
  359. icon: 'success',
  360. duration: 2000
  361. });
  362. // 刷新帖子列表
  363. setTimeout(() => {
  364. this.loadPosts(true);
  365. }, 500);
  366. } else {
  367. throw new Error(res.msg || '发布失败');
  368. }
  369. }
  370. });
  371. })
  372. },
  373. // 滚动事件监听
  374. onScroll: function (e) {
  375. const scrollTop = e.detail.scrollTop;
  376. const showBackToTop = scrollTop > this.data.scrollThreshold;
  377. if (showBackToTop !== this.data.showBackToTop) {
  378. this.setData({
  379. scrollTop: scrollTop,
  380. showBackToTop: showBackToTop
  381. });
  382. }
  383. },
  384. // 返回顶部
  385. backToTop: function () {
  386. this.setData({
  387. showBackToTop: false
  388. });
  389. wx.pageScrollTo({
  390. scrollTop: 0,
  391. duration: 400,
  392. success: () => {
  393. this.setData({
  394. scrollTop: 0
  395. });
  396. },
  397. fail: (err) => {
  398. console.log('滚动失败:', err);
  399. this.setData({
  400. scrollTop: 0
  401. });
  402. }
  403. });
  404. },
  405. // 刷新数据
  406. refreshData: function () {
  407. const pages = getCurrentPages();
  408. const currentPage = pages[pages.length - 1];
  409. if (currentPage.data && currentPage.data.refresh) {
  410. this.loadPosts(true);
  411. currentPage.setData({
  412. refresh: false
  413. });
  414. }
  415. },
  416. onPullDownRefresh: function () {
  417. this.onRefresh();
  418. },
  419. onReachBottom: function () {
  420. this.loadMore();
  421. }
  422. });