withdraw.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
  2. var Controller = {
  3. index: function () {
  4. // 初始化表格参数配置
  5. Table.api.init({
  6. extend: {
  7. index_url: 'withdraw/withdraw/index' + location.search,
  8. del_url: 'withdraw/withdraw/del',
  9. multi_url: 'withdraw/withdraw/multi',
  10. table: 'withdraw',
  11. }
  12. });
  13. // 初始化表格
  14. var table = $("#table");
  15. // 表格配置
  16. table.bootstrapTable({
  17. url: $.fn.bootstrapTable.defaults.extend.index_url,
  18. pk: 'id',
  19. sortName: 'id',
  20. sortOrder: 'desc',
  21. showToggle: false,
  22. showColumns: false,
  23. showExport: false,
  24. commonSearch: true,
  25. searchFormVisible: false,
  26. columns: [
  27. [
  28. {checkbox: true},
  29. {field: 'id', title: 'ID', width: 80, sortable: true},
  30. {
  31. field: 'user.username',
  32. title: __('User'),
  33. operate: 'LIKE',
  34. formatter: function (value, row, index) {
  35. // 显示用户头像和用户名
  36. var avatar = row.user && row.user.avatar ? row.user.avatar : '/assets/img/avatar.png';
  37. var username = row.user && row.user.username ? row.user.username : '游客';
  38. var userId = row.user_id || '';
  39. // 处理头像URL
  40. var avatarUrl = avatar;
  41. if (avatar && !avatar.startsWith('http') && !avatar.startsWith('//')) {
  42. avatarUrl = Fast.api.cdnurl ? Fast.api.cdnurl(avatar) : avatar;
  43. }
  44. return '<div style="display:flex;align-items:center;">' +
  45. '<img src="' + avatarUrl + '" style="width:40px;height:40px;border-radius:50%;margin-right:10px;" />' +
  46. '<div>' +
  47. '<div style="color:#337ab7;font-weight:bold;">' + username + '</div>' +
  48. '<div style="color:#999;font-size:12px;">ID: ' + userId + '</div>' +
  49. '</div>' +
  50. '</div>';
  51. }
  52. },
  53. {field: 'amount', title: '提现金额', width: 100, formatter: function(value, row, index) {
  54. return '¥' + parseFloat(value).toFixed(2);
  55. }},
  56. {field: 'paid_fee', title: '实际到账', width: 100, formatter: function(value, row, index) {
  57. return '¥' + parseFloat(value).toFixed(2);
  58. }},
  59. {field: 'charge_fee', title: '手续费', width: 80, formatter: function(value, row, index) {
  60. return '¥' + parseFloat(value).toFixed(2);
  61. }},
  62. {field: 'charge_rate_format', title: '费率', width: 60},
  63. {field: 'withdraw_type_text', title: '提现方式', width: 120, formatter: function(value, row, index) {
  64. var iconMap = {
  65. 'wechat': '/assets/img/wechat.png',
  66. 'alipay': '/assets/img/alipay.png',
  67. 'bank': '/assets/img/bank.png'
  68. };
  69. var icon = iconMap[row.withdraw_type] || '/assets/img/bank.png';
  70. return '<div style="display:flex;align-items:center;">' +
  71. '<img src="' + icon + '" style="width:20px;height:20px;margin-right:8px;" />' +
  72. '<span>' + value + '</span>' +
  73. '</div>';
  74. }},
  75. {field: 'withdraw_sn', title: '商户单号', width: 200},
  76. {field: 'withdraw_info', title: '打款信息', width: 250, formatter: function(value, row, index) {
  77. if (!value) return '-';
  78. var html = '';
  79. $.each(value, function(key, val) {
  80. html += '<div><strong>' + key + ':</strong> ' + val + '</div>';
  81. });
  82. return html;
  83. }},
  84. {field: 'wechat_transfer_state_text', title: '微信转账状态', width: 120, visible: false},
  85. {field: 'createtime', title: '申请时间', width: 160, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
  86. {field: 'updatetime', title: '更新时间', width: 160, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
  87. {field: 'status', title: '状态', width: 80, searchList: {"-1":"已拒绝","0":"待审核","1":"处理中","2":"已处理"}, custom: {"all":"全部"}, formatter: function(value, row, index) {
  88. var statusClass = Controller.getStatusClass(value);
  89. var statusText = Controller.getStatusText(value);
  90. return '<span class="label label-' + statusClass + '">' + statusText + '</span>';
  91. }},
  92. {
  93. field: 'operate',
  94. title: __('Operate'),
  95. width: 200,
  96. table: table,
  97. events: Table.api.events.operate,
  98. buttons: [
  99. {
  100. name: 'handle',
  101. title: '处理',
  102. classname: 'btn btn-xs btn-primary btn-dialog',
  103. icon: 'fa fa-cog',
  104. url: 'withdraw/withdraw/handle',
  105. visible: function(row) {
  106. return row.status == 0 || row.status == 1;
  107. }
  108. },
  109. {
  110. name: 'log',
  111. title: '日志',
  112. classname: 'btn btn-xs btn-info btn-dialog',
  113. icon: 'fa fa-list-alt',
  114. url: 'withdraw/withdraw/log'
  115. },
  116. {
  117. name: 'check_wechat',
  118. title: '检查微信状态',
  119. classname: 'btn btn-xs btn-warning btn-ajax',
  120. icon: 'fa fa-refresh',
  121. url: 'withdraw/withdraw/checkWechatTransferResult',
  122. confirm: '确认要检查微信转账状态吗?',
  123. success: function(data, ret) {
  124. table.bootstrapTable('refresh');
  125. Layer.msg(ret.msg);
  126. },
  127. visible: function(row) {
  128. return row.withdraw_type == 'wechat' && row.status == 1;
  129. }
  130. }
  131. ],
  132. formatter: Table.api.formatter.operate
  133. }
  134. ]
  135. ]
  136. });
  137. // 为表格绑定事件
  138. Table.api.bindevent(table);
  139. // 批量处理操作绑定
  140. $(document).on("click", ".btn-handle-agree", function () {
  141. Controller.handleBatch('agree');
  142. });
  143. $(document).on("click", ".btn-handle-withdraw", function () {
  144. Controller.handleBatch('withdraw');
  145. });
  146. $(document).on("click", ".btn-handle-agree-withdraw", function () {
  147. Controller.handleBatch('agree_and_withdraw');
  148. });
  149. $(document).on("click", ".btn-handle-refuse", function () {
  150. var ids = Table.api.selectedids(table);
  151. if (ids.length === 0) {
  152. Layer.msg("请先选择要操作的记录");
  153. return false;
  154. }
  155. Fast.api.open("withdraw/withdraw/handle/ids/" + ids.join(","), "拒绝提现", {
  156. callback: function() {
  157. table.bootstrapTable('refresh');
  158. }
  159. });
  160. });
  161. $(document).on("click", ".btn-handle-cancel", function () {
  162. Controller.handleBatch('cancel');
  163. });
  164. $(document).on("click", ".btn-handle-refund", function () {
  165. Controller.handleBatch('refund_commission');
  166. });
  167. },
  168. handle: function () {
  169. // 处理页面的表单提交
  170. Form.api.bindevent($("form[role=form]"));
  171. // 根据操作类型显示隐藏拒绝理由
  172. $('#action').on('change', function() {
  173. var action = $(this).val();
  174. if (action === 'refuse') {
  175. $('.refuse-reason').show();
  176. $('#refuse_msg').attr('data-rule-required', 'true');
  177. } else {
  178. $('.refuse-reason').hide();
  179. $('#refuse_msg').removeAttr('data-rule-required');
  180. }
  181. });
  182. // 表单提交前验证
  183. var isSubmitting = false; // 防止重复提交
  184. $('#handle-form').on('submit', function(e) {
  185. e.preventDefault(); // 阻止默认提交
  186. if (isSubmitting) {
  187. return false;
  188. }
  189. var action = $('#action').val();
  190. if (!action) {
  191. Layer.msg('请选择处理操作');
  192. return false;
  193. }
  194. if (action === 'refuse') {
  195. var refuseMsg = $('#refuse_msg').val().trim();
  196. if (!refuseMsg) {
  197. Layer.msg('请输入拒绝理由');
  198. return false;
  199. }
  200. }
  201. // 显示确认对话框
  202. var actionText = Controller.getActionText(action);
  203. var form = $(this);
  204. Layer.confirm('确认要' + actionText + '这笔提现申请吗?', function(index) {
  205. isSubmitting = true;
  206. Layer.close(index);
  207. // 使用 FastAdmin 的 ajax 提交
  208. Fast.api.ajax({
  209. url: form.attr('action') || 'withdraw/withdraw/handle',
  210. data: form.serialize(),
  211. type: 'POST'
  212. }, function(data, ret) {
  213. isSubmitting = false;
  214. parent.Layer.msg(ret.msg, {icon: 1});
  215. setTimeout(function() {
  216. var index = parent.Layer.getFrameIndex(window.name);
  217. parent.Layer.close(index);
  218. parent.$(".btn-refresh").trigger("click");
  219. }, 1000);
  220. }, function(data, ret) {
  221. isSubmitting = false;
  222. Layer.msg(ret.msg);
  223. });
  224. });
  225. return false;
  226. });
  227. },
  228. log: function () {
  229. // 日志页面使用服务器端渲染,无需 JavaScript 初始化
  230. // 如果需要可以在这里添加其他交互功能
  231. },
  232. // 批量处理方法
  233. handleBatch: function(action) {
  234. var table = $("#table");
  235. var ids = Table.api.selectedids(table);
  236. if (ids.length === 0) {
  237. Layer.msg("请先选择要操作的记录");
  238. return false;
  239. }
  240. var actionText = '';
  241. switch(action) {
  242. case 'agree': actionText = '同意'; break;
  243. case 'withdraw': actionText = '打款'; break;
  244. case 'agree_and_withdraw': actionText = '同意并打款'; break;
  245. case 'cancel': actionText = '撤销'; break;
  246. case 'refund_commission': actionText = '退回佣金'; break;
  247. }
  248. Layer.confirm("确认要" + actionText + "选中的提现申请吗?", function(index) {
  249. Fast.api.ajax({
  250. url: 'withdraw/withdraw/handle',
  251. data: {ids: ids, action: action}
  252. }, function(data, ret) {
  253. table.bootstrapTable('refresh');
  254. Layer.close(index);
  255. });
  256. });
  257. },
  258. // 获取状态样式类名
  259. getStatusClass: function(status) {
  260. var classes = {
  261. '-1': 'danger', // 已拒绝
  262. '0': 'info', // 待审核
  263. '1': 'warning', // 处理中
  264. '2': 'success' // 已处理
  265. };
  266. return classes[status] || 'default';
  267. },
  268. // 获取状态文本
  269. getStatusText: function(status) {
  270. var statusTexts = {
  271. '-1': '已拒绝',
  272. '0': '待审核',
  273. '1': '处理中',
  274. '2': '已处理'
  275. };
  276. return statusTexts[status] || '未知状态';
  277. },
  278. // 获取操作文本
  279. getActionText: function(action) {
  280. var actionTexts = {
  281. 'agree': '同意',
  282. 'withdraw': '打款',
  283. 'agree_and_withdraw': '同意并打款',
  284. 'refuse': '拒绝',
  285. 'cancel': '撤销',
  286. 'refund_commission': '退回佣金'
  287. };
  288. return actionTexts[action] || '处理';
  289. },
  290. api: {
  291. // 解析Config中的JSON字符串的辅助函数
  292. parseConfigJson: function(configKey, defaultValue) {
  293. var configValue = Config[configKey] || defaultValue || {};
  294. // 如果是字符串,尝试解析JSON
  295. if (typeof configValue === 'string') {
  296. try {
  297. return JSON.parse(configValue);
  298. } catch (e) {
  299. return defaultValue || {};
  300. }
  301. }
  302. return configValue;
  303. },
  304. bindevent: function () {
  305. Form.api.bindevent($("form[role=form]"));
  306. }
  307. }
  308. };
  309. return Controller;
  310. });