// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\services\user; use qiniu\basic\BaseServices; use app\model\user\UserBill; use think\db\exception\DbException; use think\Exception; use think\exception\ValidateException; use qiniu\services\CacheService; use think\facade\Log; /** * * Class UserBillServices * @package app\services\user * @mixin UserBill */ class UserBillServices extends BaseServices { protected $exportHeader = [ 'id' => 'ID', 'uid' => '用户id', 'link_id' => '关联ID', 'category_chs' => '变更代币', 'title' => '变动标题', 'pm_chs' => '变动类型', 'number' => '变动金额', 'balance' => '变动后金额', 'mark' => '变动详情', 'add_time' => '变动时间', 'status_chs' => '变动状态' ]; /** * 用户记录模板 * @var array[] */ protected $incomeData = [ 'system_add_integral' => [ 'title' => '系统增加积分', 'category' => 'integral', 'type' => 'system_add', 'mark' => '系统增加了{%number%}积分{%mark%}', 'status' => 1, 'pm' => 1 ], 'system_sub_integral' => [ 'title' => '系统减少消费分', 'category' => 'integral', 'type' => 'system_sub', 'mark' => '系统扣除了{%number%}积分{%mark%}', 'status' => 1, 'pm' => 0 ], 'trade_in_integral' => [ 'title' => '积分转入', 'type' => 'trade_in', 'mark' => '{%mark%}{%number%}积分', 'status' => 1, 'pm' => 1 ], 'trade_out_integral' => [ 'title' => '积分转出', 'type' => 'trade_out', 'mark' => '{%mark%}{%number%}积分', 'status' => 1, 'pm' => 0 ], ]; protected $categorys = [ 'integral' => '积分' ]; /** * UserBillServices constructor. * @param UserBill $model */ public function __construct(UserBill $model) { $this->model = $model; } /** * 获取积分列表 * @param int $uid * @param string $category * @param array $where_time * @param string $field * @return array * @throws DbException */ public function getBillList(int $uid = 0, $category = 'integral', $where_time = [], string $field = '*') { [$page, $limit] = $this->getPageValue(); $where = ['category' => $category]; if ($uid) $where['uid'] = $uid; if ($where_time) $where['add_time'] = $where_time; $list = $this->getList($where, $field, $page, $limit); foreach ($list as &$item) { $item['number'] = intval($item['number']); $item['balance'] = intval($item['balance']); } $count = $this->getCount($where); return compact('list', 'count'); } /** * 写入用户记录 * @param string $type 写入类型 * @param int $uid * @param int|string|array $number * @param int|string $link_id * @return bool|mixed */ public function income(string $type, int $uid, $number, $link_id = 0) { $data = $this->incomeData[$type] ?? null; if (!$data) { return true; } $data['uid'] = $uid; $data['balance'] = $balance ?? 0; $data['link_id'] = $link_id; if (is_array($number)) { $key = array_keys($number); $key = array_map(function ($item) { return '{%' . $item . '%}'; }, $key); $value = array_values($number); $data['number'] = $number['number'] ?? 0; $data['mark'] = str_replace($key, $value, $data['mark']); } else { $data['number'] = $number; $data['mark'] = str_replace(['{%number%}'], $number, $data['mark']); } $data['add_time'] = time(); /** @var UserServices $userService */ $userService = app()->make(UserServices::class); if ((float)$data['number'] > 0) { if ($data['status'] == 1) { $user = $userService->getUserInfo($uid); if ($data['pm'] == 1) { $data['balance'] = bcadd($user[$data['category']], $data['number'], 2); $userService->bcInc($uid, $data['category'], $data['number'], 'uid'); } else { if ($data['number'] > $user[$data['category']]) { throw new ValidateException($this->categorys[$data['category']] . '余额不足'); } $data['balance'] = bcsub($user[$data['category']], $data['number'], 2); $userService->bcDec($uid, $data['category'], $data['number'], 'uid'); } } return $this->save($data); } return true; } /** * 获取type * @param string $category * @return array */ public function getBillType(string $category = 'integral') { $getMoneyType = function () use ($category) { $array = $this->incomeData; $list = []; foreach ($array as $v) { if ($v['category'] == $category) $list[] = ['type' => $v['type'], 'title' => $v['title'], 'pm' => $v['pm']]; } return $list; }; return $getMoneyType(); } /** * 资金类型 */ public function bill_type(string $category = 'integral') { return CacheService::get('user_type_list', function () use ($category) { return ['list' => $this->getBillType($category)]; }, 600); } public function trade(int $uid, int $to_uid, $category, $num) { /** @var UserServices $userService */ $userService = app()->make(UserServices::class); $user = $userService->getUserInfo($uid); $to_user = $userService->getUserInfo($to_uid); if (!$user || !$to_user) { throw new ValidateException('数据不存在'); } if ($to_uid == $uid) throw new ValidateException('不能自己转给自己'); $extractPrice = $user[$category]; if ($num > $extractPrice) { throw new ValidateException('转账' . $this->categorys[$category] . '不足' . $num); } if ($num <= 0) { throw new ValidateException('转账' . $this->categorys[$category] . '大于0'); } return $this->transaction(function () use ($num, $user, $to_user, $userService, $category) { $this->income('trade_out_' . $category, $user['uid'], ['mark' => '转账给' . $to_user['nickname'] . '(' . $to_user['uid'] . ')', 'number' => $num], $to_user['uid']); $this->income('trade_in_' . $category, $to_user['uid'], ['mark' => '转账自' . $user['nickname'] . '(' . $user['uid'] . ')', 'number' => $num], $user['uid']); return true; }); } }