model = new \app\admin\model\FcUserExt; } /** * 会员列表(关联 fa_user 展示昵称 / 手机号 / 账户余额) * * 说明:余额money 存放在核心表 fa_user,本表只有业务扩展字段, * 因此列表需要 JOIN fa_user 才能看出「谁有多少余额」。 * 注意 TP5.0 的 count() 会清空查询条件,必须分别构建查询。 */ public function index() { if ($this->request->isAjax()) { list($where, $sort, $order, $offset, $limit) = $this->buildparams(); $total = $this->model->alias('e') ->join('user u', 'u.id = e.user_id', 'LEFT') ->where($where) ->count(); $list = $this->model->alias('e') ->join('user u', 'u.id = e.user_id', 'LEFT') ->where($where) ->field('e.*, u.nickname, u.mobile, u.money') ->order($sort, $order) ->limit($offset, $limit) ->select(); return json(['total' => $total, 'rows' => $list]); } return $this->view->fetch(); } /** * 余额充值(给选中用户增加账户余额) * * POST /s.php/fc/userext/recharge * 入参:{ ids: '1001,1002' , amount: 100, remark?: '备注' } * * 说明: * 余额存放在核心表 fa_user.money,本表(fc_user_ext)仅作业务扩展, * 因此这里按 user_id 关联 fa_user 进行加减。 * 【注意】ids 必须是 fa_user.id(即本表的 user_id 字段), * 不能传 fc_user_ext.id,否则会充错人(或报「未找到对应用户」)。 * 为可追溯,每次充值同时写入 fa_fc_finance_flow(资金流水)与 * fa_fc_message(站内通知),后台操作留痕由 Backend 自动记录。 */ public function recharge() { $ids = (string)$this->request->post('ids', ''); $userIds = array_filter(array_map('intval', explode(',', $ids))); $userIds = array_values(array_unique($userIds)); if (!$userIds) { $this->error('请选择要充值的用户'); } $amount = round((float)$this->request->post('amount', 0), 2); if ($amount <= 0) { $this->error('充值金额需大于 0'); } if ($amount > 100000) { $this->error('单次充值金额过大'); } $remark = trim((string)$this->request->post('remark', '')); $now = time(); $done = 0; $missing = []; Db::startTrans(); try { foreach ($userIds as $uid) { // 加行锁,避免并发充值互相覆盖余额 $user = Db::name('user')->where('id', $uid)->lock(true)->find(); if (!$user) { $missing[] = $uid; continue; } $balance = round((float)$user['money'] + $amount, 2); Db::name('user')->where('id', $uid)->update([ 'money' => $balance, 'updatetime' => $now, ]); // 资金流水(平台口径:余额充值属于收入) Db::name('fc_finance_flow')->insert([ 'flow_no' => 'R' . date('YmdHis') . mt_rand(100, 999) . $uid, 'type' => 'income', 'scene' => '余额充值', 'amount' => $amount, 'balance' => $balance, 'related_id' => $uid, 'remark' => $remark !== '' ? $remark : ('后台充值给用户 #' . $uid), 'createtime' => $now, ]); // 站内通知 Db::name('fc_message')->insert([ 'user_id' => $uid, 'type' => 'system', 'title' => '余额充值到账', 'content' => '您的账户已充值 ¥' . number_format($amount, 2, '.', '') . ',当前余额 ¥' . number_format($balance, 2, '.', '') . '。' . ($remark !== '' ? '备注:' . $remark : ''), 'isread' => 0, 'readtime' => null, 'createtime' => $now, ]); $done++; } Db::commit(); } catch (\Exception $e) { Db::rollback(); $this->error('充值失败:' . $e->getMessage()); } if (!$done) { $this->error('未找到对应用户:' . implode(',', $missing) . '(请确认传的是用户ID)'); } $msg = '充值成功:' . $done . ' 个用户,每人 ¥' . number_format($amount, 2, '.', ''); if ($missing) { $msg .= ';已跳过不存在的用户:' . implode(',', $missing); } $this->success($msg); } /** * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 */ }