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

579 lines
14 KiB

  1. import http from '../../../utils/api'
  2. const baseUrl = require('../../../utils/baseUrl')
  3. Page({
  4. data: {
  5. baseUrl,
  6. currentTab: 'article',
  7. // 文章相关
  8. articleForm: {
  9. title: '',
  10. subtitle: '',
  11. category: '',
  12. content: '',
  13. coverImage: '' // 这里存储服务器返回的文件名
  14. },
  15. articleCoverTemp: '', // 本地临时路径,用于预览
  16. articleCategory: null,
  17. articleCategories: [],
  18. // 视频相关
  19. videoForm: {
  20. title: '',
  21. description: '',
  22. category: '',
  23. videoUrl: '', // 这里存储服务器返回的视频文件名
  24. coverImage: '' // 这里存储服务器返回的封面文件名
  25. },
  26. videoCoverTemp: '', // 本地临时路径,用于预览
  27. videoUrlTemp: '', // 本地临时路径,用于显示
  28. videoCategory: null,
  29. videoCategories: [],
  30. // UI状态
  31. submitting: false,
  32. isUploading: false, // 防止重复上传
  33. showLoadingMask: false, // 显示加载遮罩层
  34. loadingText: '发布中...', // 加载提示文字
  35. // 表单验证状态
  36. articleFormValid: false,
  37. videoFormValid: false,
  38. },
  39. onLoad() {
  40. this.getArticleCategories()
  41. this.getVideoCategories()
  42. },
  43. /**
  44. * 生命周期函数--监听页面卸载
  45. */
  46. onUnload() {
  47. // 页面卸载时重置状态
  48. this.setData({
  49. submitting: false,
  50. showLoadingMask: false
  51. });
  52. },
  53. // 获取文章分类
  54. getArticleCategories() {
  55. http.articleZd({
  56. data: {
  57. dictType: 'article_category'
  58. },
  59. success: res => {
  60. if (res.rows) {
  61. this.setData({
  62. articleCategories: res.rows
  63. })
  64. }
  65. }
  66. })
  67. },
  68. // 获取视频分类
  69. getVideoCategories() {
  70. http.videoZd({
  71. data: {
  72. dictType: 'video_category'
  73. },
  74. success: res => {
  75. if (res.rows) {
  76. this.setData({
  77. videoCategories: res.rows
  78. })
  79. }
  80. }
  81. })
  82. },
  83. // 切换标签
  84. switchTab(e) {
  85. const type = e.currentTarget.dataset.type
  86. if (type === this.data.currentTab) return
  87. this.setData({ currentTab: type })
  88. },
  89. // 验证文章表单
  90. validateArticleForm() {
  91. const { articleForm } = this.data
  92. const isValid = !!(articleForm.title?.trim() && articleForm.category && articleForm.content?.trim())
  93. this.setData({ articleFormValid: isValid })
  94. return isValid
  95. },
  96. // 验证视频表单
  97. validateVideoForm() {
  98. const { videoForm } = this.data
  99. const isValid = !!(videoForm.title?.trim() && videoForm.category && videoForm.videoUrl)
  100. this.setData({ videoFormValid: isValid })
  101. return isValid
  102. },
  103. // 文章输入处理
  104. onArticleInput(e) {
  105. const field = e.currentTarget.dataset.field
  106. const value = e.detail.value
  107. this.setData({
  108. [`articleForm.${field}`]: value
  109. }, () => {
  110. this.validateArticleForm()
  111. })
  112. },
  113. // 视频输入处理
  114. onVideoInput(e) {
  115. const field = e.currentTarget.dataset.field
  116. const value = e.detail.value
  117. this.setData({
  118. [`videoForm.${field}`]: value
  119. }, () => {
  120. this.validateVideoForm()
  121. })
  122. },
  123. // 文章分类选择
  124. onArticleCategoryChange(e) {
  125. const index = e.detail.value
  126. const category = this.data.articleCategories[index]
  127. this.setData({
  128. 'articleForm.category': category.dictValue,
  129. articleCategory: category
  130. }, () => {
  131. this.validateArticleForm()
  132. })
  133. },
  134. // 视频分类选择
  135. onVideoCategoryChange(e) {
  136. const index = e.detail.value
  137. const category = this.data.videoCategories[index]
  138. this.setData({
  139. 'videoForm.category': category.dictValue,
  140. videoCategory: category
  141. }, () => {
  142. this.validateVideoForm()
  143. })
  144. },
  145. // 选择封面图片(文章或视频)
  146. chooseCover(e) {
  147. if (this.data.isUploading) {
  148. wx.showToast({
  149. title: '正在上传中,请稍候',
  150. icon: 'none'
  151. });
  152. return;
  153. }
  154. const type = e.currentTarget.dataset.type
  155. wx.chooseMedia({
  156. count: 1,
  157. mediaType: ['image'],
  158. sourceType: ['album', 'camera'],
  159. sizeType: ['compressed'],
  160. success: (res) => {
  161. if (res.tempFiles && res.tempFiles.length > 0) {
  162. this.setData({
  163. isUploading: true
  164. });
  165. // 显示加载提示
  166. wx.showLoading({
  167. title: '上传图片中...',
  168. mask: true
  169. });
  170. // 上传图片
  171. this.uploadImage(res.tempFiles[0].tempFilePath, type);
  172. }
  173. }
  174. });
  175. },
  176. // 上传单张图片
  177. uploadImage(tempPath, type) {
  178. wx.uploadFile({
  179. url: baseUrl + '/common/upload',
  180. header: {
  181. 'Authorization': 'Bearer ' + wx.getStorageSync('token')
  182. },
  183. filePath: tempPath,
  184. name: 'file',
  185. success: (uploadRes) => {
  186. try {
  187. const result = JSON.parse(uploadRes.data);
  188. if (result.code === 200 || result.fileName) {
  189. const serverPath = result.fileName || result.url;
  190. if (type === 'article') {
  191. // 文章封面
  192. this.setData({
  193. articleCoverTemp: tempPath,
  194. 'articleForm.coverImage': serverPath,
  195. isUploading: false
  196. });
  197. } else {
  198. // 视频封面
  199. this.setData({
  200. videoCoverTemp: tempPath,
  201. 'videoForm.coverImage': serverPath,
  202. isUploading: false
  203. }, () => {
  204. this.validateVideoForm();
  205. });
  206. }
  207. wx.hideLoading();
  208. wx.showToast({
  209. title: '上传成功',
  210. icon: 'success'
  211. });
  212. } else {
  213. throw new Error(result.msg || '上传失败');
  214. }
  215. } catch (error) {
  216. wx.hideLoading();
  217. this.setData({
  218. isUploading: false
  219. });
  220. wx.showToast({
  221. title: error.message || '上传失败',
  222. icon: 'none'
  223. });
  224. }
  225. },
  226. fail: (error) => {
  227. wx.hideLoading();
  228. this.setData({
  229. isUploading: false
  230. });
  231. wx.showToast({
  232. title: '网络请求失败',
  233. icon: 'none'
  234. });
  235. }
  236. });
  237. },
  238. // 选择视频
  239. chooseVideo() {
  240. if (this.data.isUploading) {
  241. wx.showToast({
  242. title: '正在上传中,请稍候',
  243. icon: 'none'
  244. });
  245. return;
  246. }
  247. wx.chooseMedia({
  248. count: 1,
  249. mediaType: ['video'],
  250. sourceType: ['album', 'camera'],
  251. maxDuration: 300,
  252. success: (res) => {
  253. if (res.tempFiles && res.tempFiles.length > 0) {
  254. this.setData({
  255. isUploading: true,
  256. videoUrlTemp: res.tempFiles[0].tempFilePath // 先显示本地路径
  257. });
  258. // 显示加载提示
  259. wx.showLoading({
  260. title: '上传视频中...',
  261. mask: true
  262. });
  263. // 上传视频
  264. this.uploadVideo(res.tempFiles[0].tempFilePath);
  265. }
  266. }
  267. });
  268. },
  269. // 上传视频
  270. uploadVideo(tempPath) {
  271. wx.uploadFile({
  272. url: baseUrl + '/common/upload',
  273. header: {
  274. 'Authorization': 'Bearer ' + wx.getStorageSync('token')
  275. },
  276. filePath: tempPath,
  277. name: 'file',
  278. success: (uploadRes) => {
  279. try {
  280. const result = JSON.parse(uploadRes.data);
  281. if (result.code === 200 || result.fileName) {
  282. const serverPath = result.fileName || result.url;
  283. this.setData({
  284. 'videoForm.videoUrl': serverPath,
  285. isUploading: false
  286. }, () => {
  287. this.validateVideoForm();
  288. });
  289. wx.hideLoading();
  290. wx.showToast({
  291. title: '上传成功',
  292. icon: 'success'
  293. });
  294. } else {
  295. throw new Error(result.msg || '上传失败');
  296. }
  297. } catch (error) {
  298. wx.hideLoading();
  299. this.setData({
  300. videoUrlTemp: '', // 上传失败清空临时路径
  301. isUploading: false
  302. });
  303. wx.showToast({
  304. title: error.message || '上传失败',
  305. icon: 'none'
  306. });
  307. }
  308. },
  309. fail: (error) => {
  310. wx.hideLoading();
  311. this.setData({
  312. videoUrlTemp: '', // 上传失败清空临时路径
  313. isUploading: false
  314. });
  315. wx.showToast({
  316. title: '网络请求失败',
  317. icon: 'none'
  318. });
  319. }
  320. });
  321. },
  322. // 提交文章
  323. submitArticle() {
  324. const { articleForm, submitting, isUploading } = this.data
  325. if (submitting) return
  326. // 检查是否还有图片正在上传
  327. if (isUploading) {
  328. wx.showToast({
  329. title: '图片正在上传中,请稍后提交',
  330. icon: 'none'
  331. });
  332. return;
  333. }
  334. // 表单验证
  335. if (!this.validateArticleForm()) {
  336. if (!articleForm.title?.trim()) {
  337. this.showError('请输入文章标题')
  338. } else if (!articleForm.category) {
  339. this.showError('请选择文章分类')
  340. } else if (!articleForm.content?.trim()) {
  341. this.showError('请输入文章内容')
  342. }
  343. return
  344. }
  345. // 显示加载遮罩层
  346. this.setData({
  347. submitting: true,
  348. showLoadingMask: true,
  349. loadingText: '发布中...'
  350. });
  351. // 构建提交数据
  352. const submitData = {
  353. title: articleForm.title.trim(),
  354. subtitle: articleForm.subtitle?.trim() || '',
  355. content: articleForm.content.trim(),
  356. coverImage: articleForm.coverImage || '',
  357. category: articleForm.category
  358. }
  359. // 调用接口
  360. http.articleAdd({
  361. data: submitData,
  362. success: (res) => {
  363. if (res.code == 200) {
  364. this.setData({
  365. loadingText: '发布成功'
  366. });
  367. setTimeout(() => {
  368. this.setData({
  369. submitting: false,
  370. showLoadingMask: false
  371. });
  372. wx.showToast({
  373. title: '发布成功',
  374. icon: 'success',
  375. duration: 1500,
  376. success: () => {
  377. setTimeout(() => {
  378. wx.navigateBack()
  379. }, 1500);
  380. }
  381. });
  382. }, 1000);
  383. } else {
  384. this.setData({
  385. loadingText: '发布失败'
  386. });
  387. setTimeout(() => {
  388. this.setData({
  389. submitting: false,
  390. showLoadingMask: false
  391. });
  392. wx.showToast({
  393. title: res.msg || '发布失败,请重试',
  394. icon: 'none',
  395. duration: 2000
  396. });
  397. }, 1000);
  398. }
  399. },
  400. fail: (err) => {
  401. this.setData({
  402. loadingText: '网络错误'
  403. });
  404. setTimeout(() => {
  405. this.setData({
  406. submitting: false,
  407. showLoadingMask: false
  408. });
  409. wx.showToast({
  410. title: '网络异常,请检查网络后重试',
  411. icon: 'none',
  412. duration: 2000
  413. });
  414. }, 1000);
  415. }
  416. })
  417. },
  418. // 提交视频
  419. submitVideo() {
  420. const { videoForm, submitting, isUploading } = this.data
  421. if (submitting) return
  422. // 检查是否还有图片或视频正在上传
  423. if (isUploading) {
  424. wx.showToast({
  425. title: '文件正在上传中,请稍后提交',
  426. icon: 'none'
  427. });
  428. return;
  429. }
  430. // 表单验证
  431. if (!this.validateVideoForm()) {
  432. if (!videoForm.title?.trim()) {
  433. this.showError('请输入视频标题')
  434. } else if (!videoForm.category) {
  435. this.showError('请选择视频分类')
  436. } else if (!videoForm.videoUrl) {
  437. this.showError('请选择视频')
  438. }
  439. return
  440. }
  441. // 显示加载遮罩层
  442. this.setData({
  443. submitting: true,
  444. showLoadingMask: true,
  445. loadingText: '发布中...'
  446. });
  447. // 构建提交数据
  448. const submitData = {
  449. title: videoForm.title.trim(),
  450. description: videoForm.description?.trim() || '',
  451. videoUrl: videoForm.videoUrl,
  452. coverImage: videoForm.coverImage || '',
  453. category: videoForm.category
  454. }
  455. // 调用接口
  456. http.videoAdd({
  457. data: submitData,
  458. success: (res) => {
  459. if (res.code == 200) {
  460. this.setData({
  461. loadingText: '发布成功'
  462. });
  463. setTimeout(() => {
  464. this.setData({
  465. submitting: false,
  466. showLoadingMask: false
  467. });
  468. wx.showToast({
  469. title: '发布成功',
  470. icon: 'success',
  471. duration: 1500,
  472. success: () => {
  473. setTimeout(() => {
  474. wx.navigateBack()
  475. }, 1500);
  476. }
  477. });
  478. }, 1000);
  479. } else {
  480. this.setData({
  481. loadingText: '发布失败'
  482. });
  483. setTimeout(() => {
  484. this.setData({
  485. submitting: false,
  486. showLoadingMask: false
  487. });
  488. wx.showToast({
  489. title: res.msg || '发布失败,请重试',
  490. icon: 'none',
  491. duration: 2000
  492. });
  493. }, 1000);
  494. }
  495. },
  496. fail: (err) => {
  497. this.setData({
  498. loadingText: '网络错误'
  499. });
  500. setTimeout(() => {
  501. this.setData({
  502. submitting: false,
  503. showLoadingMask: false
  504. });
  505. wx.showToast({
  506. title: '网络异常,请检查网络后重试',
  507. icon: 'none',
  508. duration: 2000
  509. });
  510. }, 1000);
  511. }
  512. })
  513. },
  514. // 显示错误提示
  515. showError(msg) {
  516. wx.showToast({
  517. title: msg,
  518. icon: 'none',
  519. duration: 2000
  520. });
  521. }
  522. })