refund-processing.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. import { getAfterSaleDetailMethod, cancelAfterSaleMethod, applyAfterSaleMethod, updateAfterSaleMethod } from "../../request";
  2. // progress 数字转页面状态
  3. const progressToState: Record<string, string> = {
  4. '0': 'processing',
  5. '1': 'revoked',
  6. '2': 'rejected',
  7. '3': 'approved',
  8. '4': 'completed',
  9. };
  10. Page({
  11. data: {
  12. id: '',
  13. recordId: '',
  14. aftersaleId: '',
  15. pageTitle: '商家处理',
  16. refundState: '',
  17. days: '00',
  18. hours: '00',
  19. minutes: '00',
  20. seconds: '00',
  21. goods: {
  22. name: "",
  23. meta1: "",
  24. price: "",
  25. image: "",
  26. },
  27. refundDetail: {
  28. reason: "",
  29. amount: "",
  30. refundAmount: "",
  31. finishTime: "",
  32. applyTime: "",
  33. refundNo: "",
  34. updateTime: ""
  35. },
  36. // 协商历史标题和内容
  37. negotiateTitle: "",
  38. negotiateContent: "",
  39. // 拒绝状态处理截止时间
  40. handleEndTime: "",
  41. refundDestination: {
  42. type: '退回微信',
  43. account: '',
  44. },
  45. // 弹窗状态
  46. refundReasonPopupVisible: false,
  47. refundConfirmPopupVisible: false,
  48. refundProofPopupVisible: false,
  49. refundStatus: '',
  50. refundAction: '', // 'modify' 修改申请 | 'reApply' 再次申请
  51. refundMaxAmount: '0',
  52. refundProofImages: [] as string[],
  53. refundDesc: '',
  54. // 接口提交所需原始字段
  55. rawDetail: {} as any,
  56. },
  57. timer: null as any,
  58. onLoad(options: any) {
  59. if (options.id) {
  60. this.setData({ id: options.id, recordId: options.recordId || '' });
  61. this.loadDetail(options.id);
  62. }
  63. },
  64. onShow() {
  65. if (this.data.id && this.data.refundState) {
  66. this.loadDetail(this.data.id);
  67. }
  68. },
  69. async loadDetail(id: string) {
  70. wx.showLoading({ title: '加载中' });
  71. try {
  72. const res = await getAfterSaleDetailMethod(id);
  73. const detail = (res as any)?.data;
  74. if (!detail) return;
  75. const refundState = progressToState[String(detail.progress)] || 'processing';
  76. console.log(detail, "888")
  77. this.setData({
  78. rawDetail: detail,
  79. aftersaleId: detail.id || '',
  80. refundState,
  81. goods: {
  82. name: detail.conditioningProgramName || '',
  83. meta1: detail.convertDose ? `${detail.convertDose}${detail.convertUnit || '次'}` : '',
  84. price: String(detail.unitPrice || 0),
  85. image: detail.conditioningProgramPhoto || '',
  86. },
  87. refundDetail: {
  88. reason: detail.reason || '',
  89. amount: String(detail.totalPrice || 0),
  90. refundAmount: String(detail.refundAmount || 0),
  91. finishTime: detail.finishTime || '',
  92. applyTime: detail.applyTime || '',
  93. refundNo: detail.ref || '',
  94. updateTime: detail.updateTime || ''
  95. },
  96. negotiateTitle: detail.title || '',
  97. negotiateContent: (() => {
  98. const c = detail.content || '';
  99. try { if (c && JSON.parse(c)) return ''; } catch (e) { /* 不是JSON,保留原文 */ }
  100. return c;
  101. })(),
  102. handleEndTime: detail.handleEndTime || '',
  103. refundMaxAmount: String(detail.totalPrice || 0),
  104. refundProofImages: detail.voucherImgs || [],
  105. refundDesc: detail.remark || '',
  106. });
  107. this.updatePageTitle();
  108. if (refundState === 'processing' || refundState === 'rejected') {
  109. this.startCountdown();
  110. }
  111. } catch (error: any) {
  112. wx.showToast({ title: error.errMsg || '获取详情失败', icon: 'none' });
  113. }
  114. wx.hideLoading();
  115. },
  116. updatePageTitle() {
  117. let title = '商家处理';
  118. if (this.data.refundState === 'revoked') {
  119. title = '撤销申请';
  120. } else if (this.data.refundState === 'completed') {
  121. title = '退款完成';
  122. }
  123. this.setData({ pageTitle: title });
  124. },
  125. onUnload() {
  126. if (this.timer) {
  127. clearInterval(this.timer);
  128. }
  129. },
  130. startCountdown() {
  131. if (this.timer) clearInterval(this.timer);
  132. const setTime = (diff: number) => {
  133. if (diff <= 0) {
  134. this.setData({ days: '00', hours: '00', minutes: '00', seconds: '00' });
  135. if (this.timer) {
  136. clearInterval(this.timer);
  137. this.timer = null;
  138. }
  139. // 拒绝状态倒计时结束,清除截止时间,触发按钮切换
  140. if (this.data.refundState === 'rejected' && this.data.handleEndTime) {
  141. this.setData({ handleEndTime: '' });
  142. }
  143. return;
  144. }
  145. const d = Math.floor(diff / (1000 * 60 * 60 * 24));
  146. const h = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  147. const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
  148. const s = Math.floor((diff % (1000 * 60)) / 1000);
  149. this.setData({
  150. days: d < 10 ? '0' + d : String(d),
  151. hours: h < 10 ? '0' + h : String(h),
  152. minutes: m < 10 ? '0' + m : String(m),
  153. seconds: s < 10 ? '0' + s : String(s),
  154. });
  155. };
  156. if (this.data.refundState === 'rejected' && this.data.handleEndTime) {
  157. // rejected:倒计时到处理截止时间
  158. const target = new Date(this.data.handleEndTime.replace(/-/g, '/')).getTime();
  159. const update = () => setTime(target - new Date().getTime());
  160. update();
  161. this.timer = setInterval(update, 1000);
  162. } else {
  163. // processing:已过去的时间
  164. const applyTime = new Date(this.data.refundDetail.applyTime.replace(/-/g, '/')).getTime();
  165. const update = () => setTime(new Date().getTime() - applyTime);
  166. update();
  167. this.timer = setInterval(update, 1000);
  168. }
  169. },
  170. // 修改申请:打开确认弹窗
  171. onModify() {
  172. this.setData({ refundAction: 'modify', refundConfirmPopupVisible: true });
  173. },
  174. onRefundConfirmClose() {
  175. this.setData({ refundConfirmPopupVisible: false });
  176. },
  177. onChangeRefundStatus(e: any) {
  178. this.setData({ refundStatus: e.detail.status });
  179. },
  180. onOpenRefundReasonAgain() {
  181. this.setData({
  182. refundConfirmPopupVisible: false,
  183. refundReasonPopupVisible: true
  184. });
  185. },
  186. onOpenRefundProofEditor() {
  187. this.setData({
  188. refundConfirmPopupVisible: false,
  189. refundProofPopupVisible: true
  190. });
  191. },
  192. onRefundAmountConfirm(e: any) {
  193. this.setData({
  194. ['refundDetail.amount']: e.detail.amount
  195. });
  196. },
  197. async onSubmitRefundApply() {
  198. if (!this.data.refundProofImages.length && !this.data.refundDesc.trim()) {
  199. wx.showToast({ title: '请上传凭证或填写描述', icon: 'none' });
  200. return;
  201. }
  202. wx.showLoading({ title: '正在提交' });
  203. const { rawDetail, refundStatus, refundDetail, refundProofImages, refundDesc, recordId, id, aftersaleId, refundAction } = this.data;
  204. const params = {
  205. patientConditioningRecordId: recordId,
  206. patientConditioningProgramId: id,
  207. type: rawDetail.type,
  208. ...(rawDetail.sellType === '1' ? { receiptStatus: refundStatus || rawDetail.receiptStatus } : {}),
  209. reason: refundDetail.reason,
  210. applyAmount: Number(refundDetail.amount) || 0,
  211. voucherImgs: refundProofImages,
  212. remark: refundDesc,
  213. };
  214. try {
  215. if (refundAction === 'modify') {
  216. await updateAfterSaleMethod(Number(aftersaleId), params);
  217. } else {
  218. await applyAfterSaleMethod(params);
  219. }
  220. this.setData({ refundConfirmPopupVisible: false });
  221. wx.navigateTo({
  222. url: '/module/order/pages/refund-success/refund-success'
  223. });
  224. } catch (error: any) {
  225. wx.showToast({ title: error.errMsg || '提交失败', icon: 'none' });
  226. }
  227. wx.hideLoading();
  228. },
  229. onRefundReasonPopupClose() {
  230. this.setData({ refundReasonPopupVisible: false });
  231. },
  232. onRefundReasonNext(e: any) {
  233. this.setData({
  234. ['refundDetail.reason']: e.detail.reason,
  235. refundReasonPopupVisible: false,
  236. refundConfirmPopupVisible: true
  237. });
  238. },
  239. onRefundProofPopupClose() {
  240. this.setData({ refundProofPopupVisible: false, refundConfirmPopupVisible: true });
  241. },
  242. onRefundProofSubmit(e: any) {
  243. this.setData({
  244. refundProofImages: e.detail.images,
  245. refundDesc: e.detail.desc || '',
  246. refundProofPopupVisible: false,
  247. refundConfirmPopupVisible: true
  248. });
  249. },
  250. onViewHistory() {
  251. wx.navigateTo({
  252. url: `/module/order/pages/negotiation-history/negotiation-history?id=${this.data.aftersaleId}`
  253. });
  254. },
  255. onCopyRefundNo() {
  256. wx.setClipboardData({
  257. data: this.data.refundDetail.refundNo,
  258. success: () => {
  259. wx.showToast({ title: '已复制', icon: 'none' });
  260. }
  261. });
  262. },
  263. onCallService() {
  264. wx.makePhoneCall({
  265. phoneNumber: '400-123-4567',
  266. fail: () => { }
  267. });
  268. },
  269. onReApply() {
  270. const originalPrice = String(this.data.rawDetail.totalPrice || 0);
  271. this.setData({
  272. refundAction: 'reApply',
  273. refundDetail: { ...this.data.refundDetail, amount: originalPrice },
  274. refundMaxAmount: originalPrice,
  275. refundConfirmPopupVisible: true,
  276. });
  277. },
  278. onRevoke() {
  279. wx.showModal({
  280. title: '撤销退款申请',
  281. content: '撤销退款申请后,可以再次发起退款申请(总共可发起2次)',
  282. confirmText: '确定撤销',
  283. cancelText: '暂不撤销',
  284. success: async (res) => {
  285. if (res.confirm) {
  286. try {
  287. await cancelAfterSaleMethod(Number(this.data.aftersaleId));
  288. wx.showToast({ title: '已撤销', icon: 'success' });
  289. setTimeout(() => {
  290. wx.redirectTo({
  291. url: '/module/article/pages/success-page/success-page?title=撤销退款申请成功'
  292. });
  293. }, 1500);
  294. } catch (error: any) {
  295. wx.showToast({ title: error.errMsg || '撤销失败', icon: 'none' });
  296. }
  297. }
  298. }
  299. });
  300. }
  301. });