Withdrawal.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <?php
  2. namespace app\admin\controller\order;
  3. use app\common\controller\Backend;
  4. use think\facade\Db;
  5. class Withdrawal extends Backend
  6. {
  7. protected array $noNeedLogin = ['*'];
  8. /**
  9. * 提现申请列表
  10. * @return void
  11. */
  12. public function index(): void
  13. {
  14. $where = [];
  15. // 申请人搜索
  16. if (!empty($this->request->get('applicant_name'))) {
  17. $applicantName = $this->request->get('applicant_name');
  18. $where[] = ['u.name', 'like', '%' . $applicantName . '%'];
  19. }
  20. // 状态筛选
  21. if ($this->request->get('status') !== '' && $this->request->get('status') !== null) {
  22. $where['wr.status'] = $this->request->get('status');
  23. }
  24. // 提现方式筛选
  25. if (!empty($this->request->get('withdrawal_method'))) {
  26. $where['wr.withdrawal_method'] = $this->request->get('withdrawal_method');
  27. }
  28. //查询时间范围
  29. $star_time = $this->request->get('star_time');
  30. $end_time = $this->request->get('end_time');
  31. if (!empty($star_time) && !empty($end_time)) {
  32. $where[] = ['wr.create_time', 'between', [$star_time, $end_time], 'AND'];
  33. }
  34. // 排序
  35. $order = [];
  36. if (!empty($this->request->get('order'))) {
  37. $order_a = $this->request->get('order');
  38. $order_a = explode(',', $order_a);
  39. $order[$order_a[0]] = $order_a[1];
  40. } else {
  41. $order['wr.create_time'] = 'desc';
  42. }
  43. // 分页
  44. $page = $this->request->get('page', 1);
  45. $limit = $this->request->get('limit', 20);
  46. // 查询数据
  47. $withdrawalList = Db::name('withdrawal_record')
  48. ->alias('wr')
  49. ->leftJoin('user_on u', 'wr.user_id = u.id')
  50. ->field('
  51. wr.id,
  52. u.name,
  53. wr.amount,
  54. wr.current_balance,
  55. wr.withdrawal_method,
  56. wr.status,
  57. wr.create_time,
  58. wr.audit_time,
  59. wr.audit_remark,
  60. wr.user_id,
  61. wr.withdrawal_no
  62. ')
  63. ->where($where)
  64. ->order($order)
  65. ->paginate([
  66. 'list_rows' => $limit,
  67. 'page' => $page
  68. ]);
  69. // 转换字段格式
  70. $list = $withdrawalList->items();
  71. foreach ($list as &$item) {
  72. // 提现方式转换
  73. $item['withdrawal_method'] = $this->getWithdrawalMethodText($item['withdrawal_method']);
  74. // 状态转换
  75. $item['status_text'] = $this->getStatusText($item['status']);
  76. // 格式化金额
  77. $item['amount'] = number_format($item['amount'], 2);
  78. $item['current_balance'] = number_format($item['current_balance'], 2);
  79. // 格式化时间
  80. if ($item['create_time']) {
  81. $item['create_time'] = date('Y-m-d H:i:s', strtotime($item['create_time']));
  82. }
  83. if ($item['audit_time']) {
  84. $item['audit_time'] = date('Y-m-d H:i:s', strtotime($item['audit_time']));
  85. }
  86. }
  87. $this->success('查询成功', [
  88. 'list' => $list,
  89. 'total' => $withdrawalList->total()
  90. ]);
  91. }
  92. /**
  93. * 审核通过
  94. * @return void
  95. */
  96. public function approve(): void
  97. {
  98. $id = $this->request->post('id');
  99. $auditRemark = $this->request->post('audit_remark', '');
  100. if (empty($id)) {
  101. $this->error(__('参数错误'));
  102. }
  103. try {
  104. Db::startTrans();
  105. // 获取提现记录
  106. $withdrawalRecord = Db::name('withdrawal_record')
  107. ->where('id', $id)
  108. ->lock(true)
  109. ->find();
  110. if (!$withdrawalRecord) {
  111. throw new \Exception('提现记录不存在');
  112. }
  113. if ($withdrawalRecord['status'] != 0) {
  114. throw new \Exception('只有待审核的记录才能审核');
  115. }
  116. // 检查用户佣金是否足够
  117. $userCommission = Db::name('user_commission')
  118. ->where('user_id', $withdrawalRecord['user_id'])
  119. ->lock(true)
  120. ->find();
  121. if (!$userCommission || $userCommission['current_commission'] < $withdrawalRecord['amount']) {
  122. throw new \Exception('用户佣金不足');
  123. }
  124. // 更新提现记录状态
  125. $updateData = [
  126. 'status' => 1, // 审核通过
  127. 'auditor_id' => $this->auth->id ?? 0,
  128. 'audit_time' => date('Y-m-d H:i:s'),
  129. 'audit_remark' => $auditRemark,
  130. 'balance_after' => Db::raw('current_balance - ' . $withdrawalRecord['amount']),
  131. 'update_time' => date('Y-m-d H:i:s')
  132. ];
  133. $result = Db::name('withdrawal_record')
  134. ->where('id', $id)
  135. ->update($updateData);
  136. if (!$result) {
  137. throw new \Exception('更新提现记录失败');
  138. }
  139. // 更新用户佣金(扣除已提现金额)
  140. Db::name('user_commission')
  141. ->where('user_id', $withdrawalRecord['user_id'])
  142. ->update([
  143. 'current_commission' => Db::raw('current_commission - ' . $withdrawalRecord['amount']),
  144. 'update_time' => date('Y-m-d H:i:s')
  145. ]);
  146. Db::commit();
  147. } catch (\Exception $e) {
  148. Db::rollback();
  149. $this->error('审核失败: ' . $e->getMessage());
  150. }
  151. $this->success('审核通过');
  152. }
  153. /**
  154. * 审核拒绝
  155. * @return void
  156. */
  157. public function reject(): void
  158. {
  159. $id = $this->request->post('id');
  160. $auditRemark = $this->request->post('audit_remark', '');
  161. if (empty($id)) {
  162. $this->error(__('参数错误'));
  163. }
  164. if (empty($auditRemark)) {
  165. $this->error(__('请填写拒绝原因'));
  166. }
  167. try {
  168. // 获取提现记录
  169. $withdrawalRecord = Db::name('withdrawal_record')
  170. ->where('id', $id)
  171. ->find();
  172. if (!$withdrawalRecord) {
  173. throw new \Exception ('提现记录不存在');
  174. }
  175. if ($withdrawalRecord['status'] != 0) {
  176. throw new \Exception ('只有待审核的记录才能审核');
  177. }
  178. // 更新提现记录状态
  179. $result = Db::name('withdrawal_record')
  180. ->where('id', $id)
  181. ->update([
  182. 'status' => 2, // 审核拒绝
  183. 'auditor_id' => $this->auth->id ?? 0,
  184. 'audit_time' => date('Y-m-d H:i:s'),
  185. 'audit_remark' => $auditRemark,
  186. 'update_time' => date('Y-m-d H:i:s')
  187. ]);
  188. } catch (\Exception $e) {
  189. $this->error('操作失败: ' . $e->getMessage());
  190. }
  191. if ($result) {
  192. $this->success('审核拒绝成功');
  193. } else {
  194. $this->error(__('审核拒绝失败'));
  195. }
  196. }
  197. /**
  198. * 获取提现方式文本
  199. * @param string $method
  200. * @return string
  201. */
  202. private function getWithdrawalMethodText(string $method): string
  203. {
  204. $map = [
  205. 'wechat' => '微信',
  206. 'alipay' => '支付宝',
  207. 'bank' => '银行卡'
  208. ];
  209. return $map[$method] ?? $method;
  210. }
  211. /**
  212. * 获取状态文本
  213. * @param int $status
  214. * @return string
  215. */
  216. private function getStatusText(int $status): string
  217. {
  218. $map = [
  219. 0 => '待审核',
  220. 1 => '审核通过',
  221. 2 => '审核拒绝',
  222. 3 => '已打款',
  223. 4 => '打款失败'
  224. ];
  225. return $map[$status] ?? '未知';
  226. }
  227. /**
  228. * 获取提现状态选项
  229. * @return void
  230. */
  231. public function statusOptions(): void
  232. {
  233. $options = [
  234. ['value' => 0, 'label' => '待审核'],
  235. ['value' => 1, 'label' => '审核通过'],
  236. ['value' => 2, 'label' => '审核拒绝'],
  237. ['value' => 3, 'label' => '已打款'],
  238. ['value' => 4, 'label' => '打款失败']
  239. ];
  240. $this->success('获取成功', $options);
  241. }
  242. /**
  243. * 获取提现方式选项
  244. * @return void
  245. */
  246. public function methodOptions(): void
  247. {
  248. $options = [
  249. ['value' => 'wechat', 'label' => '微信'],
  250. ['value' => 'alipay', 'label' => '支付宝'],
  251. ['value' => 'bank', 'label' => '银行卡']
  252. ];
  253. $this->success('获取成功', $options);
  254. }
  255. /**
  256. * 提现统计
  257. * @return void
  258. */
  259. public function statistics(): void
  260. {
  261. // 总提现申请数
  262. $totalCount = Db::name('withdrawal_record')->count();
  263. // 待审核数
  264. $pendingCount = Db::name('withdrawal_record')
  265. ->where('status', 0)
  266. ->count();
  267. // 已通过数
  268. $approvedCount = Db::name('withdrawal_record')
  269. ->where('status', 1)
  270. ->count();
  271. // 已拒绝数
  272. $rejectedCount = Db::name('withdrawal_record')
  273. ->where('status', 2)
  274. ->count();
  275. // 总提现金额
  276. $totalAmount = Db::name('withdrawal_record')
  277. ->where('status', 1) // 只计算审核通过的
  278. ->sum('amount');
  279. // 今日提现统计
  280. $todayStart = date('Y-m-d 00:00:00');
  281. $todayEnd = date('Y-m-d 23:59:59');
  282. $todayCount = Db::name('withdrawal_record')
  283. ->whereBetween('create_time', [$todayStart, $todayEnd])
  284. ->count();
  285. $todayAmount = Db::name('withdrawal_record')
  286. ->whereBetween('create_time', [$todayStart, $todayEnd])
  287. ->where('status', 1)
  288. ->sum('amount');
  289. $stats = [
  290. 'total_count' => $totalCount,
  291. 'pending_count' => $pendingCount,
  292. 'approved_count' => $approvedCount,
  293. 'rejected_count' => $rejectedCount,
  294. 'total_amount' => number_format($totalAmount ?? 0, 2),
  295. 'today_count' => $todayCount,
  296. 'today_amount' => number_format($todayAmount ?? 0, 2)
  297. ];
  298. $this->success('获取成功', $stats);
  299. }
  300. }