|
@@ -0,0 +1,344 @@
|
|
|
|
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
|
|
|
+
|
|
|
|
+ var Controller = {
|
|
|
|
+ index: function () {
|
|
|
|
+ // 初始化表格参数配置
|
|
|
|
+ Table.api.init({
|
|
|
|
+ extend: {
|
|
|
|
+ index_url: 'withdraw/withdraw/index' + location.search,
|
|
|
|
+ del_url: 'withdraw/withdraw/del',
|
|
|
|
+ multi_url: 'withdraw/withdraw/multi',
|
|
|
|
+ table: 'withdraw',
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 初始化表格
|
|
|
|
+ var table = $("#table");
|
|
|
|
+
|
|
|
|
+ // 表格配置
|
|
|
|
+ table.bootstrapTable({
|
|
|
|
+ url: $.fn.bootstrapTable.defaults.extend.index_url,
|
|
|
|
+ pk: 'id',
|
|
|
|
+ sortName: 'id',
|
|
|
|
+ sortOrder: 'desc',
|
|
|
|
+ showToggle: false,
|
|
|
|
+ showColumns: false,
|
|
|
|
+ showExport: false,
|
|
|
|
+ commonSearch: true,
|
|
|
|
+ searchFormVisible: false,
|
|
|
|
+ columns: [
|
|
|
|
+ [
|
|
|
|
+ {checkbox: true},
|
|
|
|
+ {field: 'id', title: 'ID', width: 80, sortable: true},
|
|
|
|
+ {
|
|
|
|
+ field: 'user.username',
|
|
|
|
+ title: __('User'),
|
|
|
|
+ operate: 'LIKE',
|
|
|
|
+ formatter: function (value, row, index) {
|
|
|
|
+ // 显示用户头像和用户名
|
|
|
|
+ var avatar = row.user && row.user.avatar ? row.user.avatar : '/assets/img/avatar.png';
|
|
|
|
+ var username = row.user && row.user.username ? row.user.username : '游客';
|
|
|
|
+ var userId = row.user_id || '';
|
|
|
|
+
|
|
|
|
+ // 处理头像URL
|
|
|
|
+ var avatarUrl = avatar;
|
|
|
|
+ if (avatar && !avatar.startsWith('http') && !avatar.startsWith('//')) {
|
|
|
|
+ avatarUrl = Fast.api.cdnurl ? Fast.api.cdnurl(avatar) : avatar;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return '<div style="display:flex;align-items:center;">' +
|
|
|
|
+ '<img src="' + avatarUrl + '" style="width:40px;height:40px;border-radius:50%;margin-right:10px;" />' +
|
|
|
|
+ '<div>' +
|
|
|
|
+ '<div style="color:#337ab7;font-weight:bold;">' + username + '</div>' +
|
|
|
|
+ '<div style="color:#999;font-size:12px;">ID: ' + userId + '</div>' +
|
|
|
|
+ '</div>' +
|
|
|
|
+ '</div>';
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {field: 'amount', title: '提现金额', width: 100, formatter: function(value, row, index) {
|
|
|
|
+ return '¥' + parseFloat(value).toFixed(2);
|
|
|
|
+ }},
|
|
|
|
+ {field: 'paid_fee', title: '实际到账', width: 100, formatter: function(value, row, index) {
|
|
|
|
+ return '¥' + parseFloat(value).toFixed(2);
|
|
|
|
+ }},
|
|
|
|
+ {field: 'charge_fee', title: '手续费', width: 80, formatter: function(value, row, index) {
|
|
|
|
+ return '¥' + parseFloat(value).toFixed(2);
|
|
|
|
+ }},
|
|
|
|
+ {field: 'charge_rate_format', title: '费率', width: 60},
|
|
|
|
+ {field: 'withdraw_type_text', title: '提现方式', width: 120, formatter: function(value, row, index) {
|
|
|
|
+ var iconMap = {
|
|
|
|
+ 'wechat': '/assets/img/wechat.png',
|
|
|
|
+ 'alipay': '/assets/img/alipay.png',
|
|
|
|
+ 'bank': '/assets/img/bank.png'
|
|
|
|
+ };
|
|
|
|
+ var icon = iconMap[row.withdraw_type] || '/assets/img/bank.png';
|
|
|
|
+ return '<div style="display:flex;align-items:center;">' +
|
|
|
|
+ '<img src="' + icon + '" style="width:20px;height:20px;margin-right:8px;" />' +
|
|
|
|
+ '<span>' + value + '</span>' +
|
|
|
|
+ '</div>';
|
|
|
|
+ }},
|
|
|
|
+ {field: 'withdraw_sn', title: '商户单号', width: 200},
|
|
|
|
+ {field: 'withdraw_info', title: '打款信息', width: 250, formatter: function(value, row, index) {
|
|
|
|
+ if (!value) return '-';
|
|
|
|
+ var html = '';
|
|
|
|
+ $.each(value, function(key, val) {
|
|
|
|
+ html += '<div><strong>' + key + ':</strong> ' + val + '</div>';
|
|
|
|
+ });
|
|
|
|
+ return html;
|
|
|
|
+ }},
|
|
|
|
+ {field: 'wechat_transfer_state_text', title: '微信转账状态', width: 120, visible: false},
|
|
|
|
+ {field: 'createtime', title: '申请时间', width: 160, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
|
|
|
|
+ {field: 'updatetime', title: '更新时间', width: 160, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
|
|
|
|
+ {field: 'status', title: '状态', width: 80, searchList: {"-1":"已拒绝","0":"待审核","1":"处理中","2":"已处理"}, custom: {"all":"全部"}, formatter: function(value, row, index) {
|
|
|
|
+ var statusClass = Controller.getStatusClass(value);
|
|
|
|
+ var statusText = Controller.getStatusText(value);
|
|
|
|
+ return '<span class="label label-' + statusClass + '">' + statusText + '</span>';
|
|
|
|
+ }},
|
|
|
|
+ {
|
|
|
|
+ field: 'operate',
|
|
|
|
+ title: __('Operate'),
|
|
|
|
+ width: 200,
|
|
|
|
+ table: table,
|
|
|
|
+ events: Table.api.events.operate,
|
|
|
|
+ buttons: [
|
|
|
|
+ {
|
|
|
|
+ name: 'handle',
|
|
|
|
+ title: '处理',
|
|
|
|
+ classname: 'btn btn-xs btn-primary btn-dialog',
|
|
|
|
+ icon: 'fa fa-cog',
|
|
|
|
+ url: 'withdraw/withdraw/handle',
|
|
|
|
+ visible: function(row) {
|
|
|
|
+ return row.status == 0 || row.status == 1;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: 'log',
|
|
|
|
+ title: '日志',
|
|
|
|
+ classname: 'btn btn-xs btn-info btn-dialog',
|
|
|
|
+ icon: 'fa fa-list-alt',
|
|
|
|
+ url: 'withdraw/withdraw/log'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: 'check_wechat',
|
|
|
|
+ title: '检查微信状态',
|
|
|
|
+ classname: 'btn btn-xs btn-warning btn-ajax',
|
|
|
|
+ icon: 'fa fa-refresh',
|
|
|
|
+ url: 'withdraw/withdraw/checkWechatTransferResult',
|
|
|
|
+ confirm: '确认要检查微信转账状态吗?',
|
|
|
|
+ success: function(data, ret) {
|
|
|
|
+ table.bootstrapTable('refresh');
|
|
|
|
+ Layer.msg(ret.msg);
|
|
|
|
+ },
|
|
|
|
+ visible: function(row) {
|
|
|
|
+ return row.withdraw_type == 'wechat' && row.status == 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ],
|
|
|
|
+ formatter: Table.api.formatter.operate
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ ]
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 为表格绑定事件
|
|
|
|
+ Table.api.bindevent(table);
|
|
|
|
+
|
|
|
|
+ // 批量处理操作绑定
|
|
|
|
+ $(document).on("click", ".btn-handle-agree", function () {
|
|
|
|
+ Controller.handleBatch('agree');
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on("click", ".btn-handle-withdraw", function () {
|
|
|
|
+ Controller.handleBatch('withdraw');
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on("click", ".btn-handle-agree-withdraw", function () {
|
|
|
|
+ Controller.handleBatch('agree_and_withdraw');
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on("click", ".btn-handle-refuse", function () {
|
|
|
|
+ var ids = Table.api.selectedids(table);
|
|
|
|
+ if (ids.length === 0) {
|
|
|
|
+ Layer.msg("请先选择要操作的记录");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ Fast.api.open("withdraw/withdraw/handle/ids/" + ids.join(","), "拒绝提现", {
|
|
|
|
+ callback: function() {
|
|
|
|
+ table.bootstrapTable('refresh');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on("click", ".btn-handle-cancel", function () {
|
|
|
|
+ Controller.handleBatch('cancel');
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on("click", ".btn-handle-refund", function () {
|
|
|
|
+ Controller.handleBatch('refund_commission');
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ handle: function () {
|
|
|
|
+ // 处理页面的表单提交
|
|
|
|
+ Form.api.bindevent($("form[role=form]"));
|
|
|
|
+
|
|
|
|
+ // 根据操作类型显示隐藏拒绝理由
|
|
|
|
+ $('#action').on('change', function() {
|
|
|
|
+ var action = $(this).val();
|
|
|
|
+ if (action === 'refuse') {
|
|
|
|
+ $('.refuse-reason').show();
|
|
|
|
+ $('#refuse_msg').attr('data-rule-required', 'true');
|
|
|
|
+ } else {
|
|
|
|
+ $('.refuse-reason').hide();
|
|
|
|
+ $('#refuse_msg').removeAttr('data-rule-required');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 表单提交前验证
|
|
|
|
+ var isSubmitting = false; // 防止重复提交
|
|
|
|
+
|
|
|
|
+ $('#handle-form').on('submit', function(e) {
|
|
|
|
+ e.preventDefault(); // 阻止默认提交
|
|
|
|
+
|
|
|
|
+ if (isSubmitting) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var action = $('#action').val();
|
|
|
|
+ if (!action) {
|
|
|
|
+ Layer.msg('请选择处理操作');
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (action === 'refuse') {
|
|
|
|
+ var refuseMsg = $('#refuse_msg').val().trim();
|
|
|
|
+ if (!refuseMsg) {
|
|
|
|
+ Layer.msg('请输入拒绝理由');
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 显示确认对话框
|
|
|
|
+ var actionText = Controller.getActionText(action);
|
|
|
|
+ var form = $(this);
|
|
|
|
+
|
|
|
|
+ Layer.confirm('确认要' + actionText + '这笔提现申请吗?', function(index) {
|
|
|
|
+ isSubmitting = true;
|
|
|
|
+ Layer.close(index);
|
|
|
|
+
|
|
|
|
+ // 使用 FastAdmin 的 ajax 提交
|
|
|
|
+ Fast.api.ajax({
|
|
|
|
+ url: form.attr('action') || 'withdraw/withdraw/handle',
|
|
|
|
+ data: form.serialize(),
|
|
|
|
+ type: 'POST'
|
|
|
|
+ }, function(data, ret) {
|
|
|
|
+ isSubmitting = false;
|
|
|
|
+ parent.Layer.msg(ret.msg, {icon: 1});
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ var index = parent.Layer.getFrameIndex(window.name);
|
|
|
|
+ parent.Layer.close(index);
|
|
|
|
+ parent.$(".btn-refresh").trigger("click");
|
|
|
|
+ }, 1000);
|
|
|
|
+ }, function(data, ret) {
|
|
|
|
+ isSubmitting = false;
|
|
|
|
+ Layer.msg(ret.msg);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ log: function () {
|
|
|
|
+ // 日志页面使用服务器端渲染,无需 JavaScript 初始化
|
|
|
|
+ // 如果需要可以在这里添加其他交互功能
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 批量处理方法
|
|
|
|
+ handleBatch: function(action) {
|
|
|
|
+ var table = $("#table");
|
|
|
|
+ var ids = Table.api.selectedids(table);
|
|
|
|
+ if (ids.length === 0) {
|
|
|
|
+ Layer.msg("请先选择要操作的记录");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var actionText = '';
|
|
|
|
+ switch(action) {
|
|
|
|
+ case 'agree': actionText = '同意'; break;
|
|
|
|
+ case 'withdraw': actionText = '打款'; break;
|
|
|
|
+ case 'agree_and_withdraw': actionText = '同意并打款'; break;
|
|
|
|
+ case 'cancel': actionText = '撤销'; break;
|
|
|
|
+ case 'refund_commission': actionText = '退回佣金'; break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Layer.confirm("确认要" + actionText + "选中的提现申请吗?", function(index) {
|
|
|
|
+ Fast.api.ajax({
|
|
|
|
+ url: 'withdraw/withdraw/handle',
|
|
|
|
+ data: {ids: ids, action: action}
|
|
|
|
+ }, function(data, ret) {
|
|
|
|
+ table.bootstrapTable('refresh');
|
|
|
|
+ Layer.close(index);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 获取状态样式类名
|
|
|
|
+ getStatusClass: function(status) {
|
|
|
|
+ var classes = {
|
|
|
|
+ '-1': 'danger', // 已拒绝
|
|
|
|
+ '0': 'info', // 待审核
|
|
|
|
+ '1': 'warning', // 处理中
|
|
|
|
+ '2': 'success' // 已处理
|
|
|
|
+ };
|
|
|
|
+ return classes[status] || 'default';
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 获取状态文本
|
|
|
|
+ getStatusText: function(status) {
|
|
|
|
+ var statusTexts = {
|
|
|
|
+ '-1': '已拒绝',
|
|
|
|
+ '0': '待审核',
|
|
|
|
+ '1': '处理中',
|
|
|
|
+ '2': '已处理'
|
|
|
|
+ };
|
|
|
|
+ return statusTexts[status] || '未知状态';
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 获取操作文本
|
|
|
|
+ getActionText: function(action) {
|
|
|
|
+ var actionTexts = {
|
|
|
|
+ 'agree': '同意',
|
|
|
|
+ 'withdraw': '打款',
|
|
|
|
+ 'agree_and_withdraw': '同意并打款',
|
|
|
|
+ 'refuse': '拒绝',
|
|
|
|
+ 'cancel': '撤销',
|
|
|
|
+ 'refund_commission': '退回佣金'
|
|
|
|
+ };
|
|
|
|
+ return actionTexts[action] || '处理';
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ api: {
|
|
|
|
+ // 解析Config中的JSON字符串的辅助函数
|
|
|
|
+ parseConfigJson: function(configKey, defaultValue) {
|
|
|
|
+ var configValue = Config[configKey] || defaultValue || {};
|
|
|
|
+
|
|
|
|
+ // 如果是字符串,尝试解析JSON
|
|
|
|
+ if (typeof configValue === 'string') {
|
|
|
|
+ try {
|
|
|
|
+ return JSON.parse(configValue);
|
|
|
|
+ } catch (e) {
|
|
|
|
+ return defaultValue || {};
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return configValue;
|
|
|
|
+ },
|
|
|
|
+ bindevent: function () {
|
|
|
|
+ Form.api.bindevent($("form[role=form]"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ return Controller;
|
|
|
|
+});
|