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.

430 lines
14 KiB

  1. <template>
  2. <view class="task-upload">
  3. <!-- 任务状态提示 -->
  4. <view class="status-box" v-if="taskInfo.status != 0">
  5. <!-- 驳回状态 -->
  6. <view class="reject-box" v-if="taskInfo.status == 3">
  7. <view class="reject-icon"></view>
  8. <view class="reject-content">
  9. <view class="reject-title">拒绝原因:{{taskInfo.rejectTxt}}</view>
  10. </view>
  11. </view>
  12. <!-- 审核中状态 -->
  13. <view class="reviewing-box" v-if="taskInfo.status == 1">
  14. <view class="reviewing-icon"></view>
  15. <view class="reviewing-content">
  16. <view class="reviewing-title">任务审核中请耐心等待审核结果</view>
  17. </view>
  18. </view>
  19. <!-- 已通过状态 -->
  20. <view class="approved-box" v-if="taskInfo.status == 2">
  21. <view class="approved-icon"></view>
  22. <view class="approved-content">
  23. <view class="approved-title">任务已审核通过</view>
  24. </view>
  25. </view>
  26. </view>
  27. <!-- 上传表单 -->
  28. <view class="upload-form">
  29. <!-- 链接输入 -->
  30. <view class="form-item">
  31. <view class="form-label">笔记链接</view>
  32. <view class="form-input">
  33. <u-textarea v-model="formData.proveTxt"
  34. :border="false"
  35. height="300rpx"
  36. :disabled="taskInfo.status == 1 || taskInfo.status == 2"
  37. placeholder="请输入笔记链接" :maxlength="300" count />
  38. </view>
  39. </view>
  40. <!-- 图片上传 -->
  41. <view class="form-item">
  42. <view class="form-label">笔记截图</view>
  43. <view class="upload-box">
  44. <u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="proveImage"
  45. multiple :maxCount="3" :disabled="taskInfo.status == 1 || taskInfo.status == 2"></u-upload>
  46. </view>
  47. </view>
  48. <!-- 提交按钮 -->
  49. <view class="submit-btn" v-if="taskInfo.status == 0 || taskInfo.status == 3">
  50. <u-button type="primary" color="#ffaa48" shape="circle" @click="submitTaskHandler">提交审核</u-button>
  51. </view>
  52. </view>
  53. </view>
  54. </template>
  55. <script>
  56. import { getTaskDetailUser, submitTask } from "@/api/order/task.js"
  57. export default {
  58. data() {
  59. return {
  60. taskId: null,
  61. taskStatus: 0,
  62. taskInfo: {
  63. id: 0,
  64. title: '',
  65. taskEndTime: '',
  66. rejectTxt: '',
  67. proveTxt: '',
  68. status: 0
  69. },
  70. formData: {
  71. taskId: 0,
  72. proveImage: [],
  73. rejectTxt: '',
  74. proveTxt: '',
  75. },
  76. fileList: []
  77. }
  78. },
  79. onLoad(options) {
  80. if (options.id) {
  81. this.taskId = options.id
  82. this.formData.taskId = options.id
  83. this.getTaskDetail()
  84. } else {
  85. uni.showToast({
  86. title: '任务ID不存在',
  87. icon: 'none'
  88. })
  89. setTimeout(() => {
  90. uni.navigateBack()
  91. }, 1500)
  92. }
  93. },
  94. methods: {
  95. getTaskDetail() {
  96. // 获取任务详情
  97. getTaskDetailUser(this.taskId).then(res => {
  98. if (res && res.code == 200) {
  99. this.taskInfo = res.data
  100. // 如果任务已有审核文本,填充到表单
  101. if (res.data.proveTxt) {
  102. this.formData.proveTxt = res.data.proveTxt;
  103. }
  104. // 如果任务已有图片,添加到文件列表显示
  105. if (res.data.proveImage) {
  106. const imageUrls = res.data.proveImage.split(',');
  107. imageUrls.forEach(url => {
  108. if (url) {
  109. this.fileList.push({
  110. url: url,
  111. status: 'success',
  112. message: '已上传',
  113. isImage: true
  114. });
  115. // 同时更新formData中的图片数组
  116. this.formData.proveImage.push(url);
  117. }
  118. });
  119. }
  120. }
  121. })
  122. },
  123. uploadFilePromise(url) {
  124. return new Promise((resolve, reject) => {
  125. let uploadTask = uni.uploadFile({
  126. url: 'https://store-test.catmdogd.com/test-api/h5/oss/upload',
  127. filePath: url,
  128. name: 'file',
  129. formData: {
  130. user: 'test'
  131. },
  132. success: (res) => {
  133. if (res && res.data) {
  134. try {
  135. let resData = JSON.parse(res.data);
  136. if (resData.url) {
  137. resolve(resData.url);
  138. } else {
  139. reject("上传失败: 未获取到图片URL");
  140. }
  141. } catch (e) {
  142. reject("上传失败: 解析响应数据错误");
  143. }
  144. } else {
  145. reject("上传失败: 响应数据为空");
  146. }
  147. },
  148. fail: (err) => {
  149. reject("上传失败: " + (err.errMsg || JSON.stringify(err)));
  150. }
  151. });
  152. // 监听上传进度
  153. uploadTask.onProgressUpdate((res) => {
  154. // 查找当前正在上传的文件
  155. const index = this.fileList.findIndex(file => file.status == 'uploading');
  156. if (index != -1) {
  157. // 更新上传进度信息
  158. this.fileList[index].message = '上传中 ' + res.progress + '%';
  159. }
  160. });
  161. })
  162. },
  163. formatDate(dateStr) {
  164. if (!dateStr) return '';
  165. let date = new Date(dateStr);
  166. let year = date.getFullYear();
  167. let month = (date.getMonth() + 1).toString().padStart(2, '0');
  168. let day = date.getDate().toString().padStart(2, '0');
  169. return `${year}-${month}-${day}`;
  170. },
  171. afterRead(event) {
  172. // 读取文件后的处理
  173. const { file } = event
  174. // 处理文件数组
  175. const fileList = Array.isArray(file) ? file : [file]
  176. // 遍历处理每个文件
  177. fileList.forEach(item => {
  178. // 更新UI显示上传中状态
  179. const fileListItem = {
  180. ...item,
  181. status: 'uploading',
  182. message: '上传中'
  183. }
  184. this.fileList.push(fileListItem)
  185. const currentIndex = this.fileList.length - 1
  186. // 使用Promise上传图片
  187. this.uploadFilePromise(item.url)
  188. .then(url => {
  189. // 上传成功,更新状态和URL
  190. this.fileList[currentIndex].status = 'success'
  191. this.fileList[currentIndex].message = '上传成功'
  192. this.fileList[currentIndex].url = url
  193. // 保存上传后的URL
  194. this.formData.proveImage.push(url)
  195. })
  196. .catch(err => {
  197. // 上传失败
  198. this.fileList[currentIndex].status = 'failed'
  199. this.fileList[currentIndex].message = '上传失败'
  200. uni.showToast({
  201. title: '图片上传失败',
  202. icon: 'none'
  203. })
  204. })
  205. })
  206. },
  207. deletePic(event) {
  208. // 删除图片
  209. const index = event.index
  210. this.fileList.splice(index, 1)
  211. this.formData.proveImage.splice(index, 1)
  212. },
  213. submitTaskHandler() {
  214. // 表单验证
  215. if (!this.formData.proveTxt) {
  216. uni.showToast({
  217. title: '请输入笔记链接',
  218. icon: 'none'
  219. })
  220. return
  221. }
  222. if (this.formData.proveImage.length == 0) {
  223. uni.showToast({
  224. title: '请上传至少一张截图',
  225. icon: 'none'
  226. })
  227. return
  228. }
  229. // 检查是否有正在上传的图片
  230. const isUploading = this.fileList.some(file => file.status == 'uploading')
  231. if (isUploading) {
  232. uni.showToast({
  233. title: '图片正在上传中,请稍候',
  234. icon: 'none'
  235. })
  236. return
  237. }
  238. // 显示提交中提示
  239. uni.showLoading({
  240. title: '提交中...'
  241. })
  242. // 提交任务
  243. submitTask({
  244. id: this.taskId,
  245. taskId: this.formData.taskId,
  246. proveTxt: this.formData.proveTxt,
  247. proveImage: this.formData.proveImage.join(',')
  248. }).then(res => {
  249. uni.hideLoading()
  250. if (res && res.code == 200) {
  251. uni.showToast({
  252. title: '提交成功',
  253. icon: 'success'
  254. })
  255. // 返回任务详情页
  256. setTimeout(() => {
  257. uni.navigateBack()
  258. }, 1500)
  259. } else {
  260. uni.showToast({
  261. title: res.msg || '提交失败',
  262. icon: 'none'
  263. })
  264. }
  265. }).catch(err => {
  266. uni.hideLoading()
  267. uni.showToast({
  268. title: '提交失败',
  269. icon: 'none'
  270. })
  271. console.error('提交任务失败:', err)
  272. })
  273. }
  274. }
  275. }
  276. </script>
  277. <style lang="scss" scoped>
  278. .task-upload {
  279. padding: 20rpx;
  280. background-color: #f5f5f5;
  281. min-height: 100vh;
  282. .status-box {
  283. margin-bottom: 20rpx;
  284. }
  285. .reject-box {
  286. background-color: #fff2e8;
  287. border-radius: 10rpx;
  288. padding: 20rpx 30rpx;
  289. margin-bottom: 20rpx;
  290. display: flex;
  291. align-items: center;
  292. .reject-icon {
  293. font-size: 32rpx;
  294. color: #ff8800;
  295. margin-right: 15rpx;
  296. font-weight: bold;
  297. }
  298. .reject-content {
  299. flex: 1;
  300. }
  301. .reject-title {
  302. font-size: 28rpx;
  303. color: #ff8800;
  304. font-weight: 500;
  305. }
  306. }
  307. .reviewing-box {
  308. background-color: #fff7e6;
  309. border-radius: 10rpx;
  310. padding: 20rpx 30rpx;
  311. margin-bottom: 20rpx;
  312. display: flex;
  313. align-items: center;
  314. .reviewing-icon {
  315. font-size: 32rpx;
  316. color: #fa8c16;
  317. margin-right: 15rpx;
  318. font-weight: bold;
  319. }
  320. .reviewing-content {
  321. flex: 1;
  322. }
  323. .reviewing-title {
  324. font-size: 28rpx;
  325. color: #fa8c16;
  326. font-weight: 500;
  327. }
  328. }
  329. .approved-box {
  330. background-color: #f6ffed;
  331. border-radius: 10rpx;
  332. padding: 20rpx 30rpx;
  333. margin-bottom: 20rpx;
  334. display: flex;
  335. align-items: center;
  336. .approved-icon {
  337. font-size: 32rpx;
  338. color: #52c41a;
  339. margin-right: 15rpx;
  340. font-weight: bold;
  341. }
  342. .approved-content {
  343. flex: 1;
  344. }
  345. .approved-title {
  346. font-size: 28rpx;
  347. color: #52c41a;
  348. font-weight: 500;
  349. }
  350. }
  351. .upload-form {
  352. border-radius: 10rpx;
  353. padding: 10rpx;
  354. .form-item {
  355. margin-bottom: 40rpx;
  356. background-color: #fff;
  357. padding: 30rpx;
  358. border-radius: 10rpx;
  359. &:last-child {
  360. margin-bottom: 0;
  361. }
  362. .form-label {
  363. font-size: 28rpx;
  364. color: #333;
  365. font-weight: 500;
  366. margin-bottom: 20rpx;
  367. position: relative;
  368. &::before {
  369. content: '';
  370. width: 6rpx;
  371. height: 28rpx;
  372. background-color: #ff8800;
  373. position: absolute;
  374. left: -20rpx;
  375. top: 50%;
  376. transform: translateY(-50%);
  377. border-radius: 3rpx;
  378. }
  379. }
  380. .form-input {
  381. margin-bottom: 10rpx;
  382. }
  383. .upload-box {
  384. margin-top: 20rpx;
  385. }
  386. }
  387. .submit-btn {
  388. margin-top: 60rpx;
  389. padding: 0 40rpx;
  390. }
  391. }
  392. }
  393. </style>