chore: 添加静态资源文件和版本配置文件
添加大量图片、字体、音频等静态资源文件,包括用户界面图片、模板文件和安装界面素材 添加系统版本配置文件(.version)和常量定义文件(.constant) 更新供应商依赖文件,包括Symfony VarDumper组件和相关许可证文件 添加验证码配置文件(captcha.php)和.gitignore规则
This commit is contained in:
45
app/services/user/CancelUserServices.php
Normal file
45
app/services/user/CancelUserServices.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use think\facade\Log;
|
||||
|
||||
class CancelUserServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* 注销用户账号
|
||||
* @param int $uid 用户ID
|
||||
* @return void
|
||||
*/
|
||||
public function cancelUser(int $uid)
|
||||
{
|
||||
try {
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
/** @var WechatUserServices $wechatUserServices */
|
||||
$wechatUserServices = app()->make(WechatUserServices::class);
|
||||
$userService->update(['spread_uid' => $uid], ['spread_uid' => 0]);// 清除用户与下级的关系
|
||||
$userService->update($uid, ['spread_uid' => 0, 'integral' => 0, 'now_money' => 0]);//清除
|
||||
$userService->update(['work_uid' => $uid], ['work_uid' => 0, 'work_userid' => '']);//清除企业微信上下级关系
|
||||
$userService->destroy($uid);// 软删除用户
|
||||
$wechatUserServices->update(['uid' => $uid], ['is_del' => 1, 'unionid' => '', 'openid' => time() . rand(1000, 9999)]);// 删除微信用户
|
||||
// CancelUserJob::dispatch([$uid]);// 相关记录删除队列
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('注销用户失败,失败原因:' . $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
465
app/services/user/LoginServices.php
Normal file
465
app/services/user/LoginServices.php
Normal file
@@ -0,0 +1,465 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\notice\SmsJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserDao;
|
||||
use app\services\message\sms\SmsRecordServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use crmeb\exceptions\ApiException;
|
||||
use crmeb\services\CacheService;
|
||||
use Firebase\JWT\JWT;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Config;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class LoginServices
|
||||
* @package app\services\user
|
||||
* @mixin UserDao
|
||||
*/
|
||||
class LoginServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserDao $dao;
|
||||
|
||||
/**
|
||||
* H5账号登陆
|
||||
* @param $account
|
||||
* @param $password
|
||||
* @param $spread_uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function login($account, $password, $spread_uid)
|
||||
{
|
||||
$user = $this->dao->getOne(['phone' => $account], 'uid,pwd,status');
|
||||
if ($user) {
|
||||
if ($user->pwd !== md5((string)$password))
|
||||
throw new ValidateException('账号或密码错误');
|
||||
if ($user->pwd === md5('123456'))
|
||||
throw new ValidateException('请修改您的初始密码,再尝试登录!');
|
||||
} else {
|
||||
throw new ValidateException('账号或密码错误');
|
||||
}
|
||||
if (!$user['status'])
|
||||
throw new ValidateException('已被禁止,请联系管理员');
|
||||
|
||||
$uid = (int)$user['uid'];
|
||||
//更新用户信息
|
||||
$token = $this->createToken($uid, 'api', $user->pwd);
|
||||
if ($token) {
|
||||
$this->updateUserInfo(['spread_uid' => $spread_uid], $user);
|
||||
// 用户登录成功事件
|
||||
event('user.login', [$uid, app('request')->ip()]);
|
||||
return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
|
||||
} else
|
||||
throw new ValidateException('登录失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
* @param $user
|
||||
* @param $uid
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function updateUserInfo($user, $userInfo)
|
||||
{
|
||||
$data = [];
|
||||
if (isset($userInfo['nickname']) && $userInfo['nickname']) {
|
||||
$data['nickname'] = !isset($user['nickname']) || !$user['nickname'] ? $userInfo->nickname : $user['nickname'];
|
||||
}
|
||||
if (isset($userInfo['avatar']) && $userInfo['avatar']) {
|
||||
$data['avatar'] = !isset($user['headimgurl']) || !$user['headimgurl'] ? $userInfo->avatar : $user['headimgurl'];
|
||||
}
|
||||
if (isset($user['phone']) && $user['phone'] && isset($userInfo['phone']) && !$userInfo['phone']) {
|
||||
$data['phone'] = $user['phone'];
|
||||
}
|
||||
$data['last_time'] = time();
|
||||
$data['last_ip'] = app()->request->ip();
|
||||
//永久绑定
|
||||
$store_brokergae_binding_status = sys_config('store_brokerage_binding_status', 1);
|
||||
$spread_uid = isset($user['code']) && $user['code'] && $user['code'] != $userInfo->uid ? $user['code'] : ($user['spread_uid'] ?? 0);
|
||||
if ($userInfo->spread_uid && $store_brokergae_binding_status == 1) {
|
||||
$data['login_type'] = $user['login_type'] ?? $userInfo->login_type;
|
||||
} else {
|
||||
//绑定分销关系 = 所有用户
|
||||
if (sys_config('brokerage_bindind', 1) == 1) {
|
||||
//分销绑定类型为时间段且过期 ||临时
|
||||
$store_brokerage_binding_time = sys_config('store_brokerage_binding_time', 30);
|
||||
if (!$userInfo['spread_uid'] || $store_brokergae_binding_status == 3 || ($store_brokergae_binding_status == 2 && ($userInfo['spread_time'] + $store_brokerage_binding_time * 24 * 3600) < time())) {
|
||||
$spreadUid = $spread_uid;
|
||||
if ($spreadUid && $userInfo->uid == $this->dao->value(['uid' => $spreadUid], 'spread_uid')) {
|
||||
$spreadUid = 0;
|
||||
}
|
||||
if($spreadUid == $userInfo->uid){
|
||||
$spreadUid = 0;
|
||||
}
|
||||
if ($spreadUid && $this->dao->count(['uid' => (int)$spreadUid])) {
|
||||
$data['spread_uid'] = $spreadUid;
|
||||
$data['spread_time'] = time();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->dao->update($userInfo['uid'], $data, 'uid')) {
|
||||
throw new ValidateException('修改信息失败');
|
||||
}
|
||||
if (isset($data['spread_uid']) && $data['spread_uid']) {
|
||||
event('user.register', [$this->dao->get((int)$userInfo['uid']), false, $spread_uid]);
|
||||
//推送消息
|
||||
// event('notice.notice', [['spreadUid' => $spreadUid, 'user_type' => $userInfo['user_type'], 'nickname' => $userInfo['nickname']], 'bind_spread_uid']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
* @param $phone
|
||||
* @param $type
|
||||
* @param $time
|
||||
* @param $ip
|
||||
* @return int
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function verify($phone, $type, $time, $ip)
|
||||
{
|
||||
if ($this->dao->getOne(['account' => $phone]) && $type == 'register') {
|
||||
throw new ValidateException('手机号已注册');
|
||||
}
|
||||
$default = Config::get('sms.default', 'yunxin');
|
||||
$defaultMaxPhoneCount = Config::get('sms.maxPhoneCount', 10);
|
||||
$defaultMaxIpCount = Config::get('sms.maxIpCount', 50);
|
||||
$maxPhoneCount = Config::get('sms.stores.' . $default . '.maxPhoneCount', $defaultMaxPhoneCount);
|
||||
$maxIpCount = Config::get('sms.stores.' . $default . '.maxIpCount', $defaultMaxIpCount);
|
||||
/** @var SmsRecordServices $smsRecord */
|
||||
$smsRecord = app()->make(SmsRecordServices::class);
|
||||
if ($smsRecord->count(['phone' => $phone, 'add_ip' => $ip, 'time' => 'today']) >= $maxPhoneCount) {
|
||||
throw new ValidateException('您今日发送得短信次数已经达到上限');
|
||||
}
|
||||
if ($smsRecord->count(['add_ip' => $ip, 'time' => 'today']) >= $maxIpCount) {
|
||||
throw new ValidateException('此IP今日发送次数已经达到上限');
|
||||
}
|
||||
if (CacheService::get('code_' . $phone))
|
||||
throw new ValidateException($time . '分钟内有效');
|
||||
mt_srand();
|
||||
$code = rand(100000, 999999);
|
||||
$data['code'] = $code;
|
||||
$data['time'] = $time;
|
||||
$res = SmsJob::dispatch([$phone, $data, 'VERIFICATION_CODE_TIME']);
|
||||
if (!$res)
|
||||
throw new ValidateException('短信平台验证码发送失败');
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* H5用户注册
|
||||
* @param $account
|
||||
* @param $password
|
||||
* @param $spread_uid
|
||||
* @return User|\think\Model
|
||||
*/
|
||||
public function register($account, $password, $spread_uid, $user_type = 'h5')
|
||||
{
|
||||
if ($this->dao->getOne(['phone' => $account], 'uid')) {
|
||||
throw new ValidateException('用户已存在,请去修改密码');
|
||||
}
|
||||
$phone = $account;
|
||||
$data['account'] = $account;
|
||||
$data['pwd'] = md5((string)$password);
|
||||
$data['phone'] = $phone;
|
||||
if ($spread_uid && $this->dao->count(['uid' => (int)$spread_uid])) {
|
||||
$data['spread_uid'] = $spread_uid;
|
||||
$data['spread_time'] = time();
|
||||
}
|
||||
$data['real_name'] = '';
|
||||
$data['birthday'] = '';
|
||||
$data['card_id'] = '';
|
||||
$data['mark'] = '';
|
||||
$data['addres'] = '';
|
||||
$data['user_type'] = $user_type;
|
||||
$data['add_time'] = time();
|
||||
$data['add_ip'] = app('request')->ip();
|
||||
$data['last_time'] = time();
|
||||
$data['last_ip'] = app('request')->ip();
|
||||
$data['nickname'] = substr(md5($account . time()), 0, 12);
|
||||
$data['avatar'] = $data['headimgurl'] = sys_config('h5_avatar');
|
||||
$data['city'] = '';
|
||||
$data['language'] = '';
|
||||
$data['province'] = '';
|
||||
$data['country'] = '';
|
||||
$data['status'] = 1;
|
||||
if (!$re = $this->dao->save($data)) {
|
||||
throw new ValidateException('注册失败');
|
||||
} else {
|
||||
//用户注册成功事件
|
||||
event('user.register', [$re->toArray(), true, $spread_uid]);
|
||||
//推送消息
|
||||
// event('notice.notice', [['spreadUid' => $spread, 'user_type' => $user_type, 'nickname' => $data['nickname']], 'bind_spread_uid']);
|
||||
return $re;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
* @param $account
|
||||
* @param $password
|
||||
*/
|
||||
public function reset($account, $password)
|
||||
{
|
||||
$user = $this->dao->getOne(['account|phone' => $account], 'uid');
|
||||
if (!$user) {
|
||||
throw new ValidateException('用户不存在');
|
||||
}
|
||||
if (!$this->dao->update($user['uid'], ['pwd' => md5((string)$password)], 'uid')) {
|
||||
throw new ValidateException('修改密码失败');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号登录
|
||||
* @param $phone
|
||||
* @param $spread_uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function mobile($phone, $spread_uid, $user_type = 'h5')
|
||||
{
|
||||
//数据库查询
|
||||
$user = $this->dao->getOne(['phone' => $phone]);
|
||||
if (!$user) {
|
||||
$user = $this->register($phone, '123456', $spread_uid, $user_type);
|
||||
if (!$user) {
|
||||
throw new ValidateException('用户登录失败,无法生成新用户,请稍后再试!');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$user->status)
|
||||
throw new ValidateException('已被禁止,请联系管理员');
|
||||
|
||||
// 设置推广关系
|
||||
$this->updateUserInfo(['spread_uid' => $spread_uid], $user);
|
||||
|
||||
$uid = (int)$user['uid'];
|
||||
$token = $this->createToken($uid, 'api', $user->pwd);
|
||||
if ($token) {
|
||||
// 用户登录成功事件
|
||||
event('user.login', [$uid, app('request')->ip()]);
|
||||
return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
|
||||
} else {
|
||||
throw new ValidateException('登录失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换登录
|
||||
* @param $user
|
||||
* @param $from
|
||||
*/
|
||||
public function switchAccount($user, $from)
|
||||
{
|
||||
if ($from === 'h5') {
|
||||
$where = [['phone', '=', $user['phone']], ['user_type', '<>', 'h5']];
|
||||
$login_type = 'wechat';
|
||||
} else {
|
||||
//数据库查询
|
||||
$where = [['account|phone', '=', $user['phone']], ['user_type', '=', 'h5']];
|
||||
$login_type = 'h5';
|
||||
}
|
||||
$switch_user = $this->dao->getOne($where);
|
||||
if (!$switch_user) {
|
||||
throw new ValidateException('用户不存在,无法切换');
|
||||
}
|
||||
if (!$switch_user->status) {
|
||||
throw new ValidateException('已被禁止,请联系管理员');
|
||||
}
|
||||
$edit_data = ['login_type' => $login_type];
|
||||
if (!$this->dao->update($switch_user['uid'], $edit_data, 'uid')) {
|
||||
throw new ValidateException('修改新用户登录类型出错');
|
||||
}
|
||||
$uid = (int)$switch_user['uid'];
|
||||
$token = $this->createToken($uid, 'api', $switch_user['pwd']);
|
||||
if ($token) {
|
||||
// 用户登录成功事件
|
||||
event('user.login', [$uid, app('request')->ip()]);
|
||||
return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
|
||||
} else {
|
||||
throw new ValidateException('切换失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定手机号(静默还没写入用户信息)
|
||||
* @param $user
|
||||
* @param $phone
|
||||
* @param $step
|
||||
* @return mixed
|
||||
*/
|
||||
public function bindind_phone($phone, $key = '')
|
||||
{
|
||||
if (!$key) {
|
||||
throw new ValidateException('请刷新页面或者重新授权');
|
||||
}
|
||||
[$openid, $wechatInfo, $spread_uid, $login_type, $userType] = $createData = CacheService::getTokenBucket($key);
|
||||
if (!$createData) {
|
||||
throw new ValidateException('请刷新页面或者重新授权');
|
||||
}
|
||||
$wechatInfo['phone'] = $phone;
|
||||
/** @var WechatUserServices $wechatUser */
|
||||
$wechatUser = app()->make(WechatUserServices::class);
|
||||
//更新用户信息
|
||||
$user = $wechatUser->wechatOauthAfter([$openid, $wechatInfo, $spread_uid, $login_type, $userType]);
|
||||
$token = $this->createToken((int)$user['uid'], $userType, $user['pwd']);
|
||||
if ($token) {
|
||||
return [
|
||||
'token' => $token['token'],
|
||||
'userInfo' => $user,
|
||||
'expires_time' => $token['params']['exp'],
|
||||
];
|
||||
} else
|
||||
throw new ValidateException('获取用户访问token失败!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户绑定手机号
|
||||
* @param $user
|
||||
* @param $phone
|
||||
* @param $step
|
||||
* @return mixed
|
||||
*/
|
||||
public function userBindindPhone(int $uid, $phone, $step)
|
||||
{
|
||||
$userInfo = $this->dao->get($uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('用户不存在');
|
||||
}
|
||||
if ($this->dao->getOne([['phone', '=', $phone], ['user_type', '<>', 'h5']])) {
|
||||
throw new ValidateException('此手机已经绑定,无法多次绑定!');
|
||||
}
|
||||
if ($userInfo->phone) {
|
||||
throw new ValidateException('您的账号已经绑定过手机号码!');
|
||||
}
|
||||
$data = [];
|
||||
if ($this->dao->getOne(['account' => $phone, 'phone' => $phone, 'user_type' => 'h5'])) {
|
||||
if (!$step) return ['msg' => 'H5已有账号是否绑定此账号上', 'data' => ['is_bind' => 1]];
|
||||
} else {
|
||||
$data['account'] = $phone;
|
||||
}
|
||||
$data['phone'] = $phone;
|
||||
if ($this->dao->update($userInfo['uid'], $data, 'uid') || $userInfo->phone == $phone)
|
||||
return ['msg' => '绑定成功', 'data' => []];
|
||||
else
|
||||
throw new ValidateException('绑定失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户绑定手机号
|
||||
* @param $user
|
||||
* @param $phone
|
||||
* @param $step
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateBindindPhone(int $uid, $phone)
|
||||
{
|
||||
$userInfo = $this->dao->get($uid);
|
||||
if (!$userInfo) {
|
||||
throw new ValidateException('用户不存在');
|
||||
}
|
||||
if ($userInfo->phone == $phone) {
|
||||
throw new ValidateException('新手机号和原手机号相同,无需修改');
|
||||
}
|
||||
if ($this->dao->getOne([['phone', '=', $phone]])) {
|
||||
throw new ValidateException('此手机已经注册');
|
||||
}
|
||||
$data = [];
|
||||
$data['phone'] = $phone;
|
||||
if ($this->dao->update($userInfo['uid'], $data, 'uid'))
|
||||
return ['msg' => '修改成功', 'data' => []];
|
||||
else
|
||||
throw new ValidateException('修改失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程登录接口
|
||||
* @param string $out_token
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/10/26 14:49
|
||||
*/
|
||||
public function remoteRegister(string $out_token = '')
|
||||
{
|
||||
$info = JWT::jsonDecode(JWT::urlsafeB64Decode($out_token));
|
||||
$userInfo = $this->dao->get(['uid' => $info->uid]);
|
||||
$data = [];
|
||||
if (!$userInfo) {
|
||||
$data['uid'] = $info->uid;
|
||||
$data['account'] = $info->phone != '' ? $info->phone : 'out_' . $info->uid;
|
||||
$data['phone'] = $info->phone;
|
||||
$data['pwd'] = md5('123456');
|
||||
$data['real_name'] = $info->nickname;
|
||||
$data['birthday'] = '';
|
||||
$data['card_id'] = '';
|
||||
$data['mark'] = '';
|
||||
$data['addres'] = '';
|
||||
$data['user_type'] = 'h5';
|
||||
$data['add_time'] = time();
|
||||
$data['add_ip'] = app('request')->ip();
|
||||
$data['last_time'] = time();
|
||||
$data['last_ip'] = app('request')->ip();
|
||||
$data['nickname'] = $info->nickname;
|
||||
$data['avatar'] = $info->avatar;
|
||||
$data['city'] = '';
|
||||
$data['language'] = '';
|
||||
$data['province'] = '';
|
||||
$data['country'] = '';
|
||||
$data['status'] = 1;
|
||||
$data['now_money'] = $info->now_money;
|
||||
$data['integral'] = $info->integral;
|
||||
$data['exp'] = $info->exp;
|
||||
$this->dao->save($data);
|
||||
} else {
|
||||
$data['nickname'] = $info->nickname;
|
||||
$data['avatar'] = $info->avatar;
|
||||
$data['now_money'] = $info->now_money;
|
||||
$data['integral'] = $info->integral;
|
||||
$data['exp'] = $info->exp;
|
||||
$this->dao->update($info->uid, $data);
|
||||
}
|
||||
$token = $this->createToken((int)$info->uid, 'api');
|
||||
if ($token) {
|
||||
return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
|
||||
} else {
|
||||
throw new ApiException('登录失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
303
app/services/user/UserAddressServices.php
Normal file
303
app/services/user/UserAddressServices.php
Normal file
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\validate\api\user\AddressValidate;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserAddressDao;
|
||||
use app\services\other\SystemCityServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\Exception;
|
||||
use think\exception\ValidateException;
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserAddressServices
|
||||
* @package app\services\user
|
||||
* @mixin UserAddressDao
|
||||
*/
|
||||
class UserAddressServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserAddressDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserAddressDao $dao;
|
||||
|
||||
/**
|
||||
* 获取单个地址
|
||||
* @param $id
|
||||
* @param array $field
|
||||
* @return array
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function getAddress($id, array $field = [])
|
||||
{
|
||||
return $this->dao->get($id, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户缓存地址
|
||||
* @param int $uid
|
||||
* @param int $addressId
|
||||
* @return bool|mixed|null
|
||||
*/
|
||||
public function getAdderssCache(int $id, int $expire = 60)
|
||||
{
|
||||
return $this->dao->cacheTag()->remember('user_adderss_cache_' . $id, function () use ($id) {
|
||||
$res = $this->dao->getOne(['id' => $id, 'is_del' => 0]);
|
||||
if ($res) {
|
||||
return $res->toArray();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有地址
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getAddressList(array $where, string $field = '*'): array
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->getAddresCount($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个用户的所有地址
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getUserAddressList(int $uid, string $field = '*'): array
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['uid' => $uid];
|
||||
$where['is_del'] = 0;
|
||||
return $this->dao->getList($where, $field, $page, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param int $expire
|
||||
* @return mixed
|
||||
* @throws \throwable
|
||||
*/
|
||||
public function getUserDefaultAddressCache(int $uid, int $expire = 60)
|
||||
{
|
||||
return $this->dao->cacheTag()->remember('user_adderss_cache_user_' . $uid, function () use ($uid) {
|
||||
$res = $this->dao->getOne(['uid' => $uid, 'is_default' => 1, 'is_del' => 0]);
|
||||
if ($res) {
|
||||
return $res->toArray();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
* @return array|Model|null
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function getUserDefaultAddress(int $uid, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne(['uid' => $uid, 'is_default' => 1, 'is_del' => 0], $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取条数
|
||||
* @param array $where
|
||||
* @return int
|
||||
*/
|
||||
public function getAddresCount(array $where): int
|
||||
{
|
||||
return $this->dao->count($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加地址
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
if (!$this->dao->save($data))
|
||||
throw new AdminException('写入失败');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改地址
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
public function updateAddress(int $id, array $data)
|
||||
{
|
||||
if (!$this->dao->update($id, $data))
|
||||
throw new AdminException('修改失败');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认定制
|
||||
* @param int $uid
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function setDefault(int $uid, int $id)
|
||||
{
|
||||
if (!$this->dao->be($id)) {
|
||||
throw new ValidateException('地址不存在');
|
||||
}
|
||||
if (!$this->dao->update($uid, ['is_default' => 0], 'uid'))
|
||||
throw new Exception('取消原来默认地址');
|
||||
if (!$this->dao->update($id, ['is_default' => 1]))
|
||||
throw new Exception('设置默认地址失败');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个地址
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function address(int $id)
|
||||
{
|
||||
$addressInfo = $this->getAdderssCache($id);
|
||||
if (!$addressInfo || (isset($addressInfo['is_del']) && $addressInfo['is_del'] == 1)) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
return $addressInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加|修改地址
|
||||
* @param int $uid
|
||||
* @param array $addressInfo
|
||||
* @return mixed
|
||||
*/
|
||||
public function editAddress(int $uid, array $addressInfo)
|
||||
{
|
||||
if ($addressInfo['type'] == 1 && !$addressInfo['id']) {
|
||||
$city = $addressInfo['address']['city'];
|
||||
/** @var SystemCityServices $systemCity */
|
||||
$systemCity = app()->make(SystemCityServices::class);
|
||||
$cityInfo = $systemCity->getOne([['name', '=', $city], ['parent_id', '<>', 0]]);
|
||||
if ($cityInfo && $cityInfo['city_id']) {
|
||||
$addressInfo['address']['city_id'] = $cityInfo['city_id'];
|
||||
} else {
|
||||
$cityInfo = $systemCity->getOne([['name', 'like', "%$city%"], ['parent_id', '<>', 0]]);
|
||||
if (!$cityInfo) {
|
||||
throw new ValidateException('收货地址格式错误!修改后请重新导入!');
|
||||
}
|
||||
$addressInfo['address']['city_id'] = $cityInfo['city_id'];
|
||||
}
|
||||
}
|
||||
if (!isset($addressInfo['address']['city_id']) || $addressInfo['address']['city_id'] == 0) throw new ValidateException('添加收货地址失败!');
|
||||
$addressInfo['province'] = $addressInfo['address']['province'] ?? '';
|
||||
$addressInfo['city'] = $addressInfo['address']['city'] ?? '';
|
||||
$addressInfo['city_id'] = $addressInfo['address']['city_id'] ?? 0;
|
||||
$addressInfo['district'] = $addressInfo['address']['district'] ?? '';
|
||||
$addressInfo['street'] = $addressInfo['address']['street'] ?? '';
|
||||
$addressInfo['is_default'] = (int)$addressInfo['is_default'] == true ? 1 : 0;
|
||||
$addressInfo['uid'] = $uid;
|
||||
unset($addressInfo['address'], $addressInfo['type']);
|
||||
//数据验证
|
||||
validate(AddressValidate::class)->check($addressInfo);
|
||||
$address_check = [];
|
||||
if ($addressInfo['id']) {
|
||||
$address_check = $this->getAddress((int)$addressInfo['id']);
|
||||
}
|
||||
if ($address_check && $address_check['is_del'] == 0) {
|
||||
if ($address_check['uid'] != $uid) {
|
||||
throw new ValidateException('编辑收货地址失败');
|
||||
}
|
||||
$id = (int)$addressInfo['id'];
|
||||
unset($addressInfo['id']);
|
||||
if (!$this->dao->update($id, $addressInfo, 'id')) {
|
||||
throw new ValidateException('编辑收货地址失败');
|
||||
}
|
||||
if ($addressInfo['is_default']) {
|
||||
$this->setDefault($uid, $id);
|
||||
}
|
||||
|
||||
$this->dao->cacheTag()->clear();
|
||||
|
||||
return ['type' => 'edit', 'msg' => '编辑地址成功', 'data' => []];
|
||||
} else {
|
||||
$addressInfo['add_time'] = time();
|
||||
unset($addressInfo['id']);
|
||||
if (!$address = $this->dao->save($addressInfo)) {
|
||||
throw new ValidateException('添加收货地址失败');
|
||||
}
|
||||
if ($addressInfo['is_default']) {
|
||||
$this->setDefault($uid, (int)$address->id);
|
||||
}
|
||||
|
||||
$this->dao->cacheTag()->clear();
|
||||
|
||||
return ['type' => 'add', 'msg' => '添加地址成功', 'data' => ['id' => $address->id]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除地址
|
||||
* @param int $uid
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delAddress(int $uid, int $id)
|
||||
{
|
||||
$addressInfo = $this->getAddress($id);
|
||||
if (!$addressInfo || $addressInfo['is_del'] == 1 || $addressInfo['uid'] != $uid) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
if ($this->dao->update($id, ['is_del' => '1'], 'id')) {
|
||||
$this->dao->cacheTag()->clear();
|
||||
return true;
|
||||
} else
|
||||
throw new ValidateException('删除地址失败!');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认用户地址
|
||||
* @param $id
|
||||
* @param $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function setDefaultAddress(int $id, int $uid)
|
||||
{
|
||||
$res1 = $this->dao->update($uid, ['is_default' => 0], 'uid');
|
||||
$res2 = $this->dao->update(['id' => $id, 'uid' => $uid], ['is_default' => 1]);
|
||||
$res = $res1 !== false && $res2 !== false;
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
114
app/services/user/UserAuthServices.php
Normal file
114
app/services/user/UserAuthServices.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserAuthDao;
|
||||
use app\services\work\WorkClientServices;
|
||||
use crmeb\exceptions\AuthException;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\services\wechat\config\WorkConfig;
|
||||
use crmeb\utils\JwtAuth;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserAuthServices
|
||||
* @package app\services\user
|
||||
* @mixin UserAuthDao
|
||||
*/
|
||||
class UserAuthServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserAuthDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserAuthDao $dao;
|
||||
|
||||
/**
|
||||
* 获取授权信息
|
||||
* @param $token
|
||||
* @return array
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException\
|
||||
*/
|
||||
public function parseToken($token): array
|
||||
{
|
||||
$md5Token = is_null($token) ? '' : md5($token);
|
||||
|
||||
if ($token === 'undefined') {
|
||||
throw new AuthException('请登录', 410000);
|
||||
}
|
||||
if (!$token || !$tokenData = CacheService::getTokenBucket($md5Token))
|
||||
throw new AuthException('请登录', 410000);
|
||||
|
||||
if (!is_array($tokenData) || empty($tokenData) || !isset($tokenData['uid'])) {
|
||||
throw new AuthException('请登录', 410000);
|
||||
}
|
||||
|
||||
/** @var JwtAuth $jwtAuth */
|
||||
$jwtAuth = app()->make(JwtAuth::class);
|
||||
//设置解析token
|
||||
[$id, $type, $auth] = $jwtAuth->parseToken($token);
|
||||
try {
|
||||
$jwtAuth->verifyToken();
|
||||
} catch (\Throwable $e) {
|
||||
if (!request()->isCli()) CacheService::clearToken($md5Token);
|
||||
throw new AuthException('登录已过期,请重新登录', 410001);
|
||||
}
|
||||
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$user = $userService->getUserCacheInfo($id);
|
||||
if (!$user) throw new AuthException('用户不存在,请重新登陆', 410001);
|
||||
if (!$user['status'])
|
||||
throw new AuthException('您已被禁止登录,请联系管理员', 410002);
|
||||
|
||||
if (!$user || $user->uid != $tokenData['uid']) {
|
||||
if (!request()->isCli()) CacheService::clearToken($md5Token);
|
||||
throw new AuthException('登录状态有误,请重新登录', 410002);
|
||||
}
|
||||
|
||||
//有密码在检测
|
||||
if ($user['pwd'] != md5('123456') && $auth !== md5($user['pwd'])) {
|
||||
throw new AuthException('登录已过期,请重新登录', 410001);
|
||||
}
|
||||
|
||||
$tokenData['type'] = $type;
|
||||
return compact('user', 'tokenData');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业客户
|
||||
* @param string $userid
|
||||
* @return array
|
||||
*/
|
||||
public function parseClient(string $userid)
|
||||
{
|
||||
/** @var WorkConfig $workConfig */
|
||||
$workConfig = app()->make(WorkConfig::class);
|
||||
$corpId = $workConfig->corpId;
|
||||
if (!$corpId) {
|
||||
throw new AuthException('请先配置企业微信');
|
||||
}
|
||||
/** @var WorkClientServices $service */
|
||||
$service = app()->make(WorkClientServices::class);
|
||||
$clientInfo = $service->get(['corp_id' => $corpId, 'external_userid' => $userid]);
|
||||
if (!$clientInfo) {
|
||||
throw new AuthException('客户信息不存在');
|
||||
}
|
||||
|
||||
return $clientInfo->toArray();
|
||||
}
|
||||
|
||||
}
|
||||
168
app/services/user/UserBatchProcessServices.php
Normal file
168
app/services/user/UserBatchProcessServices.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
//declare (strict_types=1);
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\user\UserBatchJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserDao;
|
||||
use app\services\user\group\UserGroupServices;
|
||||
use app\services\user\label\UserLabelServices;
|
||||
use app\services\user\level\SystemUserLevelServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 用户批量操作
|
||||
* Class UserBatchProcessServices
|
||||
* @package app\services\user
|
||||
* @mixin UserDao
|
||||
*/
|
||||
class UserBatchProcessServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 批量处理参数
|
||||
* @var array[]
|
||||
*/
|
||||
protected array $data = [
|
||||
'group_id' => [],//分组ID
|
||||
'label_id' => [],//标签ids
|
||||
'level_id' => 0,//等级ID
|
||||
'money_status' => 0,//余额变动状态
|
||||
'money' => 0,//余额变动金额
|
||||
'integration_status' => 0,//积分变动状态
|
||||
'integration' => 0,//积分变动数量
|
||||
'days_status' => 0,//付费会员条数变动状态
|
||||
'day' => 0,//变动天数
|
||||
'spread_uid' => 0,//上级推广人uid
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserDao $dao;
|
||||
|
||||
/**
|
||||
* 根据搜索条件查询uids
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getUidByWhere($where)
|
||||
{
|
||||
if ($where) {
|
||||
if (is_string($where)) {
|
||||
$where = json_decode($where, true);
|
||||
} elseif (is_array($where)) {
|
||||
$where = $where;
|
||||
} else {
|
||||
$where = [];
|
||||
}
|
||||
}
|
||||
/** @var UserWechatuserServices $userWechatUser */
|
||||
$userWechatUser = app()->make(UserWechatuserServices::class);
|
||||
$fields = 'u.uid';
|
||||
[$list, $count] = $userWechatUser->getWhereUserList($where, $fields);
|
||||
$uids = array_unique(array_column($list, 'uid'));
|
||||
return $uids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户批量操作
|
||||
* @param int $type
|
||||
* @param array $uids
|
||||
* @param array $input_data
|
||||
* @param bool $is_all
|
||||
* @param array $where
|
||||
* @return bool
|
||||
*/
|
||||
public function batchProcess(int $type, array $uids, array $input_data, bool $is_all = false, array $where = [], $label_type = 0)
|
||||
{
|
||||
//全选
|
||||
if ($is_all == 1) {
|
||||
$uids = $this->getUidByWhere($where);
|
||||
}
|
||||
$data = [];
|
||||
switch ($type) {
|
||||
case 1://分组
|
||||
$group_id = $input_data['group_id'] ?? 0;
|
||||
if (!$group_id) throw new ValidateException('请选择分组');
|
||||
/** @var UserGroupServices $userGroup */
|
||||
$userGroup = app()->make(UserGroupServices::class);
|
||||
if (!$userGroup->getGroup($group_id)) {
|
||||
throw new ValidateException('该分组不存在');
|
||||
}
|
||||
$data['group_id'] = $group_id;
|
||||
break;
|
||||
case 2://标签
|
||||
$label_id = $input_data['label_id'] ?? [];
|
||||
if (!$label_id) throw new ValidateException ('请选择标签');
|
||||
/** @var UserLabelServices $userLabelServices */
|
||||
$userLabelServices = app()->make(UserLabelServices::class);
|
||||
$count = $userLabelServices->getCount([['id', 'IN', $label_id]]);
|
||||
if ($count != count($label_id)) {
|
||||
throw new ValidateException('用户标签不存在或被删除');
|
||||
}
|
||||
$data['label_id'] = $label_id;
|
||||
break;
|
||||
case 3://等级
|
||||
$level_id = $input_data['level_id'] ?? 0;
|
||||
if (!$level_id) throw new ValidateException('请选择用户等级');
|
||||
/** @var SystemUserLevelServices $systemLevelServices */
|
||||
$systemLevelServices = app()->make(SystemUserLevelServices::class);
|
||||
//查询当前选择的会员等级
|
||||
$systemLevel = $systemLevelServices->getLevel($level_id);
|
||||
if (!$systemLevel) throw new AdminException('您选择赠送的用户等级不存在!');
|
||||
$data['level_id'] = $level_id;
|
||||
break;
|
||||
case 4://积分余额
|
||||
$data['money_status'] = $input_data['money_status'] ?? 0;
|
||||
$data['money'] = $input_data['money'] ?? 0;
|
||||
$data['integration_status'] = $input_data['integration_status'] ?? 0;
|
||||
$data['integration'] = $input_data['integration'] ?? 0;
|
||||
if (!$data['money_status'] && !$data['integration_status']) {
|
||||
throw new AdminException('请选择操作积分或余额');
|
||||
}
|
||||
if ($data['money_status'] && !$data['money']) {
|
||||
throw new AdminException('请填写变动余额数量');
|
||||
}
|
||||
if ($data['integration_status'] && !$data['integration']) {
|
||||
throw new AdminException('请填写变动积分数量');
|
||||
}
|
||||
break;
|
||||
case 5://赠送会员
|
||||
$data['days_status'] = $input_data['days_status'] ?? 0;
|
||||
$data['day'] = $input_data['day'] ?? 0;
|
||||
if (!$data['days_status']) {
|
||||
throw new AdminException('请选择增加或者减少会员天数');
|
||||
}
|
||||
if (!$data['day']) {
|
||||
throw new AdminException('请填写变动会员天数');
|
||||
}
|
||||
break;
|
||||
case 6://上级推广人
|
||||
$spread_uid = $input_data['spread_uid'] ?? 0;
|
||||
if (!$spread_uid) throw new ValidateException('请选择上级推广人');
|
||||
if (!$this->dao->count(['uid' => $spread_uid])) {
|
||||
throw new ValidateException('上级用户不存在');
|
||||
}
|
||||
$data['spread_uid'] = $spread_uid;
|
||||
break;
|
||||
default:
|
||||
throw new AdminException('暂不支持该类型批操作');
|
||||
}
|
||||
//加入批量队列
|
||||
UserBatchJob::dispatchDo('userBatch', [$type, $uids, $data, $label_type]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
634
app/services/user/UserBillServices.php
Normal file
634
app/services/user/UserBillServices.php
Normal file
@@ -0,0 +1,634 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\user\UserLevelJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserBillDao;
|
||||
use app\services\system\admin\SystemAdminServices;
|
||||
use think\annotation\Inject;
|
||||
use think\Exception;
|
||||
use think\exception\ValidateException;
|
||||
use crmeb\services\CacheService;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserBillServices
|
||||
* @package app\services\user
|
||||
* @mixin UserBillDao
|
||||
*/
|
||||
class UserBillServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 用户记录模板
|
||||
* @var array[]
|
||||
*/
|
||||
protected array $incomeData = [
|
||||
'pay_give_integral' => [
|
||||
'title' => '购买商品赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'gain',
|
||||
'mark' => '购买商品赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'order_give_integral' => [
|
||||
'title' => '下单赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'gain',
|
||||
'mark' => '下单赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'order_promotions_give_integral' => [
|
||||
'title' => '下单优惠活动赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'gain',
|
||||
'mark' => '下单优惠活动赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'order_give_exp' => [
|
||||
'title' => '下单赠送经验',
|
||||
'category' => 'exp',
|
||||
'type' => 'gain',
|
||||
'mark' => '下单赠送{%num%}经验',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'integral_refund' => [
|
||||
'title' => '赠送积分回退',
|
||||
'category' => 'integral',
|
||||
'type' => 'deduction',
|
||||
'mark' => '下单赠送积分,回退{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'order_integral_refund' => [
|
||||
'title' => '下单支付积分回退',
|
||||
'category' => 'integral',
|
||||
'type' => 'integral_refund',
|
||||
'mark' => '下单支付积分,回退{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'pay_product_integral_back' => [
|
||||
'title' => '下单抵扣积分回退',
|
||||
'category' => 'integral',
|
||||
'type' => 'pay_product_integral_back',
|
||||
'mark' => '下单抵扣积分,返还{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'deduction' => [
|
||||
'title' => '积分抵扣',
|
||||
'category' => 'integral',
|
||||
'type' => 'deduction',
|
||||
'mark' => '购买商品使用{%number%}积分抵扣{%deductionPrice%}元',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'lottery_use_integral' => [
|
||||
'title' => '参与抽奖使用积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'lottery_use',
|
||||
'mark' => '参与抽奖使用{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'lottery_give_integral' => [
|
||||
'title' => '抽奖中奖赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'lottery_add',
|
||||
'mark' => '抽奖中奖赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'storeIntegral_use_integral' => [
|
||||
'title' => '积分兑换商品',
|
||||
'category' => 'integral',
|
||||
'type' => 'storeIntegral_use',
|
||||
'mark' => '积分商城兑换商品使用{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'system_clear_integral' => [
|
||||
'title' => '到期自动清除积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'system_clear',
|
||||
'mark' => '到期自动清除{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'newcomer_give_integral' => [
|
||||
'title' => '新人礼赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'newcomer_add',
|
||||
'mark' => '新人礼赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'level_give_integral' => [
|
||||
'title' => '会员卡激活赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'level_add',
|
||||
'mark' => '会员卡激活赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'system_add_integral' => [
|
||||
'title' => '系统增加积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'system_add',
|
||||
'mark' => '系统增加了{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'system_sub_integral' => [
|
||||
'title' => '系统减少积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'system_sub',
|
||||
'mark' => '系统扣除了{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'community_add_integral' => [
|
||||
'title' => '发布种草内容奖励积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'community_add_integral',
|
||||
'mark' => '发布种草内容赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'community_add_exp' => [
|
||||
'title' => '发布种草内容奖励经验',
|
||||
'category' => 'exp',
|
||||
'type' => 'community_add_exp',
|
||||
'mark' => '发布种草内容赠送{%num%}经验',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'reply_add_integral' => [
|
||||
'title' => '评价赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'reply_add_integral',
|
||||
'mark' => '评价商品赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'reply_add_exp' => [
|
||||
'title' => '评价赠送经验',
|
||||
'category' => 'exp',
|
||||
'type' => 'reply_add_exp',
|
||||
'mark' => '评价商品赠送{%num%}经验',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'holiday_gift_integral' => [
|
||||
'title' => '节日有礼赠送积分',
|
||||
'category' => 'integral',
|
||||
'type' => 'holiday_gift_integral',
|
||||
'mark' => '节日有礼赠送{%num%}积分',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserBillDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserBillDao $dao;
|
||||
|
||||
/**
|
||||
* 获取用户记录总和
|
||||
* @param int $uid
|
||||
* @param string $category
|
||||
* @param array $type
|
||||
* @param string $time
|
||||
* @param bool $pm
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRecordCount(int $uid, string $category = 'now_money', array $type = [], string $time = '', bool $pm = false)
|
||||
{
|
||||
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['category'] = $category;
|
||||
$where['status'] = 1;
|
||||
|
||||
if (is_string($type) && strlen(trim($type))) {
|
||||
$where['type'] = explode(',', $type);
|
||||
}
|
||||
if ($time) {
|
||||
$where['time'] = $time;
|
||||
}
|
||||
|
||||
$where['pm'] = $pm ? 1 : 0;
|
||||
|
||||
return $this->dao->getBillSumColumn($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分列表
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getIntegralList(int $uid = 0, $where_time = [], string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['category' => 'integral'];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['add_time'] = $where_time;
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
$times = [];
|
||||
if ($list) {
|
||||
foreach ($list as &$item) {
|
||||
$addTime = strtotime($item['add_time']);
|
||||
$item['time_key'] = $item['time'] = $addTime ? date('Y-m', (int)$addTime) : '';
|
||||
$item['day'] = $addTime ? date('Y-m-d', (int)$addTime) : '';
|
||||
$item['number'] = intval($item['number']);
|
||||
$item['balance'] = intval($item['balance']);
|
||||
if (in_array($item['type'], ['system_add', 'system_sub'])) {
|
||||
$item['admin_name'] = app()->make(SystemAdminServices::class)->value(['id' => $item['link_id']], 'real_name');
|
||||
} else {
|
||||
$item['admin_name'] = '';
|
||||
}
|
||||
$item['is_frozen'] = $item['frozen_time'] > time() ? 1 : 0;
|
||||
$item['frozen_time'] = $item['frozen_time'] ? date('Y-m-d H:i:s', (int)$item['frozen_time']) : '';
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
return compact('list', 'count', 'times');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到列表
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getSignList(int $uid = 0, $where_time = [], string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['category' => 'integral', 'type' => 'sign'];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['add_time'] = $where_time;
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 经验总数
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @return float
|
||||
*/
|
||||
public function getExpSum(int $uid = 0, $where_time = [])
|
||||
{
|
||||
$where = ['category' => ['exp'], 'pm' => 1, 'status' => 1];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['time'] = $where_time;
|
||||
return $this->dao->getBillSum($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有经验列表
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getExpList(int $uid = 0, $where_time = [], string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['category' => ['exp']];
|
||||
$where['status'] = 1;
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['time'] = $where_time;
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加积分
|
||||
* @param int $uid
|
||||
* @param string $type
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function incomeIntegral(int $uid, string $type, array $data)
|
||||
{
|
||||
$data['uid'] = $uid;
|
||||
$data['category'] = 'integral';
|
||||
$data['type'] = $type;
|
||||
$data['pm'] = 1;
|
||||
$data['status'] = 1;
|
||||
$data['add_time'] = time();
|
||||
if (!$this->dao->save($data))
|
||||
throw new Exception('增加记录失败');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 写入用户记录
|
||||
* @param string $type 写入类型
|
||||
* @param int $uid
|
||||
* @param int|array|string $number
|
||||
* @param int|string $balance
|
||||
* @param int $link_id
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function income(string $type, int $uid, $number, $balance, $link_id = 0, $obtain_time = 0, $mark = '')
|
||||
{
|
||||
$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(['{%num%}'], (string)$number, $data['mark']);
|
||||
}
|
||||
if ($mark) $data['mark'] = $mark;
|
||||
$data['add_time'] = time();
|
||||
$data['obtain_time'] = $obtain_time;
|
||||
|
||||
if ($type == 'pay_give_integral' || $type == 'order_give_integral') {
|
||||
$integral_frozen = sys_config('integral_frozen');
|
||||
if ($integral_frozen) {
|
||||
$data['frozen_time'] = $data['add_time'] + ($integral_frozen * 86400);
|
||||
}
|
||||
}
|
||||
if ((float)$data['number']) {
|
||||
return $this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请新用户增加经验
|
||||
* @param int $spreadUid
|
||||
*/
|
||||
public function inviteUserIncExp(int $spreadUid)
|
||||
{
|
||||
if (!$spreadUid) {
|
||||
return false;
|
||||
}
|
||||
//用户等级是否开启
|
||||
if (!sys_config('member_func_status', 1)) {
|
||||
return false;
|
||||
}
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$spread_user = $userService->getUserInfo($spreadUid);
|
||||
if (!$spread_user) {
|
||||
return false;
|
||||
}
|
||||
$exp_num = sys_config('invite_user_exp', 0);
|
||||
if ($exp_num) {
|
||||
$userService->incField($spreadUid, 'exp', (int)$exp_num);
|
||||
$balance = bcadd((string)$spread_user['exp'], (string)$exp_num);
|
||||
$data = [];
|
||||
$data['uid'] = $spreadUid;
|
||||
$data['number'] = $exp_num;
|
||||
$data['category'] = 'exp';
|
||||
$data['type'] = 'invite_user';
|
||||
$data['title'] = $data['mark'] = '邀新奖励';
|
||||
$data['balance'] = $balance;
|
||||
$data['pm'] = 1;
|
||||
$data['status'] = 1;
|
||||
$this->dao->save($data);
|
||||
}
|
||||
//检测会员升级
|
||||
UserLevelJob::dispatch([$spreadUid]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取type
|
||||
* @param array $where
|
||||
* @param string $filed
|
||||
*/
|
||||
public function getBillType(array $where)
|
||||
{
|
||||
return $this->dao->getType($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资金类型
|
||||
*/
|
||||
public function bill_type()
|
||||
{
|
||||
$where = [];
|
||||
$where['not_type'] = ['gain', 'system_sub', 'deduction', 'sign'];
|
||||
$where['not_category'] = ['exp', 'integral'];
|
||||
return CacheService::get('user_type_list', function () use ($where) {
|
||||
return ['list' => $this->dao->getType($where)];
|
||||
}, 600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录分享次数
|
||||
* @param int $uid 用户uid
|
||||
* @param int $cd 冷却时间
|
||||
* @return Boolean
|
||||
* */
|
||||
public function setUserShare(int $uid, $cd = 300)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('用户不存在!');
|
||||
}
|
||||
$cachename = 'Share_' . $uid;
|
||||
if (CacheService::get($cachename)) {
|
||||
return false;
|
||||
}
|
||||
$data = ['title' => '用户分享记录', 'uid' => $uid, 'category' => 'share', 'type' => 'share', 'number' => 0, 'link_id' => 0, 'balance' => 0, 'mark' => date('Y-m-d H:i:s', time()) . ':用户分享'];
|
||||
if (!$this->dao->save($data)) {
|
||||
throw new ValidateException('记录分享记录失败');
|
||||
}
|
||||
CacheService::set($cachename, 1, $cd);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getPointList(array $where, string $field = '*', int $limit = 0)
|
||||
{
|
||||
$where_data = [];
|
||||
$where_data['category'] = 'integral';
|
||||
if (isset($where['uid']) && $where['uid'] != '') {
|
||||
$where_data['uid'] = $where['uid'];
|
||||
}
|
||||
if ($where['start_time'] != '' && $where['end_time'] != '') {
|
||||
$where_data['time'] = $where['start_time'] . ' - ' . $where['end_time'];
|
||||
}
|
||||
if (isset($where['type']) && $where['type'] != '') {
|
||||
$where_data['type'] = $where['type'];
|
||||
}
|
||||
if (isset($where['nickname']) && $where['nickname'] != '') {
|
||||
$where_data['like'] = $where['nickname'];
|
||||
}
|
||||
if (isset($where['excel']) && $where['excel'] != '') {
|
||||
$where_data['excel'] = $where['excel'];
|
||||
} else {
|
||||
$where_data['excel'] = 0;
|
||||
}
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$list = $this->dao->getBillList($where_data, $field, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['number'] = intval($item['number']);
|
||||
$item['balance'] = intval($item['balance']);
|
||||
unset($item['user']);
|
||||
}
|
||||
$count = $this->dao->count($where_data);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分头部信息
|
||||
* @param array $where
|
||||
* @return array[]
|
||||
*/
|
||||
public function getUserPointBadgelist(array $where)
|
||||
{
|
||||
$data = [];
|
||||
$where_data = [];
|
||||
$where_data['category'] = 'integral';
|
||||
if ($where['start_time'] != '' && $where['end_time'] != '') {
|
||||
$where_data['time'] = $where['start_time'] . ' - ' . $where['end_time'];
|
||||
}
|
||||
if (isset($where['nickname']) && $where['nickname'] != '') {
|
||||
$where_data['like'] = $where['nickname'];
|
||||
}
|
||||
$data['SumIntegral'] = intval($this->dao->getBillSumColumn($where_data + ['pm' => 1, 'not_type' => [
|
||||
'integral_refund',
|
||||
'order_integral_refund',
|
||||
'pay_product_integral_back',
|
||||
]]));
|
||||
$where_data['type'] = 'sign';
|
||||
$data['CountSign'] = $this->dao->getUserSignPoint($where_data);
|
||||
$data['SumSign'] = intval($this->dao->getBillSumColumn($where_data));
|
||||
unset($where_data['type']);
|
||||
$data['SumDeductionIntegral'] = intval($this->dao->getBillSumColumn($where_data + ['pm' => 0]));
|
||||
return [
|
||||
[
|
||||
'col' => 6,
|
||||
'count' => $data['SumIntegral'],
|
||||
'name' => '总积分(个)',
|
||||
],
|
||||
[
|
||||
'col' => 6,
|
||||
'count' => $data['CountSign'],
|
||||
'name' => '客户签到次数(次)',
|
||||
],
|
||||
[
|
||||
'col' => 6,
|
||||
'count' => $data['SumSign'],
|
||||
'name' => '签到送出积分(个)',
|
||||
],
|
||||
[
|
||||
'col' => 6,
|
||||
'count' => $data['SumDeductionIntegral'],
|
||||
'name' => '使用积分(个)',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uid
|
||||
* @param $type
|
||||
* @return array
|
||||
*/
|
||||
public function getUserBillList(int $uid, int $type)
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['category'] = 'now_money';
|
||||
switch ((int)$type) {
|
||||
case 0:
|
||||
$where['type'] = ['recharge', 'pay_money', 'system_add', 'pay_product_refund', 'system_sub', 'pay_member', 'offline_scan', 'lottery_use', 'lottery_add'];
|
||||
break;
|
||||
case 1:
|
||||
$where['type'] = ['pay_money', 'pay_member', 'offline_scan', 'user_recharge_refund', 'lottery_use'];
|
||||
break;
|
||||
case 2:
|
||||
$where['type'] = ['recharge', 'system_add', 'lottery_add'];
|
||||
break;
|
||||
case 3:
|
||||
$where['type'] = ['brokerage', 'brokerage_user'];
|
||||
break;
|
||||
case 4:
|
||||
$where['type'] = ['extract'];
|
||||
break;
|
||||
}
|
||||
$field = 'FROM_UNIXTIME(add_time,"%Y-%m") as time,group_concat(id SEPARATOR ",") ids';
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getUserBillListByGroup($where, $field, 'time', $page, $limit);
|
||||
$data = [];
|
||||
if ($list) {
|
||||
$listIds = array_column($list, 'ids');
|
||||
$ids = [];
|
||||
foreach ($listIds as $id) {
|
||||
$ids = array_merge($ids, explode(',', $id));
|
||||
}
|
||||
$info = $this->dao->getColumn([['id', 'in', $ids]], 'FROM_UNIXTIME(add_time,"%Y-%m-%d %H:%i") as add_time,title,number,pm', 'id');
|
||||
foreach ($list as $item) {
|
||||
$value['time'] = $item['time'];
|
||||
$id = explode(',', $item['ids']);
|
||||
array_multisort($id, SORT_DESC);
|
||||
$value['list'] = [];
|
||||
foreach ($id as $v) {
|
||||
if (isset($info[$v])) {
|
||||
$value['list'][] = $info[$v];
|
||||
}
|
||||
}
|
||||
$data[] = $value;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
56
app/services/user/UserBrokerageFrozenServices.php
Normal file
56
app/services/user/UserBrokerageFrozenServices.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
|
||||
use app\dao\user\UserBrokerageFrozenDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 佣金冻结
|
||||
* Class UserBrokerageFrozenServices
|
||||
* @package app\services\user
|
||||
* @mixin UserBrokerageFrozenDao
|
||||
*/
|
||||
class UserBrokerageFrozenServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserBrokerageFrozenDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserBrokerageFrozenDao $dao;
|
||||
|
||||
/**
|
||||
* 保存冻结金额
|
||||
* @param int $uid
|
||||
* @param string $price
|
||||
* @param int $uillId
|
||||
* @param string $orderId
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveBrokage(int $uid, string $price, int $uillId, string $orderId)
|
||||
{
|
||||
$broken_time = intval(sys_config('extract_time'));
|
||||
$data = [
|
||||
'uid' => $uid,
|
||||
'price' => $price,
|
||||
'uill_id' => $uillId,
|
||||
'order_id' => $orderId,
|
||||
'add_time' => time(),
|
||||
'status' => 1,
|
||||
'frozen_time' => time() + $broken_time * 86400
|
||||
];
|
||||
return $this->dao->save($data);
|
||||
}
|
||||
}
|
||||
893
app/services/user/UserBrokerageServices.php
Normal file
893
app/services/user/UserBrokerageServices.php
Normal file
@@ -0,0 +1,893 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\dao\user\UserBrokerageDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\message\service\StoreServiceServices;
|
||||
use app\services\order\StoreOrderCartInfoServices;
|
||||
use app\services\order\StoreOrderServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use crmeb\services\CacheService;
|
||||
|
||||
/**
|
||||
* 用户佣金
|
||||
* Class UserBrokerageServices
|
||||
* @package app\services\user
|
||||
* @mixin UserBrokerageDao
|
||||
*/
|
||||
class UserBrokerageServices extends BaseServices
|
||||
{
|
||||
public array $isBrokerage = [
|
||||
'self_brokerage',//自购佣金
|
||||
'one_brokerage',//一级佣金
|
||||
'two_brokerage',//二级佣金
|
||||
'brokerage_user',//推广用户佣金
|
||||
'staff_brokerage',//员工佣金
|
||||
'agent_brokerage',//代理佣金
|
||||
'division_brokerage',//团队佣金
|
||||
];
|
||||
|
||||
/**
|
||||
* 用户记录模板
|
||||
* @var array[]
|
||||
*/
|
||||
protected array $incomeData = [
|
||||
'get_self_brokerage' => [
|
||||
'title' => '获得自购订单佣金',
|
||||
'type' => 'self_brokerage',
|
||||
'mark' => '您成功消费{%pay_price%}元,奖励自购佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'get_brokerage' => [
|
||||
'title' => '获得下级推广订单佣金',
|
||||
'type' => 'one_brokerage',
|
||||
'mark' => '{%nickname%}成功消费{%pay_price%}元,奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'get_two_brokerage' => [
|
||||
'title' => '获得推广订单佣金',
|
||||
'type' => 'two_brokerage',
|
||||
'mark' => '二级推广人{%nickname%}成功消费{%pay_price%}元,奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'get_user_brokerage' => [
|
||||
'title' => '获得推广用户佣金',
|
||||
'type' => 'brokerage_user',
|
||||
'mark' => '成功推广用户:{%nickname%},奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'extract' => [
|
||||
'title' => '佣金提现',
|
||||
'type' => 'extract',
|
||||
'mark' => '{%mark%},佣金提现{%number%}元',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'extract_fail' => [
|
||||
'title' => '提现失败',
|
||||
'type' => 'extract_fail',
|
||||
'mark' => '提现失败,退回佣金{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'brokerage_to_nowMoney' => [
|
||||
'title' => '佣金提现到余额',
|
||||
'type' => 'extract_money',
|
||||
'mark' => '佣金提现到余额{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'brokerage_refund' => [
|
||||
'title' => '退款退佣金',
|
||||
'type' => 'refund',
|
||||
'mark' => '订单退款扣除佣金{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'get_staff_brokerage' => [
|
||||
'title' => '获得员工推广订单佣金',
|
||||
'type' => 'staff_brokerage',
|
||||
'mark' => '{%nickname%}成功消费{%pay_price%}元,奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'get_agent_brokerage' => [
|
||||
'title' => '获得代理推广订单佣金',
|
||||
'type' => 'agent_brokerage',
|
||||
'mark' => '{%nickname%}成功消费{%pay_price%}元,奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'get_division_brokerage' => [
|
||||
'title' => '获得区域代理推广订单佣金',
|
||||
'type' => 'division_brokerage',
|
||||
'mark' => '{%nickname%}成功消费{%pay_price%}元,奖励推广佣金{%number%}',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserBrokerageDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserBrokerageDao $dao;
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户记录总和
|
||||
* @param int $uid
|
||||
* @param string $time
|
||||
* @param bool $pm
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRecordCount(int $uid, $time = '', $pm = false)
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['status'] = 1;
|
||||
if ($time) {
|
||||
$where['time'] = $time;
|
||||
}
|
||||
if ($pm) {
|
||||
$where['pm'] = 0;
|
||||
}
|
||||
return $this->dao->getBrokerageSumColumn($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算佣金
|
||||
* @param array $where
|
||||
* @param int $time
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUsersBokerageSum(array $where, $time = 0)
|
||||
{
|
||||
$where_data = [
|
||||
'status' => 1,
|
||||
'pm' => $where['pm'] ?? '',
|
||||
'uid' => $where['uid'] ?? '',
|
||||
'time' => $where['time'] ?? 0,
|
||||
'type' => $where['type'] ?? '',
|
||||
'not_type' => $where['not_type'] ?? ''
|
||||
];
|
||||
if ($time) $where_data['time'] = $time;
|
||||
return $this->dao->getBrokerageSumColumn($where_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 某个用户佣金总和
|
||||
* @param int $uid
|
||||
* @param array|string[] $type
|
||||
* @param string $time
|
||||
* @return float
|
||||
*/
|
||||
public function getUserBillBrokerageSum(int $uid, array $type = ['self_brokerage', 'one_brokerage', 'two_brokerage', 'brokerage_user', 'staff_brokerage', 'agent_brokerage', 'division_brokerage'], $time = '')
|
||||
{
|
||||
$where = ['uid' => $uid];
|
||||
if ($type) $where['type'] = $type;
|
||||
if ($time) $where['time'] = $time;
|
||||
return $this->dao->getBrokerageSum($where);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户|所有佣金总数
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @return float
|
||||
*/
|
||||
public function getBrokerageCount(int $uid = 0, $where_time = [])
|
||||
{
|
||||
$where = ['category' => 'now_money', 'type' => ['system_add', 'pay_product', 'extract', 'pay_product_refund', 'system_sub'], 'pm' => 1, 'status' => 1];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['add_time'] = $where_time;
|
||||
return $this->dao->getBillCount($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入用户记录
|
||||
* @param string $type 写入类型
|
||||
* @param int $uid
|
||||
* @param int|string|array $number
|
||||
* @param int|string $balance
|
||||
* @param int $link_id
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function income(string $type, int $uid, $number, $balance, $link_id)
|
||||
{
|
||||
$data = $this->incomeData[$type] ?? null;
|
||||
if (!$data) {
|
||||
return true;
|
||||
}
|
||||
$data['uid'] = $uid;
|
||||
$data['balance'] = $balance ?? 0;
|
||||
$data['link_id'] = $link_id;
|
||||
//佣金记录表存放下单用户 uid 和金额
|
||||
if (in_array($data['type'], $this->isBrokerage)) {
|
||||
if ($data['type'] !== 'brokerage_user') {
|
||||
$orderInfo = app()->make(StoreOrderServices::class)->get($link_id, ['uid', 'pay_price']);
|
||||
$data['order_uid'] = $orderInfo['uid'] ?? 0;
|
||||
$data['order_price'] = $orderInfo['pay_price'] ?? 0;
|
||||
} else {
|
||||
$data['order_uid'] = $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['frozen_time'] = $number['frozen_time'] ?? 0;
|
||||
$data['mark'] = str_replace($key, $value, $data['mark']);
|
||||
} else {
|
||||
$data['number'] = $number;
|
||||
$data['mark'] = str_replace(['{%num%}'], (string)$number, $data['mark']);
|
||||
}
|
||||
$data['add_time'] = time();
|
||||
if ((float)$data['number']) {
|
||||
return $this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 资金类型
|
||||
*/
|
||||
public function bill_type()
|
||||
{
|
||||
return CacheService::get('user_brokerage_type_list', function () {
|
||||
return ['list' => $this->dao->getBrokerageType([])];
|
||||
}, 600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资金列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getBrokerageList(array $where, string $field = '*', int $limit = 0)
|
||||
{
|
||||
$where_data = [];
|
||||
if (isset($where['uid']) && $where['uid'] != '') {
|
||||
$where_data['uid'] = $where['uid'];
|
||||
}
|
||||
if ($where['start_time'] != '' && $where['end_time'] != '') {
|
||||
$where_data['time'] = str_replace('-', '/', $where['start_time']) . ' - ' . str_replace('-', '/', $where['end_time']);
|
||||
}
|
||||
if (isset($where['type']) && $where['type'] != '') {
|
||||
$where_data['type'] = $where['type'];
|
||||
}
|
||||
if (isset($where['nickname']) && $where['nickname'] != '') {
|
||||
$where_data['like'] = $where['nickname'];
|
||||
}
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$data = $this->dao->getBrokerageList($where_data, $field, $page, $limit);
|
||||
foreach ($data as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
unset($item['user']);
|
||||
}
|
||||
$count = $this->dao->count($where_data);
|
||||
return compact('data', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取佣金列表
|
||||
* @param array $where
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getCommissionList(array $where, int $limit = 0)
|
||||
{
|
||||
$where_data = [];
|
||||
$where_data['time'] = $where['time'];
|
||||
if (isset($where['nickname']) && $where['nickname']) {
|
||||
$where_data[] = ['u.account|u.nickname|u.uid|u.phone', 'LIKE', "%$where[nickname]%"];
|
||||
}
|
||||
if (isset($where['price_max']) && isset($where['price_min'])) {
|
||||
if ($where['price_max'] != '' && $where['price_min'] != '') {
|
||||
$where_data[] = ['u.brokerage_price', 'between', [$where['price_min'], $where['price_max']]];
|
||||
} elseif ($where['price_min'] != '' && $where['price_max'] == '') {
|
||||
$where_data[] = ['u.brokerage_price', '>=', $where['price_min']];
|
||||
} elseif ($where['price_min'] == '' && $where['price_max'] != '') {
|
||||
$where_data[] = ['u.brokerage_price', '<=', $where['price_max']];
|
||||
}
|
||||
}
|
||||
$order_string = '';
|
||||
$order_arr = ['asc', 'desc'];
|
||||
if (isset($where['sum_number']) && in_array($where['sum_number'], $order_arr)) {
|
||||
$order_string .= ',income ' . $where['sum_number'];
|
||||
}
|
||||
if (isset($where['brokerage_price']) && in_array($where['brokerage_price'], $order_arr)) {
|
||||
$order_string .= ',u.brokerage_price ' . $where['brokerage_price'];
|
||||
}
|
||||
if ($order_string) {
|
||||
$order_string = trim($order_string, ',');
|
||||
}
|
||||
/** @var UserUserBrokerageServices $userUserBrokerage */
|
||||
$userUserBrokerage = app()->make(UserUserBrokerageServices::class);
|
||||
[$count, $list] = $userUserBrokerage->getBrokerageList($where_data, 'b.type,b.pm,sum(IF(b.pm = 1, b.number, 0)) as income,sum(IF(b.pm = 0, b.number, 0)) as pay,u.nickname,u.phone,u.uid,u.now_money,u.brokerage_price,u.delete_time,b.add_time as time', $order_string, $limit);
|
||||
$uids = array_unique(array_column($list, 'uid'));
|
||||
/** @var UserExtractServices $userExtract */
|
||||
$userExtract = app()->make(UserExtractServices::class);
|
||||
$extractSumList = $userExtract->getUsersSumList($uids);
|
||||
foreach ($list as &$item) {
|
||||
// $item['sum_number'] = $item['income'] > $item['pay'] ? bcsub($item['income'], $item['pay'], 2) : 0;
|
||||
$item['nickname'] = $item['nickname'] . "|" . ($item['phone'] ? $item['phone'] . "|" : '') . $item['uid'];
|
||||
$item['extract_price'] = $extractSumList[$item['uid']] ?? 0;
|
||||
$item['sum_number'] = bcadd((string)$item['extract_price'], (string)$item['brokerage_price'], 2);
|
||||
$item['time'] = $item['time'] ? date('Y-m-d H:i:s', $item['time']) : '';
|
||||
}
|
||||
return compact('count', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户佣金详情
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function user_info(int $uid)
|
||||
{
|
||||
/** @var UserServices $user */
|
||||
$user = app()->make(UserServices::class);
|
||||
$user_info = $user->getUserWithTrashedInfo($uid, 'nickname,spread_uid,now_money,brokerage_price,add_time');
|
||||
if (!$user_info) {
|
||||
throw new ValidateException('您查看的用户信息不存在!');
|
||||
}
|
||||
$user_info = $user_info->toArray();
|
||||
$income = $this->getUserBillBrokerageSum($uid);
|
||||
$expend = $this->getUserBillBrokerageSum($uid, ['refund']);
|
||||
$number = (float)bcsub((string)$income, (string)$expend, 2);
|
||||
$user_info['number'] = max($number, 0);
|
||||
$user_info['add_time'] = date('Y-m-d H:i:s', $user_info['add_time']);
|
||||
$user_info['spread_name'] = $user_info['spread_uid'] ? $user->getUserInfo((int)$user_info['spread_uid'], 'nickname', true)['nickname'] ?? '' : '';
|
||||
return compact('user_info');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退佣金
|
||||
* @param $order
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function orderRefundBrokerageBack($order)
|
||||
{
|
||||
$id = (int)$order['id'];
|
||||
$where = [
|
||||
'uid' => [$order['spread_uid'], $order['spread_two_uid'], $order['division_staff_id'], $order['division_agent_id'], $order['division_id']],
|
||||
'type' => ['self_brokerage', 'one_brokerage', 'two_brokerage', 'staff_brokerage', 'agent_brokerage', 'division_brokerage'],
|
||||
'link_id' => $id,
|
||||
'pm' => 1
|
||||
];
|
||||
$brokerageList = $this->dao->getUserBrokerageList($where);
|
||||
//子订单
|
||||
if (!$brokerageList && $order['pid']) {
|
||||
$where['link_id'] = $order['pid'];
|
||||
$p_brokerageList = $this->dao->getUserBrokerageList($where);
|
||||
//主订单已分佣 子订单按订单拆分后计算结果回退
|
||||
if ($p_brokerageList) {
|
||||
$brokerageList = [
|
||||
['uid' => $order['spread_uid'], 'number' => $order['one_brokerage']],
|
||||
['uid' => $order['spread_two_uid'], 'number' => $order['two_brokerage']],
|
||||
];
|
||||
}
|
||||
}
|
||||
$res = true;
|
||||
if ($brokerageList) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$brokerages = $userServices->getColumn([['uid', 'in', array_column($brokerageList, 'uid')]], 'brokerage_price', 'uid');
|
||||
$brokerageData = [];
|
||||
|
||||
foreach ($brokerageList as $item) {
|
||||
if (!$item['uid'] || $item['uid'] <= 0) continue;
|
||||
$usermoney = $brokerages[$item['uid']] ?? 0;
|
||||
if ($item['number'] > $usermoney) {
|
||||
$item['number'] = $usermoney;
|
||||
}
|
||||
$res = $res && $userServices->bcDec($item['uid'], 'brokerage_price', (string)$item['number'], 'uid', 2, false);
|
||||
$brokerageData[] = [
|
||||
'title' => '退款退佣金',
|
||||
'uid' => $item['uid'],
|
||||
'pm' => 0,
|
||||
'add_time' => time(),
|
||||
'type' => 'refund',
|
||||
'number' => $item['number'],
|
||||
'link_id' => $id,
|
||||
'balance' => bcsub((string)$usermoney, (string)$item['number'], 2),
|
||||
'mark' => '订单退款扣除佣金' . floatval($item['number']) . '元'
|
||||
];
|
||||
}
|
||||
if ($brokerageData) {
|
||||
$res = $res && $this->dao->saveAll($brokerageData);
|
||||
}
|
||||
//修改佣金冻结时间
|
||||
// $this->dao->update($where, ['frozen_time' => 0]);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 佣金排行
|
||||
* @param string $time
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function brokerageRankList(string $time = 'week')
|
||||
{
|
||||
$where = [];
|
||||
if ($time) {
|
||||
$where['time'] = $time;
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->brokerageRankList($where, $page, $limit);
|
||||
foreach ($list as $key => &$item) {
|
||||
if (!isset($item['user']) || !$item['user'] || $item['brokerage_price'] <= 0) {
|
||||
unset($list[$key]);
|
||||
continue;
|
||||
}
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['avatar'] = $item['user']['avatar'] ?? '';
|
||||
if ($item['brokerage_price'] == '0.00' || $item['brokerage_price'] == 0 || !$item['brokerage_price']) {
|
||||
unset($list[$key]);
|
||||
}
|
||||
unset($item['user']);
|
||||
}
|
||||
return array_merge($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户排名
|
||||
* @param int $uid
|
||||
* @param string $time
|
||||
*/
|
||||
public function getUserBrokerageRank(int $uid, string $time = 'week')
|
||||
{
|
||||
$where = [];
|
||||
if ($time) {
|
||||
$where['time'] = $time;
|
||||
}
|
||||
$list = $this->dao->brokerageRankList($where);
|
||||
foreach ($list as $key => &$item) {
|
||||
if (!isset($item['user']) || !$item['user'] || $item['brokerage_price'] <= 0) {
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
$position_tmp_one = array_column($list, 'uid');
|
||||
$position_tmp_two = array_column($list, 'brokerage_price', 'uid');
|
||||
$brokerage_price = $position_tmp_two[$uid] ?? 0;
|
||||
if (!in_array($uid, $position_tmp_one)) {
|
||||
$position = 0;
|
||||
} else {
|
||||
if ($position_tmp_two[$uid] == 0.00) {
|
||||
$position = 0;
|
||||
} else {
|
||||
$position = array_search($uid, $position_tmp_one) + 1;
|
||||
}
|
||||
}
|
||||
return compact('position', 'brokerage_price');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 推广数据 昨天的佣金 累计提现金额 当前佣金
|
||||
* @param int $uid
|
||||
* @return mixed
|
||||
*/
|
||||
public function commission(int $uid)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if (!$userServices->userExist($uid)) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
/** @var UserExtractServices $userExtract */
|
||||
$userExtract = app()->make(UserExtractServices::class);
|
||||
$data = [];
|
||||
$data['uid'] = $uid;
|
||||
$data['pm'] = 1;
|
||||
$data['commissionSum'] = $this->getUsersBokerageSum($data);
|
||||
$data['pm'] = 0;
|
||||
$data['commissionRefund'] = $this->getUsersBokerageSum($data);
|
||||
$data['commissionCount'] = $data['commissionSum'] > $data['commissionRefund'] ? bcsub((string)$data['commissionSum'], (string)$data['commissionRefund'], 2) : 0.00;
|
||||
$data['lastDayCount'] = $this->getUsersBokerageSum($data, 'yesterday');//昨天的佣金
|
||||
$data['extractCount'] = $userExtract->getUserExtract($uid);//累计提现金额
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端佣金排行页面数据
|
||||
* @param int $uid
|
||||
* @param $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function brokerage_rank(int $uid, $type)
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
if (!$userService->userExist($uid)) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$rankList = $this->getUserBrokerageRank($uid, $type);
|
||||
return [
|
||||
'rank' => $this->brokerageRankList($type),
|
||||
'position' => $rankList['position'],
|
||||
'brokerage_price' => $rankList['brokerage_price'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广 佣金/提现 总和
|
||||
* @param int $uid
|
||||
* @param $type 3 佣金 4 提现
|
||||
* @return mixed
|
||||
*/
|
||||
public function spread_count(int $uid, $type)
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
if (!$userService->userExist($uid)) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$count = 0;
|
||||
if ($type == 3) {
|
||||
$where = [
|
||||
'uid' => $uid,
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
];
|
||||
$count1 = $this->dao->getBrokerageSumColumn($where);
|
||||
$where['pm'] = 0;
|
||||
$count2 = $this->dao->getBrokerageSumColumn($where);
|
||||
$count = $count1 - $count2;
|
||||
} else if ($type == 4) {
|
||||
/** @var UserExtractServices $userExtract */
|
||||
$userExtract = app()->make(UserExtractServices::class);
|
||||
$count = $userExtract->getUserExtract($uid);//累计提现
|
||||
}
|
||||
return $count ? $count : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广订单
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function spreadOrderList(int $uid, array $data, int $page = 0, int $limit = 0)
|
||||
{
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
|
||||
$where = ['pid' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'is_del' => 0, 'is_system_del' => 0, 'division_spread' => $uid];
|
||||
if ($data['start'] || $data['stop']) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
$where['real_name'] = $data['keyword'] ?? '';
|
||||
$count = $storeOrderServices->count($where);
|
||||
$list = $storeOrderServices->getList($where, ['id,order_id,uid,add_time,spread_uid,status,spread_two_uid,one_brokerage,two_brokerage,pay_price,cart_id,division_id,division_brokerage,division_agent_id,division_agent_brokerage,division_staff_id,division_staff_brokerage'], $page, $limit, ['brokerage' => function ($query) use ($uid) {
|
||||
$query->where('uid', $uid);
|
||||
}]);
|
||||
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户贡献
|
||||
* @param int $uid
|
||||
* @param $order
|
||||
* @return array
|
||||
* @throws \ReflectionException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/11/23 下午2:18
|
||||
*/
|
||||
public function contribute(int $uid, $order = 'order_count')
|
||||
{
|
||||
$userService = app()->make(UserServices::class);
|
||||
if (!in_array($order, ['order_price', 'order_count', 'brokerage'])) {
|
||||
throw new ValidateException('参数错误');
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$order = 'total_' . $order . ' desc';
|
||||
$list = $this->dao->search(['uid' => $uid])->whereIn('type', $this->isBrokerage)
|
||||
->group('order_uid')->field("sum(order_price) as total_order_price,sum(number) as total_brokerage,count(*) as total_order_count,order_uid")
|
||||
->order($order)->page($page, $limit)->select()->toArray();
|
||||
foreach ($list as &$item) {
|
||||
$userInfo = $userService->getUserCacheInfo($item['order_uid']);
|
||||
$item['nickname'] = $userInfo['nickname'] ?? '';
|
||||
$item['avatar'] = $userInfo['avatar'] ?? '';
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据总览
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array[]
|
||||
* User: liusl
|
||||
* DateTime: 2024/11/23 下午12:12
|
||||
*/
|
||||
public function overview(int $uid, array $data)
|
||||
{
|
||||
$where = [];
|
||||
if ($data['start'] || $data['stop']) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
//推广用户
|
||||
$user_count = app()->make(UserServices::class)->count($where + ['spread_uid' => $uid]);
|
||||
//提现次数
|
||||
$extract_count = app()->make(UserExtractServices::class)->count($where + ['uid' => $uid, 'status' => 1]);
|
||||
//提现金额
|
||||
$extract_price = app()->make(UserExtractServices::class)->sum($where + ['uid' => $uid, 'status' => 1], 'extract_price', true);
|
||||
|
||||
$_data = $this->spreadOrderList($uid, $data);
|
||||
$list = $_data['list'];
|
||||
$brokerage = $order_price = '0.00';
|
||||
$order_count = count($list);
|
||||
foreach ($list as $item) {
|
||||
$brokerageMap = [
|
||||
$item['spread_uid'] => $item['one_brokerage'],
|
||||
$item['spread_two_uid'] => $item['two_brokerage'],
|
||||
$item['division_id'] => $item['division_brokerage'],
|
||||
$item['division_agent_id'] => $item['division_agent_brokerage'],
|
||||
$item['division_staff_id'] => $item['division_staff_brokerage']
|
||||
];
|
||||
$_brokerage = $brokerageMap[$uid] ?? '';
|
||||
$order_price = bcadd((string)$order_price, (string)$item['pay_price'], 2);
|
||||
$brokerage = bcadd((string)$brokerage, (string)$_brokerage, 2);
|
||||
}
|
||||
return [
|
||||
[
|
||||
'name' => '推广用户数',
|
||||
'value' => $user_count
|
||||
],
|
||||
[
|
||||
'name' => '提现次数',
|
||||
'value' => $extract_count
|
||||
],
|
||||
[
|
||||
'name' => '提现金额',
|
||||
'value' => $extract_price
|
||||
],
|
||||
[
|
||||
'name' => '推广佣金',
|
||||
'value' => $brokerage
|
||||
],
|
||||
[
|
||||
'name' => '订单金额',
|
||||
'value' => $order_price
|
||||
],
|
||||
[
|
||||
'name' => '订单数',
|
||||
'value' => $order_count
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广订单收入
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2024/11/22 上午10:40
|
||||
*/
|
||||
public function orderIncome(int $uid, array $data)
|
||||
{
|
||||
$_data = $this->spreadOrderList($uid, $data);
|
||||
$list = $_data['list'];
|
||||
$order_count = $brokerage = $no_brokerage = $no_order_count = 0;
|
||||
foreach ($list as $item) {
|
||||
$brokerageMap = [
|
||||
$item['spread_uid'] => $item['one_brokerage'],
|
||||
$item['spread_two_uid'] => $item['two_brokerage'],
|
||||
$item['division_id'] => $item['division_brokerage'],
|
||||
$item['division_agent_id'] => $item['division_agent_brokerage'],
|
||||
$item['division_staff_id'] => $item['division_staff_brokerage']
|
||||
];
|
||||
$_brokerage = $brokerageMap[$uid] ?? '';
|
||||
if ($item['status'] < 2) {
|
||||
$no_order_count++;
|
||||
$no_brokerage = bcadd((string)$no_brokerage, (string)$_brokerage, 2);
|
||||
} else {
|
||||
$brokerage = bcadd((string)$brokerage, (string)$_brokerage, 2);
|
||||
$order_count++;
|
||||
}
|
||||
}
|
||||
return ['order_count' => $order_count, 'no_order_count' => $no_order_count, 'brokerage' => $brokerage, 'no_brokerage' => $no_brokerage];
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广订单
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function spread_order(int $uid, array $data)
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
/** @var StoreOrderServices $storeOrderServices */
|
||||
$storeOrderServices = app()->make(StoreOrderServices::class);
|
||||
if (!$userService->userExist($uid)) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$result = ['list' => [], 'time' => [], 'count' => 0];
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$_data = $this->spreadOrderList($uid, $data, $page, $limit);
|
||||
$list = $_data['list'];
|
||||
$count = $_data['count'];
|
||||
if ($list) {
|
||||
/** @var StoreOrderCartInfoServices $cartInfoServices */
|
||||
$cartInfoServices = app()->make(StoreOrderCartInfoServices::class);
|
||||
$uids = array_unique(array_column($list, 'uid'));
|
||||
$userInfos = $userService->getColumn([['uid', 'in', $uids]], 'uid,avatar,nickname', 'uid');
|
||||
foreach ($list as &$item) {
|
||||
$item['store_name'] = $cartInfoServices->getCarIdByProductTitle((int)$item['id']);
|
||||
$item['avatar'] = $userInfos[$item['uid']]['avatar'] ?? '';
|
||||
$item['nickname'] = $userInfos[$item['uid']]['nickname'] ?? '';
|
||||
$item['number'] = $item['spread_uid'] == $uid ? $item['one_brokerage'] : $item['two_brokerage'];
|
||||
if ($item['division_id'] == $uid) $item['number'] = $item['division_brokerage'];
|
||||
if ($item['division_agent_id'] == $uid) $item['number'] = $item['division_agent_brokerage'];
|
||||
if ($item['division_staff_id'] == $uid) $item['number'] = $item['division_staff_brokerage'];
|
||||
$item['time_key'] = $item['add_time'] ? date('Y-m', $item['add_time']) : '';
|
||||
$item['type'] = in_array($item['status'], [2, 3]) ? 'brokerage' : 'number';
|
||||
$brokerage = $item['brokerage'];
|
||||
$time = $brokerage['add_time'] ?? $item['add_time'];
|
||||
$item['time'] = $time ? date('Y-m-d H:i', $time) : '';
|
||||
$item['is_frozen'] = $brokerage && $brokerage['frozen_time'] > time() ? 1 : 0;
|
||||
unset($item['brokerage']);
|
||||
}
|
||||
}
|
||||
$times = array_unique(array_column($list, 'time_key'));
|
||||
$time_data = [];
|
||||
$i = 0;
|
||||
$where = ['pid' => 0, 'type' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'is_del' => 0, 'is_system_del' => 0, 'division_spread' => $uid];
|
||||
if ($data['start'] || $data['stop']) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
$where['real_name'] = $data['keyword'] ?? '';
|
||||
foreach ($times as $time) {
|
||||
$time_data[$i]['time'] = $time;
|
||||
$time_data[$i]['count'] = $storeOrderServices->getMonthCount($where, $time);
|
||||
$time_data[$i]['sumPrice'] = $storeOrderServices->getMonthMoneyCount($where, $time, 'pay_price');
|
||||
$i++;
|
||||
}
|
||||
$result['list'] = $list;
|
||||
$result['time'] = $time_data;
|
||||
$result['count'] = $count;
|
||||
$priceWhere = ['pid' => 0, 'type' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'is_del' => 0, 'is_system_del' => 0];
|
||||
if ($data['start'] || $data['stop']) {
|
||||
$priceWhere['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
//条件获取一级佣金总和
|
||||
$sum_price_one = $storeOrderServices->sum($priceWhere + ['spread_uid' => $uid], 'one_brokerage', true);
|
||||
$sum_price_two = $storeOrderServices->sum($priceWhere + ['spread_two_uid' => $uid], 'two_brokerage', true);
|
||||
$sum_price_division = $storeOrderServices->sum($priceWhere + ['division_id' => $uid], 'division_brokerage', true);
|
||||
$sum_price_agent = $storeOrderServices->sum($priceWhere + ['division_agent_id' => $uid], 'division_agent_brokerage', true);
|
||||
$sum_price_staff = $storeOrderServices->sum($priceWhere + ['division_staff_id' => $uid], 'division_staff_brokerage', true);
|
||||
$result['sum_brokerage'] = bcadd(bcadd(bcadd(bcadd((string)$sum_price_one, (string)$sum_price_two, 2), (string)$sum_price_division, 2), (string)$sum_price_agent, 2), (string)$sum_price_staff, 2);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户佣金记录v2
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function userBrokerageList(int $uid, $data = [])
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
if ($data['start'] || $data['stop']) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
$where['like'] = $data['keyword'];
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
$times = [];
|
||||
if ($list) {
|
||||
$extracts = [];
|
||||
$extractList = function ($types) {
|
||||
return in_array($types['type'], ['extract', 'extract_fail']);
|
||||
};
|
||||
$extractIds = array_column(array_filter($list, $extractList), 'link_id', 'id');
|
||||
/** @var UserExtractServices $userExtractServices */
|
||||
$userExtractServices = app()->make(UserExtractServices::class);
|
||||
if ($extractIds) {
|
||||
$extracts = $userExtractServices->search(['id' => $extractIds])->column('status,fail_msg,order_id,wechat_state,extract_type', 'id');
|
||||
}
|
||||
foreach ($list as &$item) {
|
||||
if ($item['type'] == 'extract_money') {
|
||||
$item['extract_status'] = 1;
|
||||
} else {
|
||||
$item['extract_status'] = $extracts[$item['link_id']]['status'] ?? 0;
|
||||
}
|
||||
$item['extract_msg'] = $extracts[$item['link_id']]['fail_msg'] ?? '';
|
||||
$wechat_state = $extracts[$item['link_id']]['wechat_state'] ?? '';
|
||||
$extract_type = $extracts[$item['link_id']]['extract_type'] ?? '';
|
||||
$item['wechat_state'] = 0;
|
||||
if ($extract_type == 'weixin' && $wechat_state == 'WAIT_USER_CONFIRM' && sys_config('pay_wechat_type') == 1) {
|
||||
$item['wechat_state'] = 1;
|
||||
}
|
||||
$item['extract_order_id'] = $extracts[$item['link_id']]['order_id'] ?? '';
|
||||
$item['time_key'] = $item['add_time'] ? date('Y-m', (int)$item['add_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y/m/d H:i', (int)$item['add_time']) : '';
|
||||
$item['is_frozen'] = $item['frozen_time'] > time() ? 1 : 0;
|
||||
$item['frozen_time'] = $item['frozen_time'] ? date('Y/m/d H:i', (int)$item['frozen_time']) : '';
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
$income = $this->dao->sum($where + ['pm' => 1, 'not_type' => ['extract_fail']], 'number', true);
|
||||
$expend = $this->dao->sum($where + ['pm' => 0], 'number', true);
|
||||
return ['list' => $list, 'time' => $times, 'income' => $income, 'expend' => $expend];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户提现记录v2
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function userExtractList(int $uid, array $data = [])
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['type'] = ['extract', 'extract_money', 'extract_fail'];
|
||||
if ((isset($data['start']) && $data['start']) || (isset($data['stop']) && $data['stop'])) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
$times = [];
|
||||
if ($list) {
|
||||
foreach ($list as &$item) {
|
||||
$item['time_key'] = $item['add_time'] ? date('Y-m', (int)$item['add_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y/m/d H:i', (int)$item['add_time']) : '';
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
return ['list' => $list, 'time' => $times];
|
||||
}
|
||||
}
|
||||
223
app/services/user/UserCardServices.php
Normal file
223
app/services/user/UserCardServices.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserCardDao;
|
||||
use app\services\store\SystemStoreStaffServices;
|
||||
use app\services\wechat\WechatCardServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use crmeb\services\wechat\OfficialAccount;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 用户领取卡券
|
||||
* Class UserCardServices
|
||||
* @package app\services\user
|
||||
* @mixin UserCardDao
|
||||
*/
|
||||
class UserCardServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 激活会员卡微信字段对应eb_user字段
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $userField = [
|
||||
'USER_FORM_INFO_FLAG_MOBILE' => 'phone',
|
||||
'USER_FORM_INFO_FLAG_BIRTHDAY' => 'birthday'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserCardDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserCardDao $dao;
|
||||
|
||||
/**
|
||||
* 用户领取微信会员卡事件
|
||||
* @param $message
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function userGetCard($message)
|
||||
{
|
||||
if (isset($message['CardId'])) {
|
||||
$card_id = $message['CardId'];
|
||||
$openid = $message['FromUserName'];
|
||||
/** @var WechatCardServices $wechatCardServices */
|
||||
$wechatCardServices = app()->make(WechatCardServices::class);
|
||||
$card = $wechatCardServices->getOne(['card_id' => $card_id]);
|
||||
if ($card) {
|
||||
$staffInfo = [];
|
||||
$uid = (int)$message['OuterId'];
|
||||
if ($uid) {
|
||||
try {
|
||||
/** @var SystemStoreStaffServices $staffServices */
|
||||
$staffServices = app()->make(SystemStoreStaffServices::class);
|
||||
$staffInfo = $staffServices->getStaffInfoByUid($uid);
|
||||
} catch (\Throwable $e) {
|
||||
$staffInfo = [];
|
||||
}
|
||||
}
|
||||
$data = [
|
||||
'openid' => $openid,
|
||||
'card_id' => $card_id,
|
||||
'code' => $message['UserCardCode'],
|
||||
'wechat_card_id' => $card['id'],
|
||||
'staff_id' => $staffInfo['id'] ?? 0,
|
||||
'store_id' => $staffInfo['store_id'] ?? 0,
|
||||
'spread_uid' => $uid,
|
||||
'add_time' => time()
|
||||
];
|
||||
$userCard = $this->dao->getOne(['openid' => $openid, 'card_id' => $card_id, 'is_del' => 0]);
|
||||
if ($userCard) {
|
||||
$this->dao->update($userCard['id'], $data);
|
||||
} else {
|
||||
$this->dao->save($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活会员事件
|
||||
* @param $message
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function userSubmitCard($message)
|
||||
{
|
||||
if (isset($message['CardId'])) {
|
||||
$card_id = $message['CardId'];
|
||||
$openid = $message['FromUserName'];
|
||||
/** @var WechatCardServices $wechatCardServices */
|
||||
$wechatCardServices = app()->make(WechatCardServices::class);
|
||||
$card = $wechatCardServices->getOne(['card_id' => $card_id]);
|
||||
if ($card) {
|
||||
$userCard = $this->dao->getOne(['openid' => $openid, 'card_id' => $card_id, 'is_del' => 0]);
|
||||
if ($userCard && !$userCard['is_submit']) {
|
||||
$this->transaction(function () use ($openid, $userCard, $card_id) {
|
||||
|
||||
$data = $this->getWechatCardInfo($card_id, $userCard['code']);
|
||||
/** @var WechatUserServices $wechatUserSerives */
|
||||
$wechatUserSerives = app()->make(WechatUserServices::class);
|
||||
$userInfo = $wechatUserSerives->saveUser($openid, $userCard['spread_uid'], $data['phone']);
|
||||
$this->dao->update($userCard['id'], ['uid' => $userInfo['uid'] ?? 0, 'is_submit' => 1, 'submit_time' => time()]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户激活会员卡填写信息
|
||||
* @param string $card_id
|
||||
* @param string $code
|
||||
* @return array
|
||||
*/
|
||||
public function getWechatCardInfo(string $card_id, string $code)
|
||||
{
|
||||
//获取用户激活填写字段信息
|
||||
$cart = OfficialAccount::getMemberCardUser($card_id, $code);
|
||||
$formList = $cart['user_info']['common_field_list'] ?? [];
|
||||
$userField = $this->userField;
|
||||
$fields = array_keys($userField);
|
||||
$data = [];
|
||||
foreach ($formList as $item) {
|
||||
if (in_array($item['name'], $fields)) {
|
||||
$data[$userField[$item['name']]] = $item['value'];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户删除微信会员卡事件
|
||||
* @param $message
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function userDelCard($message)
|
||||
{
|
||||
if (isset($message['CardId'])) {
|
||||
$card_id = $message['CardId'];
|
||||
$openid = $message['FromUserName'];
|
||||
/** @var WechatCardServices $wechatCardServices */
|
||||
$wechatCardServices = app()->make(WechatCardServices::class);
|
||||
$card = $wechatCardServices->getOne(['card_id' => $card_id]);
|
||||
if ($card) {
|
||||
$userCard = $this->dao->getOne(['openid' => $openid, 'card_id' => $card_id, 'is_del' => 0]);
|
||||
if ($userCard) {
|
||||
$this->dao->update($userCard['id'], ['is_del' => 1, 'del_time' => time()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店推广统计详情列表
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param array $time
|
||||
* @return array|array[]
|
||||
*/
|
||||
public function time(int $store_id, int $staff_id, array $time = [])
|
||||
{
|
||||
if (!$time) {
|
||||
return [[], []];
|
||||
}
|
||||
[$start, $stop, $front, $front_stop] = $time;
|
||||
$where = ['store_id' => $store_id, 'is_submit' => 1];
|
||||
if ($staff_id) {
|
||||
$where['staff_id'] = $staff_id;
|
||||
}
|
||||
$frontPrice = $this->dao->count($where + ['time' => [$front, $front_stop]]);
|
||||
$nowPrice = $this->dao->count($where + ['time' => [$start, $stop]]);
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where + ['time' => [$start, $stop]], '*', ['user'], $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
return [[$nowPrice, $frontPrice], $list];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员卡列表
|
||||
* @param int $uid
|
||||
* @param UserServices $userServices
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getCardList(array $where, string $field = '*', array $with = ['user'])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $field, $with, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
foreach ($list as &$item) {
|
||||
$item['submit_time'] = $item['submit_time'] ? date('Y-m-d H:i:s', $item['submit_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
}
|
||||
158
app/services/user/UserExtendServices.php
Normal file
158
app/services/user/UserExtendServices.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\dao\user\UserCardDao;
|
||||
use app\dao\user\UserExtendDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 用户扩展数据服务
|
||||
* Class UserExtendServices
|
||||
* @package app\services\user
|
||||
* @mixin UserExtendDao
|
||||
*/
|
||||
class UserExtendServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserExtendDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserExtendDao $dao;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户扩展数据列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where = []): array
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户扩展数据
|
||||
* @param int $uid
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserExtendValue(int $uid, string $fieldName): string
|
||||
{
|
||||
$data = $this->dao->getUserFieldData($uid, $fieldName);
|
||||
return $data ? $data['field_value'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户所有扩展数据
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserAllExtendData(int $uid): array
|
||||
{
|
||||
return $this->dao->getUserExtendDataKeyValue($uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户扩展数据
|
||||
* @param int $uid
|
||||
* @param string $fieldName
|
||||
* @param string $fieldValue
|
||||
* @param string $remark
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function setUserExtendData(int $uid, string $fieldName, string $fieldValue, string $remark = ''): bool
|
||||
{
|
||||
if (!$uid || !$fieldName) {
|
||||
throw new AdminException('参数错误');
|
||||
}
|
||||
|
||||
return $this->dao->setUserExtendData($uid, $fieldName, $fieldValue, $remark) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置用户扩展数据
|
||||
* @param int $uid
|
||||
* @param array $extendData
|
||||
* @return bool
|
||||
*/
|
||||
public function setBatchUserExtendData(int $uid, array $extendData): bool
|
||||
{
|
||||
if (!$uid || empty($extendData)) {
|
||||
throw new AdminException('参数错误');
|
||||
}
|
||||
|
||||
return $this->dao->setBatchUserExtendData($uid, $extendData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户扩展数据
|
||||
* @param int $uid
|
||||
* @param string $fieldName
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function deleteUserExtendData(int $uid, string $fieldName = ''): bool
|
||||
{
|
||||
if (!$uid) {
|
||||
throw new AdminException('参数错误');
|
||||
}
|
||||
|
||||
return $this->dao->deleteUserExtendData($uid, $fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存扩展数据
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function save(array $data): bool
|
||||
{
|
||||
if (!isset($data['uid']) || !isset($data['field_name']) || !isset($data['field_value'])) {
|
||||
throw new AdminException('参数错误');
|
||||
}
|
||||
|
||||
return $this->dao->setUserExtendData(
|
||||
(int)$data['uid'],
|
||||
$data['field_name'],
|
||||
$data['field_value'],
|
||||
) !== false;
|
||||
}
|
||||
}
|
||||
617
app/services/user/UserExtractServices.php
Normal file
617
app/services/user/UserExtractServices.php
Normal file
@@ -0,0 +1,617 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\system\CapitalFlowJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserExtractDao;
|
||||
use app\services\order\StoreOrderCreateServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\exceptions\ApiException;
|
||||
use crmeb\services\AliPayService;
|
||||
use crmeb\services\wechat\Payment;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserExtractServices
|
||||
* @package app\services\user
|
||||
* @mixin UserExtractDao
|
||||
*/
|
||||
class UserExtractServices extends BaseServices
|
||||
{
|
||||
public array $wechatState = ['ACCEPTED' => '转账已受理', 'PROCESSING' => '余额不足', 'WAIT_USER_CONFIRM' => '待收款用户确认', 'TRANSFERING' => '转账中', 'SUCCESS' => '转账成功', 'FAIL' => '转账失败', 'CANCELING' => '商户撤销请求受理成功', 'CANCELLED' => '转账撤销完成'];
|
||||
|
||||
/**
|
||||
* @var UserExtractDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserExtractDao $dao;
|
||||
|
||||
/**
|
||||
* 获取一条提现记录
|
||||
* @param int $id
|
||||
* @param array $field
|
||||
* @return array|\think\Model|null
|
||||
*/
|
||||
public function getExtract(int $id, array $field = [])
|
||||
{
|
||||
return $this->dao->get($id, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个用户提现总数
|
||||
* @param int $uid
|
||||
* @return float
|
||||
*/
|
||||
public function getUserExtract(int $uid)
|
||||
{
|
||||
return $this->dao->getWhereSum(['uid' => $uid, 'status' => [0, 1]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某些用户的提现总数列表
|
||||
* @param array $uids
|
||||
*/
|
||||
public function getUsersSumList(array $uids)
|
||||
{
|
||||
return $this->dao->getWhereSumList(['uid' => $uids, 'status' => [0, 1]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现记录总数
|
||||
* @param array $where 查询条件
|
||||
* @return int
|
||||
*/
|
||||
public function getCount(array $where = [])
|
||||
{
|
||||
return $this->dao->getCount($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserExtractList(array $where, string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getExtractList($where, $field, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['wechat_state_text'] = $this->wechatState[$item['wechat_state']] ?? '';
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现总数
|
||||
* @param array $where
|
||||
*/
|
||||
public function getExtractSum(array $where)
|
||||
{
|
||||
//提现金额 + 手续费
|
||||
$price = $this->dao->getExtractMoneyByWhere($where, 'extract_price');
|
||||
$fee = $this->dao->getExtractMoneyByWhere($where, 'extract_fee');
|
||||
return (float)bcadd((string)$price, (string)$fee, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝提现申请
|
||||
* @param $id
|
||||
* @param $fail_msg
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function changeFail(int $id, $userExtract, $message)
|
||||
{
|
||||
$fail_time = time();
|
||||
$extract_number = bcadd((string)$userExtract['extract_price'], (string)$userExtract['extract_fee'], 2);
|
||||
$mark = '提现失败,退回佣金' . $extract_number . '元';
|
||||
$uid = $userExtract['uid'];
|
||||
$status = -1;
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('用户不存在');
|
||||
}
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$this->transaction(function () use ($user, $userBrokerageServices, $uid, $id, $extract_number, $message, $userServices, $status, $fail_time) {
|
||||
$now_brokerage = bcadd((string)$user['brokerage_price'], (string)$extract_number, 2);
|
||||
//增加佣金记录
|
||||
$userBrokerageServices->income('extract_fail', $uid, $extract_number, $now_brokerage, $id);
|
||||
//修改用户佣金
|
||||
if (!$userServices->update($uid, ['brokerage_price' => $now_brokerage], 'uid'))
|
||||
throw new AdminException('增加用户佣金失败');
|
||||
if (!$this->dao->update($id, ['fail_time' => $fail_time, 'fail_msg' => $message, 'status' => $status])) {
|
||||
throw new AdminException('修改失败');
|
||||
}
|
||||
});
|
||||
//消息推送
|
||||
event('notice.notice', [['uid' => $uid, 'userType' => strtolower($user['user_type']), 'extract_number' => $extract_number, 'nickname' => $user['nickname'], 'message' => $message], 'user_balance_change']);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过提现申请
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function changeSuccess(int $id, $userExtract)
|
||||
{
|
||||
$extractNumber = $userExtract['extract_price'];
|
||||
$order_id = $this->transaction(function () use ($id, $userExtract, $extractNumber) {
|
||||
if (!$this->dao->update($id, ['status' => 1])) {
|
||||
throw new AdminException('修改失败');
|
||||
}
|
||||
switch ($userExtract['extract_type']) {
|
||||
case 'bank':
|
||||
$order_id = $userExtract['bank_code'];
|
||||
break;
|
||||
case 'weixin':
|
||||
$order_id = $userExtract['wechat'];
|
||||
$this->processWechatExtract($userExtract, $extractNumber);
|
||||
break;
|
||||
case 'alipay':
|
||||
$order_id = $userExtract['alipay_code'];
|
||||
$this->processAlipayExtract($userExtract, $extractNumber);
|
||||
break;
|
||||
case 'balance'://用户余额账号
|
||||
/** @var UserRechargeServices $userRechargeServices */
|
||||
$userRechargeServices = app()->make(UserRechargeServices::class);
|
||||
$userRechargeServices->importNowMoney((int)$userExtract['uid'], $extractNumber, 'extract');
|
||||
$order_id = $userExtract['id'];
|
||||
break;
|
||||
default:
|
||||
$order_id = '';
|
||||
break;
|
||||
}
|
||||
return $order_id;
|
||||
});
|
||||
if ($userExtract['extract_type'] == 'weixin' && sys_config('pay_wechat_type') == 1) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userType = $userServices->value(['uid' => $userExtract['uid']], 'user_type');
|
||||
$nickname = $userServices->value(['uid' => $userExtract['uid']], 'nickname');
|
||||
$phone = $userServices->value(['uid' => $userExtract['uid']], 'phone');
|
||||
|
||||
//记录资金流水队列
|
||||
CapitalFlowJob::dispatch([['order_id' => $order_id, 'store_id' => 0, 'uid' => $userExtract['uid'], 'nickname' => $nickname, 'phone' => $phone, 'price' => $extractNumber, 'pay_type' => $userExtract['extract_type']], 'extract']);
|
||||
|
||||
//消息推送
|
||||
event('notice.notice', [['uid' => $userExtract['uid'], 'userType' => strtolower($userType), 'extractNumber' => $extractNumber, 'nickname' => $nickname], 'user_extract']);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信提现
|
||||
* @param array $userExtract 提现记录
|
||||
* @param float $extractNumber 提现金额
|
||||
* @return bool
|
||||
*/
|
||||
protected function processWechatExtract($userExtract, $extractNumber)
|
||||
{
|
||||
if (sys_config('brokerage_type', 0)) {
|
||||
/** @var StoreOrderCreateServices $services */
|
||||
$services = app()->make(StoreOrderCreateServices::class);
|
||||
$wechat_order_id = $userExtract['order_id'] ?: $services->getNewOrderId();
|
||||
$transferDetailList = [
|
||||
[
|
||||
'info_type' => '活动名称',
|
||||
'info_content' => '分销员'
|
||||
],
|
||||
[
|
||||
'info_type' => '奖励说明',
|
||||
'info_content' => '佣金提现'
|
||||
],
|
||||
];
|
||||
$res = Payment::merchantPay($userExtract['channel_type'], $userExtract['uid'], $wechat_order_id, (string)$extractNumber, '提现佣金到零钱', $userExtract['user_name'] ?? '用户', $transferDetailList);
|
||||
if (!$res) {
|
||||
throw new ValidateException('企业付款到零钱失败,请稍后再试');
|
||||
}
|
||||
if (sys_config('pay_wechat_type') == 1) {
|
||||
$updateData = [
|
||||
'transfer_bill_no' => $res['transfer_bill_no'] ?? '',
|
||||
'wechat_state' => $res['state'] ?? '',
|
||||
'fail_reason' => $res['fail_reason'] ?? '',
|
||||
'package_info' => $res['package_info'] ?? ''
|
||||
];
|
||||
$this->dao->update($userExtract['id'], $updateData);
|
||||
event('notice.notice', [[
|
||||
'uid' => $userExtract['uid'],
|
||||
'extract_price' => $userExtract['extract_price'],
|
||||
'type' => 1,
|
||||
'order_id' => $userExtract['order_id']
|
||||
], 'revenue_received']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理支付宝提现
|
||||
* @param array $userExtract 提现记录
|
||||
* @param float $extractNumber 提现金额
|
||||
* @return bool
|
||||
*/
|
||||
protected function processAlipayExtract($userExtract, $extractNumber)
|
||||
{
|
||||
if (sys_config('alipay_extract_type', 0)) {
|
||||
// 构造支付宝提现参数
|
||||
$bizParams = [
|
||||
'out_biz_no' => $userExtract['alipay_code'], // 商户订单号
|
||||
'payee_type' => 'ALIPAY_LOGONID', // 收款方账户类型,ALIPAY_LOGONID-支付宝登录账号
|
||||
'payee_account' => $userExtract['alipay_code'], // 收款方账户,实名认证的支付宝账号
|
||||
'amount' => $extractNumber, // 提现金额
|
||||
'payer_show_name' => sys_config('site_name'), // 付款方姓名/个人名称
|
||||
'payee_real_name' => $userExtract['real_name'], // 收款方真实姓名/个人名称
|
||||
'remark' => '提现 ¥' . $extractNumber . ' 到支付宝', // 业务备注
|
||||
];
|
||||
// 调用支付宝服务发起支付宝提现请求
|
||||
$res = AliPayService::instance()->merchantPay($bizParams);
|
||||
// 如果支付宝提现请求失败,则抛出异常
|
||||
if (!$res) {
|
||||
throw new ValidateException('企业付款到零钱失败,请稍后再试');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示资源列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index(array $where)
|
||||
{
|
||||
$list = $this->getUserExtractList($where);
|
||||
//待提现金额
|
||||
$where['status'] = 0;
|
||||
$extract_statistics['price'] = $this->getExtractSum($where);
|
||||
//已提现金额
|
||||
$where['status'] = 1;
|
||||
$extract_statistics['priced'] = $this->getExtractSum($where);
|
||||
//佣金总金额
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$extract_statistics['brokerage_count'] = $userBrokerageServices->getUsersBokerageSum(array_merge($where, ['pm' => 1, 'not_type' => ['extract_fail', 'refund']]));
|
||||
//未提现金额
|
||||
$extract_statistics['brokerage_not'] = $extract_statistics['brokerage_count'] > $extract_statistics['priced'] ? bcsub((string)$extract_statistics['brokerage_count'], (string)$extract_statistics['priced'], 2) : 0.00;
|
||||
return compact('extract_statistics', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示编辑资源表单页.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$UserExtract = $this->getExtract($id);
|
||||
if (!$UserExtract) {
|
||||
throw new AdminException('数据不存在!');
|
||||
}
|
||||
$f = array();
|
||||
$f[] = Form::input('real_name', '姓名', $UserExtract['real_name']);
|
||||
$f[] = Form::number('extract_price', '提现金额', (float)$UserExtract['extract_price'])->disabled(true);
|
||||
if ($UserExtract['extract_type'] == 'alipay') {
|
||||
$f[] = Form::input('alipay_code', '支付宝账号', $UserExtract['alipay_code']);
|
||||
} else if ($UserExtract['extract_type'] == 'weixin') {
|
||||
$f[] = Form::input('wechat', '微信号', $UserExtract['wechat']);
|
||||
} else {
|
||||
$f[] = Form::input('bank_code', '银行卡号', $UserExtract['bank_code']);
|
||||
$f[] = Form::input('bank_address', '开户行', $UserExtract['bank_address']);
|
||||
}
|
||||
$f[] = Form::input('mark', '备注', $UserExtract['mark'])->type('textarea');
|
||||
return create_form('编辑', $f, Url::buildUrl('/finance/extract/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现备注表单
|
||||
* @param int $id 提现记录ID
|
||||
* @return array
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function remarkForm($id)
|
||||
{
|
||||
$UserExtract = $this->getExtract($id);
|
||||
if (!$UserExtract) {
|
||||
throw new AdminException('数据不存在!');
|
||||
}
|
||||
$f = array();
|
||||
$f[] = Form::input('mark', '备注', $UserExtract['mark'])->type('textarea');
|
||||
return create_form('编辑', $f, Url::buildUrl('/finance/extract/remark/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新提现记录
|
||||
* @param int $id 提现记录ID
|
||||
* @param array $data 更新数据
|
||||
* @return bool
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function update(int $id, array $data)
|
||||
{
|
||||
if (!$this->dao->update($id, $data))
|
||||
throw new AdminException('修改失败');
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function refuse(int $id, string $message)
|
||||
{
|
||||
$extract = $this->getExtract($id);
|
||||
if (!$extract) {
|
||||
throw new AdminException('操作记录不存在!');
|
||||
}
|
||||
if ($extract->status == 1) {
|
||||
throw new AdminException('已经提现,错误操作');
|
||||
}
|
||||
if ($extract->status == -1) {
|
||||
throw new AdminException('您的提现申请已被拒绝,请勿重复操作!');
|
||||
}
|
||||
$res = $this->changeFail($id, $extract, $message);
|
||||
if ($res) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('操作失败!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function adopt(int $id)
|
||||
{
|
||||
$extract = $this->getExtract($id);
|
||||
if (!$extract) {
|
||||
throw new AdminException('操作记录不存!');
|
||||
}
|
||||
if ($extract->status == 1) {
|
||||
throw new AdminException('您已提现,请勿重复提现!');
|
||||
}
|
||||
if ($extract->status == -1) {
|
||||
throw new AdminException('您的提现申请已被拒绝!');
|
||||
}
|
||||
if ($this->changeSuccess($id, $extract)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('操作失败!');
|
||||
}
|
||||
}
|
||||
|
||||
/**待提现的数量
|
||||
* @return int
|
||||
*/
|
||||
public function userExtractCount()
|
||||
{
|
||||
return $this->dao->count(['status' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 银行卡提现
|
||||
* @param int $uid
|
||||
* @return mixed
|
||||
*/
|
||||
public function bank(int $uid)
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$user = $userService->getUserInfo($uid, 'brokerage_price');
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$data['broken_commission'] = $userBrokerageServices->getUserFrozenPrice($uid);
|
||||
if ($data['broken_commission'] < 0)
|
||||
$data['broken_commission'] = '0';
|
||||
$data['brokerage_price'] = $user['brokerage_price'];
|
||||
//可提现佣金
|
||||
$data['commissionCount'] = bcsub((string)$data['brokerage_price'], (string)$data['broken_commission'], 2);
|
||||
$extractBank = sys_config('user_extract_bank') ?? []; //提现银行
|
||||
$extractBank = str_replace("\r\n", "\n", $extractBank);//防止不兼容
|
||||
$data['extractBank'] = explode("\n", is_array($extractBank) ? (isset($extractBank[0]) ? $extractBank[0] : $extractBank) : $extractBank);
|
||||
$data['minPrice'] = sys_config('user_extract_min_price');//提现最低金额
|
||||
$data['maxPrice'] = sys_config('user_extract_max_price');//提现最高金额
|
||||
$data['withdraw_fee'] = sys_config('withdraw_fee');//提现手续费
|
||||
$data['extract_wechat_type'] = sys_config('brokerage_type');//微信提现到账方式
|
||||
$data['user_extract_balance_status'] = sys_config('user_extract_balance_status', 1);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现申请
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
*/
|
||||
public function cash(int $uid, array $data)
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$user = $userService->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$data['broken_commission'] = $userBrokerageServices->getUserFrozenPrice($uid);
|
||||
if ($data['broken_commission'] < 0)
|
||||
$data['broken_commission'] = 0;
|
||||
$data['brokerage_price'] = $user['brokerage_price'];
|
||||
//可提现佣金
|
||||
$commissionCount = (float)bcsub((string)$data['brokerage_price'], (string)$data['broken_commission'], 2);
|
||||
if ($data['money'] > $commissionCount) {
|
||||
throw new ValidateException('可提现佣金不足');
|
||||
}
|
||||
|
||||
$extractPrice = $user['brokerage_price'];
|
||||
$userExtractMinPrice = sys_config('user_extract_min_price');
|
||||
if ($data['money'] < $userExtractMinPrice) {
|
||||
throw new ValidateException('提现金额不能小于' . $userExtractMinPrice . '元');
|
||||
}
|
||||
$userExtractMaxPrice = sys_config('user_extract_max_price');
|
||||
if ($data['money'] > $userExtractMaxPrice) {
|
||||
throw new ValidateException('提现金额不能大于' . $userExtractMaxPrice . '元');
|
||||
}
|
||||
if ($extractPrice < 0) {
|
||||
throw new ValidateException('提现佣金不足' . $data['money']);
|
||||
}
|
||||
if ($data['money'] > $extractPrice) {
|
||||
throw new ValidateException('提现佣金不足' . $data['money']);
|
||||
}
|
||||
if ($data['money'] <= 0) {
|
||||
throw new ValidateException('提现佣金大于0');
|
||||
}
|
||||
$extract_fee = bcmul((string)$data['money'], bcdiv(sys_config('withdraw_fee'), '100', 4), 2);
|
||||
if ($data['extract_type'] == 'balance') {//提现至余额不要手续费
|
||||
$extract_fee = 0;
|
||||
}
|
||||
$insertData = [
|
||||
'uid' => $user['uid'],
|
||||
'order_id' => app()->make(StoreOrderCreateServices::class)->getNewOrderId('tx'),
|
||||
'extract_type' => $data['extract_type'],
|
||||
'extract_price' => bcsub((string)$data['money'], (string)$extract_fee, 2),
|
||||
'extract_fee' => $extract_fee,
|
||||
'add_time' => time(),
|
||||
'balance' => $user['brokerage_price'],
|
||||
'status' => 0,
|
||||
'channel_type' => $data['channel_type']
|
||||
];
|
||||
if (isset($data['name']) && strlen(trim($data['name']))) $insertData['real_name'] = $data['name'];
|
||||
else $insertData['real_name'] = $user['nickname'];
|
||||
if (isset($data['cardnum'])) $insertData['bank_code'] = $data['cardnum'];
|
||||
else $insertData['bank_code'] = '';
|
||||
if (isset($data['bankname'])) $insertData['bank_address'] = $data['bankname'];
|
||||
else $insertData['bank_address'] = '';
|
||||
if (isset($data['weixin'])) $insertData['wechat'] = $data['weixin'];
|
||||
else $insertData['wechat'] = $user['nickname'];
|
||||
if ($data['extract_type'] == 'alipay') {
|
||||
$insertData['alipay_code'] = $data['alipay_code'];
|
||||
$insertData['qrcode_url'] = $data['qrcode_url'];
|
||||
$mark = '使用支付宝';
|
||||
} else if ($data['extract_type'] == 'bank') {
|
||||
$mark = '使用银联卡' . $insertData['bank_code'];
|
||||
} else if ($data['extract_type'] == 'weixin') {
|
||||
$insertData['qrcode_url'] = $data['qrcode_url'];
|
||||
$mark = '使用微信提现';
|
||||
/** @var WechatUserServices $wechatServices */
|
||||
$wechatServices = app()->make(WechatUserServices::class);
|
||||
$openid = $wechatServices->getWechatOpenid($uid, 'wechat');
|
||||
if (sys_config('brokerage_type', 0) && $openid) {
|
||||
if ($insertData['extract_price'] < 0.01) {
|
||||
throw new ValidateException('扣除手续费后,提现金额不足1元;而企业微信付款到零钱最低金额为0.01元');
|
||||
}
|
||||
}
|
||||
} elseif ($data['extract_type'] == 'balance') {
|
||||
$mark = '提现至余额账号';
|
||||
}
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$res1 = $this->transaction(function () use ($insertData, $data, $uid, $userService, $user, $userBrokerageServices, $mark) {
|
||||
if (!$res1 = $this->dao->save($insertData)) {
|
||||
throw new ValidateException('提现失败');
|
||||
}
|
||||
//修改用户佣金
|
||||
$balance = bcsub((string)$user['brokerage_price'], (string)$data['money'], 2) ?? 0;
|
||||
if (!$userService->update($uid, ['brokerage_price' => $balance], 'uid')) {
|
||||
throw new ValidateException('修改用户信息失败');
|
||||
}
|
||||
//保存佣金记录
|
||||
$userBrokerageServices->income('extract', $uid, ['mark' => $mark, 'number' => $data['money']], $balance, $res1['id']);
|
||||
|
||||
//提现值余额 不用审核,直接通过
|
||||
if ($data['extract_type'] == 'balance') {
|
||||
$this->adopt((int)$res1['id']);
|
||||
}
|
||||
return $res1;
|
||||
});
|
||||
//用户申请体现事件
|
||||
event('user.extract', [$user, $data, $res1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $where
|
||||
* @param string $SumField
|
||||
* @param string $selectType
|
||||
* @param string $group
|
||||
* @return float|mixed
|
||||
*/
|
||||
public function getOutMoneyByWhere(array $where, string $SumField, string $selectType, string $group = "")
|
||||
{
|
||||
switch ($selectType) {
|
||||
case "sum" :
|
||||
return $this->dao->getWhereSumField($where, $SumField);
|
||||
case "group" :
|
||||
return $this->dao->getGroupField($where, $SumField, $group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户取消提现申请
|
||||
* @param int $id 提现记录ID
|
||||
* @param int $uid 用户ID
|
||||
* @return bool
|
||||
* @throws ValidateException
|
||||
*/
|
||||
public function cancel($id, $uid)
|
||||
{
|
||||
$extract = $this->getExtract($id);
|
||||
if (!$extract) {
|
||||
throw new ValidateException('提现记录不存在');
|
||||
}
|
||||
if ($extract['status'] != 0) {
|
||||
throw new ValidateException('提现状态不是待审核,不能取消');
|
||||
}
|
||||
if ($extract['uid'] != $uid) {
|
||||
throw new ValidateException('提现不属于当前用户');
|
||||
}
|
||||
$res = $this->changeFail($id, $extract, '用户取消提现申请');
|
||||
if ($res) {
|
||||
return true;
|
||||
} else {
|
||||
throw new ValidateException('操作失败!');
|
||||
}
|
||||
}
|
||||
}
|
||||
108
app/services/user/UserFriendsServices.php
Normal file
108
app/services/user/UserFriendsServices.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
|
||||
use app\dao\user\UserFriendsDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\user\level\SystemUserLevelServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 获取好友列表
|
||||
* Class UserFriendsServices
|
||||
* @package app\services\user
|
||||
* @mixin UserFriendsDao
|
||||
*/
|
||||
class UserFriendsServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserFriendsDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserFriendsDao $dao;
|
||||
|
||||
/**
|
||||
* 保存好友关系
|
||||
* @param int $uid
|
||||
* @param int $friends_uid
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function saveFriend(int $uid, int $friends_uid)
|
||||
{
|
||||
$data = [
|
||||
'uid' => $uid,
|
||||
'friends_uid' => $friends_uid
|
||||
];
|
||||
$userFriend = $this->dao->get($data);
|
||||
$res1 = true;
|
||||
if (!$userFriend) {
|
||||
$data['add_time'] = time();
|
||||
$res1 = $this->dao->save($data);
|
||||
}
|
||||
return $res1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友uids 我推广的 推广我的
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function getFriendUids(int $uid)
|
||||
{
|
||||
$result = [];
|
||||
if ($uid) {
|
||||
$spread = $this->dao->getColumn(['uid' => $uid], 'friends_uid');
|
||||
$sup_spread = $this->dao->getColumn(['friends_uid' => $uid], 'uid');
|
||||
$result = array_unique(array_merge($spread, $sup_spread));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友
|
||||
* @param int $id
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getFriendList(int $uid, string $field = 'uid,nickname,level,add_time')
|
||||
{
|
||||
$uids = $this->getFriendUids($uid);
|
||||
$list = [];
|
||||
$count = 0;
|
||||
if ($uids) {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$list = $userServices->getList(['uid' => $uids], $field, $page, $limit);
|
||||
/** @var SystemUserLevelServices $systemLevelServices */
|
||||
$systemLevelServices = app()->make(SystemUserLevelServices::class);
|
||||
$systemLevelList = $systemLevelServices->getWhereLevelList([], 'id,name');
|
||||
if ($systemLevelList) $systemLevelList = array_combine(array_column($systemLevelList, 'id'), $systemLevelList);
|
||||
foreach ($list as &$item) {
|
||||
$item['type'] = $systemLevelList[$item['level']]['name'] ?? '暂无';
|
||||
$item['add_time'] = $item['add_time'] && is_numeric($item['add_time']) ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
$count = $userServices->count(['uid' => $uids]);
|
||||
}
|
||||
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
}
|
||||
242
app/services/user/UserIntegralServices.php
Normal file
242
app/services/user/UserIntegralServices.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\dao\user\UserBillDao;
|
||||
use app\jobs\user\UserIntegralJob;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 用户积分
|
||||
* Class UserIntegralServices
|
||||
* @package app\services\user
|
||||
* @mixin UserBillDao
|
||||
*/
|
||||
class UserIntegralServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserBillDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserBillDao $dao;
|
||||
|
||||
/**
|
||||
* 清空到期积分(分批加入队列)
|
||||
* @return bool
|
||||
*/
|
||||
public function clearExpireIntegral()
|
||||
{
|
||||
//是否开启积分有效期
|
||||
if (!sys_config('integral_effective_status', 0)) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$users = $userServices->getColumn([['integral', '>', 0]], 'uid');
|
||||
if ($users) {
|
||||
//拆分大数组
|
||||
$uidsArr = array_chunk($users, 100);
|
||||
foreach ($uidsArr as $uids) {
|
||||
//加入同步|更新用户队列
|
||||
UserIntegralJob::dispatch([$uids]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行清空到期积分
|
||||
* @param array $uids
|
||||
* @return bool
|
||||
*/
|
||||
public function doClearExpireIntegral(array $uids)
|
||||
{
|
||||
if (!$uids) return true;
|
||||
//是否开启积分有效期
|
||||
if (!sys_config('integral_effective_status', 0)) {
|
||||
return true;
|
||||
}
|
||||
[$clear_time, $start_time, $end_time] = $this->getTime();
|
||||
$start = date('Y年m月d日', $start_time);
|
||||
$end = date('Y年m月d日', $end_time);
|
||||
$where = ['category' => 'integral', 'pm' => 1, 'status' => 1];
|
||||
$where['add_time'] = [$start_time, $end_time];
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$users = $userServices->getColumn([['uid', 'in', $uids]], 'uid,integral', 'uid');
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
//查询是否清除过
|
||||
$clear_uids = $userBillServices->getColumn([['category', '=', 'integral'], ['type', '=', 'system_clear'], ['add_time', '>=', $clear_time], ['add_time', '<=', $clear_time + 86400]], 'uid');
|
||||
foreach ($uids as $uid) {
|
||||
$number = 0;
|
||||
if (!isset($users[$uid]) || in_array($uid, $clear_uids)) continue;
|
||||
$user = $users[$uid];
|
||||
$where['uid'] = $uid;
|
||||
$where['pm'] = 1;
|
||||
$userSumIntegralInc = $userBillServices->getBillSum($where);
|
||||
$where['pm'] = 0;
|
||||
$userSumIntegralDec = $userBillServices->getBillSum($where);
|
||||
$userSumIntegral = $userSumIntegralInc > $userSumIntegralDec ? (int)bcsub((string)$userSumIntegralInc, (string)$userSumIntegralDec, 0) : 0;
|
||||
if ($userSumIntegral) {
|
||||
$user_data = [];
|
||||
$number = $userSumIntegral;
|
||||
if ($userSumIntegral >= $user['integral']) {
|
||||
$number = $user['integral'];
|
||||
$user_data['integral'] = 0;
|
||||
} else {
|
||||
$user_data['integral'] = (int)bcsub((string)$user['integral'], (string)$userSumIntegral, 0);
|
||||
}
|
||||
//记录清除积分
|
||||
$userBillServices->income('system_clear_integral', $uid, (int)$number, (int)$user_data['integral'], $uid);
|
||||
$userServices->update($uid, $user_data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户清空到期积分
|
||||
* @param int $uid
|
||||
* @param array $user
|
||||
* @return array|int[]
|
||||
*/
|
||||
public function getUserClearIntegral(int $uid, $user = [])
|
||||
{
|
||||
if (!$uid) return [0, 0];
|
||||
//是否开启积分有效期
|
||||
if (!sys_config('integral_effective_status', 0)) {
|
||||
return [0, 0];
|
||||
}
|
||||
[$clear_time, $start_time, $end_time] = $this->getTime();
|
||||
|
||||
$where = ['category' => 'integral', 'pm' => 1, 'status' => 1];
|
||||
$where['add_time'] = [$start_time, $end_time];
|
||||
if (!$user) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->get($uid, 'uid,integral');
|
||||
}
|
||||
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
$where['uid'] = $uid;
|
||||
$userSumIntegralInc = $userBillServices->getBillSum($where);
|
||||
$where['pm'] = 0;
|
||||
$userSumIntegralDec = $userBillServices->getBillSum($where);
|
||||
$userSumIntegral = $userSumIntegralInc > $userSumIntegralDec ? (int)bcsub((string)$userSumIntegralInc, (string)$userSumIntegralDec, 0) : 0;
|
||||
if ($userSumIntegral) {
|
||||
if ($userSumIntegral >= $user['integral']) {
|
||||
$userSumIntegral = $user['integral'];
|
||||
}
|
||||
}
|
||||
return [$userSumIntegral, $clear_time];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取清空积分时间段
|
||||
* @param int $type
|
||||
* @return int[]
|
||||
*/
|
||||
public function getTime(int $type = 0)
|
||||
{
|
||||
if (!$type) $type = (int)sys_config('integral_effective_time', 3);
|
||||
switch ($type) {
|
||||
case 1://月
|
||||
$start = date('Y-m-01 00:00:00', strtotime('-1 month'));
|
||||
$end = date("Y-m-d 23:59:59", strtotime(-date('d') . 'day'));
|
||||
$clear_end = date('Y-m-t', strtotime(date('Y-m-d')));
|
||||
break;
|
||||
case 2://季度
|
||||
$season = ceil((date('n')) / 3) - 1;//上季度是第几季度
|
||||
$start = date('Y-m-d 00:00:00', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));
|
||||
$end = date('Y-m-d 23:59:59', mktime(23, 59, 59, $season * 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));
|
||||
$clear_end = date('Y-m-t', mktime(0, 0, 0, ($season + 1) * 3, 1, date('Y')));
|
||||
break;
|
||||
case 3://年
|
||||
default://默认年
|
||||
$start = date('Y-01-01 00:00:00', strtotime('-1 year'));
|
||||
$end = date('Y-m-d 23:59:59', strtotime($start . "+12 month -1 day"));
|
||||
$clear_end = date('Y-12-31');
|
||||
break;
|
||||
}
|
||||
return [strtotime($clear_end), strtotime($start), strtotime($end)];
|
||||
}
|
||||
|
||||
/**
|
||||
* 新人礼赠送积分
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function newcomerGiveIntegral(int $uid)
|
||||
{
|
||||
if (!sys_config('newcomer_status')) {
|
||||
return false;
|
||||
}
|
||||
$status = sys_config('register_integral_status');
|
||||
if (!$status) {//未开启
|
||||
return true;
|
||||
}
|
||||
$integral = (int)sys_config('register_give_integral', []);
|
||||
if (!$integral) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo($uid);
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
$balance = bcadd((string)$userInfo['integral'], (string)$integral, 2);
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
$userBillServices->income('newcomer_give_integral', $uid, (int)$integral, (int)$balance);
|
||||
$userServices->update($uid, ['integral' => $balance]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员卡激活赠送积分
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function levelGiveIntegral(int $uid)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo($uid);
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
$status = sys_config('level_activate_status');
|
||||
if (!$status) {//是否需要激活
|
||||
return true;
|
||||
}
|
||||
$status = sys_config('level_integral_status');
|
||||
if (!$status) {//未开启
|
||||
return true;
|
||||
}
|
||||
$integral = (int)sys_config('level_give_integral', []);
|
||||
if (!$integral) {
|
||||
return true;
|
||||
}
|
||||
$balance = bcadd((string)$userInfo['integral'], (string)$integral, 2);
|
||||
/** @var UserBillServices $userBillServices */
|
||||
$userBillServices = app()->make(UserBillServices::class);
|
||||
$userBillServices->income('level_give_integral', $uid, (int)$integral, (int)$balance);
|
||||
$userServices->update($uid, ['integral' => $balance]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
211
app/services/user/UserInvoiceServices.php
Normal file
211
app/services/user/UserInvoiceServices.php
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
|
||||
use app\dao\user\UserInvoiceDao;
|
||||
use app\services\BaseServices;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserInvoiceServices
|
||||
* @package app\services\user
|
||||
* @mixin UserInvoiceDao
|
||||
*/
|
||||
class UserInvoiceServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserInvoiceDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserInvoiceDao $dao;
|
||||
|
||||
/**
|
||||
* 检测系统设置发票功能
|
||||
* @param bool $is_speclial
|
||||
* @return bool|array
|
||||
*/
|
||||
public function invoiceFuncStatus(bool $is_speclial = true)
|
||||
{
|
||||
$invoice = (bool)sys_config('invoice_func_status', 0);
|
||||
if ($is_speclial) {
|
||||
$specialInvoice = sys_config('special_invoice_status', 0);
|
||||
return ['invoice_func' => $invoice, 'special_invoice' => $invoice && $specialInvoice];
|
||||
}
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个发票信息
|
||||
* @param int $id
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getInvoice(int $id, int $uid = 0)
|
||||
{
|
||||
$invoice = $this->dao->getOne(['id' => $id, 'is_del' => 0]);
|
||||
if (!$invoice || ($uid && $invoice['uid'] != $uid)) {
|
||||
return [];
|
||||
}
|
||||
return $invoice->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测该发票是否可用
|
||||
* @param int $id
|
||||
* @param int $uid
|
||||
* @return bool|array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function checkInvoice(int $id, int $uid)
|
||||
{
|
||||
$invoice = $this->getInvoice($id, $uid);
|
||||
if (!$invoice) {
|
||||
throw new ValidateException('发票不存在或删除');
|
||||
}
|
||||
$invoice_func = $this->invoiceFuncStatus();
|
||||
if (!$invoice_func['invoice_func']) {
|
||||
throw new ValidateException('暂未开启开票,请联系管理员');
|
||||
}
|
||||
//专用发票
|
||||
if ($invoice['type'] == 2) {
|
||||
if (!$invoice_func['special_invoice']) {
|
||||
throw new ValidateException('暂未开启专用发票,请联系管理员');
|
||||
}
|
||||
}
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取某个用户发票列表
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserList(int $uid, $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where['is_del'] = 0;
|
||||
$where['uid'] = $uid;
|
||||
return $this->dao->getList($where, '*', $page, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个用户默认发票
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserDefaultInvoice(int $uid, int $type, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne(['uid' => $uid, 'is_default' => 1, 'is_del' => 0, 'type' => $type], $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加|修改
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function saveInvoice(int $uid, array $data)
|
||||
{
|
||||
$id = (int)$data['id'];
|
||||
$data['uid'] = $uid;
|
||||
unset($data['id']);
|
||||
$invoice = $this->dao->get(['uid' => $uid, 'name' => $data['name'], 'drawer_phone' => $data['drawer_phone'], 'is_del' => 0]);
|
||||
if ($id) {
|
||||
if ($invoice && $id != $invoice['id']) {
|
||||
throw new ValidateException('该发票已经存在');
|
||||
}
|
||||
if ($this->dao->update($id, $data, 'id')) {
|
||||
if ($data['is_default']) {
|
||||
$this->setDefaultInvoice($uid, $id);
|
||||
}
|
||||
return ['type' => 'edit', 'msg' => '修改发票成功', 'data' => []];
|
||||
} else {
|
||||
throw new ValidateException('修改失败或者您没有修改什么');
|
||||
}
|
||||
} else {
|
||||
if ($invoice) {
|
||||
throw new ValidateException('该发票已经存在');
|
||||
}
|
||||
if ($add_invoice = $this->dao->save($data)) {
|
||||
$id = (int)$add_invoice['id'];
|
||||
if ($data['is_default']) {
|
||||
$this->setDefaultInvoice($uid, $id);
|
||||
}
|
||||
return ['type' => 'add', 'msg' => '添加发票成功', 'data' => ['id' => $id]];
|
||||
} else {
|
||||
throw new ValidateException('添加失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认发票
|
||||
* @param int $id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function setDefaultInvoice(int $uid, int $id)
|
||||
{
|
||||
if (!$invoice = $this->getInvoice($id)) {
|
||||
throw new ValidateException('发票不存在');
|
||||
}
|
||||
if ($invoice['uid'] != $uid) {
|
||||
throw new ValidateException('数据错误');
|
||||
}
|
||||
if (!$this->dao->setDefault($uid, $id, $invoice['header_type'], $invoice['type'])) {
|
||||
throw new ValidateException('设置默认发票失败');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param $id
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delInvoice(int $uid, int $id)
|
||||
{
|
||||
if ($invoice = $this->getInvoice($id)) {
|
||||
if ($invoice['uid'] != $uid) {
|
||||
throw new ValidateException('数据错误');
|
||||
}
|
||||
if (!$this->dao->update($id, ['is_del' => 1])) {
|
||||
throw new ValidateException('删除失败,请稍候再试!');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
645
app/services/user/UserMoneyServices.php
Normal file
645
app/services/user/UserMoneyServices.php
Normal file
@@ -0,0 +1,645 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\dao\user\UserMoneyDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\StoreOrderRefundServices;
|
||||
use app\services\system\admin\SystemAdminServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
use crmeb\services\CacheService;
|
||||
|
||||
|
||||
/**
|
||||
* 用户余额
|
||||
* Class UserMoneyServices
|
||||
* @package app\services\user
|
||||
* @mixin UserMoneyDao
|
||||
*/
|
||||
class UserMoneyServices extends BaseServices
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 用户记录模板
|
||||
* @var array[]
|
||||
*/
|
||||
protected array $incomeData = [
|
||||
'pay_product' => [
|
||||
'title' => '余额支付购买商品',
|
||||
'type' => 'pay_product',
|
||||
'mark' => '余额支付{%num%}元购买商品',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'pay_product_refund' => [
|
||||
'title' => '商品退款',
|
||||
'type' => 'pay_product_refund',
|
||||
'mark' => '订单余额退款{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'system_add' => [
|
||||
'title' => '系统增加余额',
|
||||
'type' => 'system_add',
|
||||
'mark' => '系统增加{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'system_sub' => [
|
||||
'title' => '系统减少余额',
|
||||
'type' => 'system_sub',
|
||||
'mark' => '系统扣除了{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'user_recharge' => [
|
||||
'title' => '用户充值余额',
|
||||
'type' => 'recharge',
|
||||
'mark' => '成功充值余额{%price%}元,赠送{%give_price%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'user_recharge_refund' => [
|
||||
'title' => '用户充值退款',
|
||||
'type' => 'recharge_refund',
|
||||
'mark' => '退款扣除用户余额{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'brokerage_to_nowMoney' => [
|
||||
'title' => '佣金提现到余额',
|
||||
'type' => 'extract',
|
||||
'mark' => '佣金提现到余额{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'lottery_use_money' => [
|
||||
'title' => '参与抽奖使用余额',
|
||||
'type' => 'lottery_use',
|
||||
'mark' => '参与抽奖使用{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'lottery_give_money' => [
|
||||
'title' => '抽奖中奖赠送余额',
|
||||
'type' => 'lottery_add',
|
||||
'mark' => '抽奖中奖赠送{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'newcomer_give_money' => [
|
||||
'title' => '新人礼赠送余额',
|
||||
'type' => 'newcomer_add',
|
||||
'mark' => '新人礼赠送{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'level_give_money' => [
|
||||
'title' => '会员卡激活赠送余额',
|
||||
'type' => 'level_add',
|
||||
'mark' => '会员卡激活赠送{%num%}余额',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'pay_integral_product' => [
|
||||
'title' => '余额支付购买积分商品',
|
||||
'type' => 'pay_integral_product',
|
||||
'mark' => '余额支付{%num%}元购买积分商品',
|
||||
'status' => 1,
|
||||
'pm' => 0
|
||||
],
|
||||
'card_add_money' => [
|
||||
'title' => '礼品卡充值余额',
|
||||
'type' => 'card_add_money',
|
||||
'mark' => '礼品卡充值余额{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
'holiday_gift_money' => [
|
||||
'title' => '节日有礼赠送余额',
|
||||
'type' => 'holiday_gift_money',
|
||||
'mark' => '节日有礼赠送{%num%}元',
|
||||
'status' => 1,
|
||||
'pm' => 1
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* 类型名称
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $typeName = [
|
||||
'pay_product' => '商城购物',
|
||||
'pay_product_refund' => '商城购物退款',
|
||||
'system_add' => '系统充值',
|
||||
'system_sub' => '系统扣除',
|
||||
'recharge' => '用户充值',
|
||||
'recharge_refund' => '用户充值退款',
|
||||
'extract' => '佣金提现充值',
|
||||
'lottery_use' => '抽奖使用',
|
||||
'lottery_add' => '抽奖中奖充值',
|
||||
'newcomer_add' => '新人礼赠送充值',
|
||||
'level_add' => '会员卡激活赠送充值',
|
||||
'card_add_money' => '礼品卡充值余额',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserMoneyDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserMoneyDao $dao;
|
||||
|
||||
/**
|
||||
* 获取用户记录总和
|
||||
* @param $uid
|
||||
* @param string $category
|
||||
* @param array $type
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRecordCount(int $uid, $category = 'now_money', $type = [], $time = '', $pm = false)
|
||||
{
|
||||
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
$where['category'] = $category;
|
||||
$where['status'] = 1;
|
||||
|
||||
if (is_string($type) && strlen(trim($type))) {
|
||||
$where['type'] = explode(',', $type);
|
||||
}
|
||||
if ($time) {
|
||||
$where['time'] = $time;
|
||||
}
|
||||
if ($pm) {
|
||||
$where['pm'] = 0;
|
||||
}
|
||||
return $this->dao->getBillSumColumn($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资金列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getMoneyList(array $where, string $field = '*', int $limit = 0)
|
||||
{
|
||||
$where_data = [];
|
||||
if (isset($where['uid']) && $where['uid'] != '') {
|
||||
$where_data['uid'] = $where['uid'];
|
||||
}
|
||||
if ($where['start_time'] != '' && $where['end_time'] != '') {
|
||||
$where_data['time'] = str_replace('-', '/', $where['start_time']) . ' - ' . str_replace('-', '/', $where['end_time']);
|
||||
}
|
||||
if (isset($where['category']) && $where['category'] != '') {
|
||||
$where_data['category'] = $where['category'];
|
||||
}
|
||||
if (isset($where['type']) && $where['type'] != '') {
|
||||
$where_data['type'] = $where['type'];
|
||||
}
|
||||
$where_data['not_category'] = ['integral', 'exp', 'share'];
|
||||
$where_data['not_type'] = ['gain', 'system_sub', 'deduction', 'sign'];
|
||||
if (isset($where['nickname']) && $where['nickname'] != '') {
|
||||
$where_data['like'] = $where['nickname'];
|
||||
}
|
||||
if (isset($where['excel']) && $where['excel'] != '') {
|
||||
$where_data['excel'] = $where['excel'];
|
||||
} else {
|
||||
$where_data['excel'] = 0;
|
||||
}
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$data = $this->dao->getList($where_data, $field, $page, $limit, [
|
||||
'user' => function ($query) {
|
||||
$query->field('uid,nickname');
|
||||
}]);
|
||||
foreach ($data as &$item) {
|
||||
$item['nickname'] = $item['user']['nickname'] ?? '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
unset($item['user']);
|
||||
}
|
||||
$count = $this->dao->count($where_data);
|
||||
return compact('data', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户|所有资金变动列表
|
||||
* @param int $uid
|
||||
* @param array $where_time
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getUserMoneyList(int $uid = 0, $where_time = [], string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = [];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['add_time'] = $where_time;
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
foreach ($list as &$item) {
|
||||
$value = array_filter($this->incomeData, function ($value) use ($item) {
|
||||
if ($item['type'] == $value['type']) {
|
||||
return $item['title'];
|
||||
}
|
||||
});
|
||||
$item['type_title'] = $value[$item['type']]['title'] ?? '未知类型';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
if (in_array($item['type'], ['system_add', 'system_sub'])) {
|
||||
$item['admin_name'] = app()->make(SystemAdminServices::class)->value(['id' => $item['link_id']], 'real_name');
|
||||
} else {
|
||||
$item['admin_name'] = '';
|
||||
}
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的充值总数
|
||||
* @param int $uid
|
||||
* @return float
|
||||
*/
|
||||
public function getRechargeSum(int $uid = 0, $time = [])
|
||||
{
|
||||
$where = ['uid' => $uid, 'pm' => 1, 'status' => 1, 'type' => ['system_add', 'recharge', 'extract', 'lottery_add', 'newcomer_add', 'level_add']];
|
||||
if ($time) $where['add_time'] = $time;
|
||||
return $this->dao->sum($where, 'number', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户|所有充值列表
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getRechargeList(int $uid = 0, $where_time = [], string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['category' => 'now_money', 'type' => 'recharge'];
|
||||
if ($uid) $where['uid'] = $uid;
|
||||
if ($where_time) $where['add_time'] = $where_time;
|
||||
$list = $this->dao->getList($where, $field, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入用户记录
|
||||
* @param string $type 写入类型
|
||||
* @param int $uid
|
||||
* @param int|string|array $number
|
||||
* @param int|string $balance
|
||||
* @param int $link_id
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function income(string $type, int $uid, $number, $balance, $link_id = 0, string $title = '', $mark = '')
|
||||
{
|
||||
$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(['{%num%}'], (string)$number, $data['mark']);
|
||||
}
|
||||
if ($title) $data['title'] = $title;
|
||||
if ($mark) $data['mark'] = $mark;
|
||||
$data['add_time'] = time();
|
||||
if ((float)$data['number']) {
|
||||
return $this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资金类型
|
||||
* @return bool|mixed|null
|
||||
*/
|
||||
public function bill_type()
|
||||
{
|
||||
return CacheService::get('user_money_type_list', function () {
|
||||
return ['list' => $this->dao->getMoneyType([])];
|
||||
}, 600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户余额记录列表
|
||||
* @param int $uid
|
||||
* @param int $type
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function userMoneyList(int $uid, int $type, array $data = [])
|
||||
{
|
||||
$where = [];
|
||||
$where['uid'] = $uid;
|
||||
switch ($type) {
|
||||
case 1:
|
||||
$where['pm'] = 0;
|
||||
break;
|
||||
case 2:
|
||||
$where['pm'] = 1;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
if ((isset($data['start']) && $data['start']) || (isset($data['stop']) && $data['stop'])) {
|
||||
$where['time'] = [$data['start'], $data['stop']];
|
||||
}
|
||||
$list = $this->dao->getList($where, '*', $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
$times = [];
|
||||
if ($list) {
|
||||
$typeName = $this->typeName;
|
||||
foreach ($list as &$item) {
|
||||
$item['time_key'] = $item['time'] = $item['add_time'] ? date('Y-m', (int)$item['add_time']) : '';
|
||||
$item['day'] = $item['add_time'] ? date('Y-m-d', (int)$item['add_time']) : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y/m/d H:i', (int)$item['add_time']) : '';
|
||||
$item['type_name'] = $typeName[$item['type'] ?? ''] ?? '未知类型';
|
||||
if ($item['type'] == 'pay_product') {
|
||||
/** @var StoreOrderRefundServices $refundSerives */
|
||||
$refundSerives = app()->make(StoreOrderRefundServices::class);
|
||||
$refund = $refundSerives->getOne(['store_order_id' => $item['link_id']]);
|
||||
$item['refund_status'] = '';
|
||||
if ($refund) {
|
||||
if ($refund['refund_type'] == 6) {
|
||||
$item['refund_status'] = '已退款';
|
||||
} else {
|
||||
$item['refund_status'] = '退款中';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ($item['type'] == 'recharge') {
|
||||
/** @var UserRechargeServices $rechargeSerives */
|
||||
$orderSerives = app()->make(UserRechargeServices::class);
|
||||
$refund_price = $orderSerives->value(['id' => $item['link_id']], 'refund_price');
|
||||
if ($refund_price) {
|
||||
$item['refund_status'] = '已退款';
|
||||
} else {
|
||||
$item['refund_status'] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
|
||||
return ['count' => $count, 'list' => $list, 'time' => $times];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据查询用户充值金额
|
||||
* @param array $where
|
||||
* @param string $rechargeSumField
|
||||
* @param string $selectType
|
||||
* @param string $group
|
||||
* @return float|mixed
|
||||
*/
|
||||
public function getRechargeMoneyByWhere(array $where, string $rechargeSumField, string $selectType, string $group = "")
|
||||
{
|
||||
switch ($selectType) {
|
||||
case "sum" :
|
||||
return $this->dao->getWhereSumField($where, $rechargeSumField);
|
||||
case "group" :
|
||||
return $this->dao->getGroupField($where, $rechargeSumField, $group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新人礼赠送余额
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function newcomerGiveMoney(int $uid)
|
||||
{
|
||||
if (!sys_config('newcomer_status')) {
|
||||
return false;
|
||||
}
|
||||
$status = sys_config('register_money_status');
|
||||
if (!$status) {//未开启
|
||||
return true;
|
||||
}
|
||||
$money = (int)sys_config('register_give_money', []);
|
||||
if (!$money) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo($uid);
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
$balance = bcadd((string)$userInfo['now_money'], (string)$money);
|
||||
$this->income('newcomer_give_money', $uid, $money, $balance);
|
||||
$userServices->update($uid, ['now_money' => $balance]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员卡激活赠送余额
|
||||
* @param int $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function levelGiveMoney(int $uid)
|
||||
{
|
||||
$status = sys_config('level_activate_status');
|
||||
if (!$status) {//是否需要激活
|
||||
return true;
|
||||
}
|
||||
$status = sys_config('level_money_status');
|
||||
if (!$status) {//未开启
|
||||
return true;
|
||||
}
|
||||
$money = (int)sys_config('level_give_money', []);
|
||||
if (!$money) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo($uid);
|
||||
if (!$userInfo) {
|
||||
return true;
|
||||
}
|
||||
$balance = bcadd((string)$userInfo['now_money'], (string)$money);
|
||||
$this->income('level_give_money', $uid, $money, $balance);
|
||||
$userServices->update($uid, ['now_money' => $balance]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额统计基础
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getBasic($where)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$data['now_balance'] = $userServices->sum(['status' => 1], 'now_money', true);
|
||||
$data['add_balance'] = $this->dao->sum(['pm' => 1], 'number', true);
|
||||
$data['sub_balance'] = $this->dao->sum(['pm' => 0], 'number', true);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额趋势
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getTrend($where)
|
||||
{
|
||||
$time = explode('-', $where['time']);
|
||||
if (count($time) != 2) throw new AdminException('参数错误');
|
||||
$dayCount = (strtotime($time[1]) - strtotime($time[0])) / 86400 + 1;
|
||||
$data = [];
|
||||
if ($dayCount == 1) {
|
||||
$data = $this->trend($time, 0);
|
||||
} elseif ($dayCount > 1 && $dayCount <= 31) {
|
||||
$data = $this->trend($time, 1);
|
||||
} elseif ($dayCount > 31 && $dayCount <= 92) {
|
||||
$data = $this->trend($time, 3);
|
||||
} elseif ($dayCount > 92) {
|
||||
$data = $this->trend($time, 30);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额趋势
|
||||
* @param $time
|
||||
* @param $num
|
||||
* @param false $excel
|
||||
* @return array
|
||||
*/
|
||||
public function trend($time, $num, $excel = false)
|
||||
{
|
||||
if ($num == 0) {
|
||||
$xAxis = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
|
||||
$timeType = '%H';
|
||||
} elseif ($num != 0) {
|
||||
$dt_start = strtotime($time[0]);
|
||||
$dt_end = strtotime($time[1]);
|
||||
while ($dt_start <= $dt_end) {
|
||||
if ($num == 30) {
|
||||
$xAxis[] = date('Y-m', $dt_start);
|
||||
$dt_start = strtotime("+1 month", $dt_start);
|
||||
$timeType = '%Y-%m';
|
||||
} else {
|
||||
$xAxis[] = date('m-d', $dt_start);
|
||||
$dt_start = strtotime("+$num day", $dt_start);
|
||||
$timeType = '%m-%d';
|
||||
}
|
||||
}
|
||||
}
|
||||
$time[1] = date("Y-m-d", strtotime("+1 day", strtotime($time[1])));
|
||||
$point_add = array_column($this->dao->getBalanceTrend($time, $timeType, 'add_time', 'sum(number)', 'add'), 'num', 'days');
|
||||
$point_sub = array_column($this->dao->getBalanceTrend($time, $timeType, 'add_time', 'sum(number)', 'sub'), 'num', 'days');
|
||||
$data = $series = [];
|
||||
foreach ($xAxis as $item) {
|
||||
$data['余额积累'][] = isset($point_add[$item]) ? floatval($point_add[$item]) : 0;
|
||||
$data['余额消耗'][] = isset($point_sub[$item]) ? floatval($point_sub[$item]) : 0;
|
||||
}
|
||||
foreach ($data as $key => $item) {
|
||||
$series[] = [
|
||||
'name' => $key,
|
||||
'data' => $item,
|
||||
'type' => 'line',
|
||||
];
|
||||
}
|
||||
return compact('xAxis', 'series');
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额来源
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getChannel($where)
|
||||
{
|
||||
$bing_xdata = ['系统增加', '用户充值', '佣金提现', '抽奖赠送', '商品退款'];
|
||||
$color = ['#64a1f4', '#3edeb5', '#70869f', '#ffc653', '#fc7d6a'];
|
||||
$data = ['system_add', 'recharge', 'extract', 'lottery_add', 'pay_product_refund'];
|
||||
$bing_data = [];
|
||||
foreach ($data as $key => $item) {
|
||||
$bing_data[] = [
|
||||
'name' => $bing_xdata[$key],
|
||||
'value' => $this->dao->sum(['pm' => 1, 'type' => $item, 'time' => $where['time']], 'number', true),
|
||||
'itemStyle' => ['color' => $color[$key]]
|
||||
];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$count = array_sum(array_column($bing_data, 'value'));
|
||||
foreach ($bing_data as $key => $item) {
|
||||
$list[] = [
|
||||
'name' => $item['name'],
|
||||
'value' => $item['value'],
|
||||
'percent' => $count != 0 ? bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2) : 0,
|
||||
];
|
||||
}
|
||||
array_multisort(array_column($list, 'value'), SORT_DESC, $list);
|
||||
return compact('bing_xdata', 'bing_data', 'list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额类型
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function getType($where)
|
||||
{
|
||||
$bing_xdata = ['系统减少', '充值退款', '购买商品'];
|
||||
$color = ['#64a1f4', '#3edeb5', '#70869f'];
|
||||
$data = ['system_sub', 'recharge_refund', 'pay_product'];
|
||||
$bing_data = [];
|
||||
foreach ($data as $key => $item) {
|
||||
$bing_data[] = [
|
||||
'name' => $bing_xdata[$key],
|
||||
'value' => $this->dao->sum(['pm' => 0, 'type' => $item, 'time' => $where['time']], 'number', true),
|
||||
'itemStyle' => ['color' => $color[$key]]
|
||||
];
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$count = array_sum(array_column($bing_data, 'value'));
|
||||
foreach ($bing_data as $key => $item) {
|
||||
$list[] = [
|
||||
'name' => $item['name'],
|
||||
'value' => $item['value'],
|
||||
'percent' => $count != 0 ? bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2) : 0,
|
||||
];
|
||||
}
|
||||
array_multisort(array_column($list, 'value'), SORT_DESC, $list);
|
||||
return compact('bing_xdata', 'bing_data', 'list');
|
||||
}
|
||||
}
|
||||
597
app/services/user/UserRechargeServices.php
Normal file
597
app/services/user/UserRechargeServices.php
Normal file
@@ -0,0 +1,597 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\user\MicroPayOrderJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserRechargeDao;
|
||||
use app\services\pay\PayServices;
|
||||
use app\services\pay\RechargeServices;
|
||||
use app\services\system\config\SystemGroupDataServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\{AliPayService, FormBuilder as Form, wechat\Payment};
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
use app\services\order\StoreOrderCreateServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use app\webscoket\SocketPush;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserRechargeServices
|
||||
* @package app\services\user
|
||||
* @mixin UserRechargeDao
|
||||
*/
|
||||
class UserRechargeServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserRechargeDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserRechargeDao $dao;
|
||||
|
||||
/**
|
||||
* 获取单条数据
|
||||
* @param int $id
|
||||
* @param array $field
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getRecharge(int $id, array $field = [])
|
||||
{
|
||||
return $this->dao->get($id, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $storeId
|
||||
* @return int
|
||||
*/
|
||||
public function getRechargeCount(int $storeId)
|
||||
{
|
||||
return $this->dao->count(['store_id' => $storeId, 'paid' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取统计数据
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return float
|
||||
*/
|
||||
public function getRechargeSum(array $where, string $field = '')
|
||||
{
|
||||
$whereData = [];
|
||||
if (isset($where['data'])) {
|
||||
$whereData['time'] = $where['data'];
|
||||
}
|
||||
if (isset($where['paid']) && $where['paid'] != '') {
|
||||
$whereData['paid'] = $where['paid'];
|
||||
}
|
||||
if (isset($where['nickname']) && $where['nickname']) {
|
||||
$whereData['like'] = $where['nickname'];
|
||||
}
|
||||
if (isset($where['recharge_type']) && $where['recharge_type']) {
|
||||
$whereData['recharge_type'] = $where['recharge_type'];
|
||||
}
|
||||
if (isset($where['store_id'])) {
|
||||
$whereData['store_id'] = $where['store_id'];
|
||||
}
|
||||
return $this->dao->getWhereSumField($whereData, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取充值列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getRechargeList(array $where, string $field = '*', int $limit = 0, array $with = [])
|
||||
{
|
||||
$whereData = $where;
|
||||
if (isset($where['data'])) {
|
||||
$whereData['time'] = $where['data'];
|
||||
unset($whereData['data']);
|
||||
}
|
||||
if (isset($where['nickname']) && $where['nickname']) {
|
||||
$whereData['like'] = $where['nickname'];
|
||||
unset($whereData['nickname']);
|
||||
}
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$list = $this->dao->getList($whereData, $field, $page, $limit, $with);
|
||||
$count = $this->dao->count($whereData);
|
||||
|
||||
foreach ($list as &$item) {
|
||||
switch ($item['recharge_type']) {
|
||||
case 'routine':
|
||||
$item['_recharge_type'] = '小程序充值';
|
||||
break;
|
||||
case 'weixin':
|
||||
$item['_recharge_type'] = '公众号充值';
|
||||
break;
|
||||
case 'alipay':
|
||||
$item['_recharge_type'] = '支付宝充值';
|
||||
break;
|
||||
case 'balance':
|
||||
$item['_recharge_type'] = '佣金转入';
|
||||
break;
|
||||
case 'store':
|
||||
$item['_recharge_type'] = '门店余额充值';
|
||||
break;
|
||||
default:
|
||||
$item['_recharge_type'] = '其他充值';
|
||||
break;
|
||||
}
|
||||
$item['_pay_time'] = $item['pay_time'] ? date('Y-m-d H:i:s', $item['pay_time']) : '暂无';
|
||||
$item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '暂无';
|
||||
$item['paid_type'] = $item['paid'] ? '已支付' : '待付款';
|
||||
unset($item['user']);
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户充值数据
|
||||
* @return array
|
||||
*/
|
||||
public function user_recharge(array $where)
|
||||
{
|
||||
$data = [];
|
||||
$where['paid'] = 1;
|
||||
$data['sumPrice'] = $this->getRechargeSum($where, 'price');
|
||||
$data['sumRefundPrice'] = $this->getRechargeSum($where, 'refund_price');
|
||||
$where['recharge_type'] = 'routine';
|
||||
$data['sumRoutinePrice'] = $this->getRechargeSum($where, 'price');
|
||||
$where['recharge_type'] = 'weixin';
|
||||
$data['sumWeixinPrice'] = $this->getRechargeSum($where, 'price');
|
||||
return [
|
||||
[
|
||||
'name' => '充值总金额',
|
||||
'field' => '元',
|
||||
'count' => $data['sumPrice'],
|
||||
'className' => 'logo-yen',
|
||||
'col' => 6,
|
||||
],
|
||||
[
|
||||
'name' => '充值退款金额',
|
||||
'field' => '元',
|
||||
'count' => $data['sumRefundPrice'],
|
||||
'className' => 'logo-usd',
|
||||
'col' => 6,
|
||||
],
|
||||
[
|
||||
'name' => '小程序充值金额',
|
||||
'field' => '元',
|
||||
'count' => $data['sumRoutinePrice'],
|
||||
'className' => 'logo-bitcoin',
|
||||
'col' => 6,
|
||||
],
|
||||
[
|
||||
'name' => '公众号充值金额',
|
||||
'field' => '元',
|
||||
'count' => $data['sumWeixinPrice'],
|
||||
'className' => 'ios-bicycle',
|
||||
'col' => 6,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款表单
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function refund_edit(int $id)
|
||||
{
|
||||
$UserRecharge = $this->getRecharge($id);
|
||||
if (!$UserRecharge) {
|
||||
throw new AdminException('数据不存在!');
|
||||
}
|
||||
if ($UserRecharge['paid'] != 1) {
|
||||
throw new AdminException('订单未支付');
|
||||
}
|
||||
if ($UserRecharge['price'] == $UserRecharge['refund_price']) {
|
||||
throw new AdminException('已退完支付金额!不能再退款了');
|
||||
}
|
||||
if ($UserRecharge['recharge_type'] == 'balance') {
|
||||
throw new AdminException('佣金转入余额,不能退款');
|
||||
}
|
||||
$f = array();
|
||||
$f[] = Form::input('order_id', '退款单号', $UserRecharge->getData('order_id'))->disabled(true);
|
||||
$f[] = Form::radio('refund_price', '状态', 1)->options([['label' => '本金(扣赠送余额)', 'value' => 1], ['label' => '仅本金', 'value' => 0]]);
|
||||
// $f[] = Form::number('refund_price', '退款金额', (float)$UserRecharge->getData('price'))->min(0)->max($UserRecharge->getData('price'));
|
||||
// if ($UserRecharge['store_id']) {
|
||||
// return create_form('退款', $f, Url::buildUrl('/order/recharge/' . $id), 'PUT');
|
||||
// } else {
|
||||
return create_form('退款', $f, Url::buildUrl('/finance/recharge/' . $id), 'PUT');
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 充值退款操作
|
||||
* @param int $id
|
||||
* @param $refund_price
|
||||
* @return mixed
|
||||
*/
|
||||
public function refund_update(int $id, string $refund_price)
|
||||
{
|
||||
$UserRecharge = $this->getRecharge($id);
|
||||
if (!$UserRecharge) {
|
||||
throw new AdminException('数据不存在!');
|
||||
}
|
||||
if ($UserRecharge['price'] == $UserRecharge['refund_price']) {
|
||||
throw new AdminException('已退完支付金额!不能再退款了');
|
||||
}
|
||||
if ($UserRecharge['recharge_type'] == 'balance') {
|
||||
throw new AdminException('佣金转入余额,不能退款');
|
||||
}
|
||||
$UserRecharge = $UserRecharge->toArray();
|
||||
|
||||
// $data['refund_price'] = bcadd($refund_price, $UserRecharge['refund_price'], 2);
|
||||
$data['refund_price'] = $UserRecharge['price'];
|
||||
// $bj = bccomp((string)$UserRecharge['price'], (string)$data['refund_price'], 2);
|
||||
// if ($bj < 0) {
|
||||
// throw new AdminException('退款金额大于支付金额,请修改退款金额');
|
||||
// }
|
||||
$refund_data['pay_price'] = $UserRecharge['price'];
|
||||
$refund_data['refund_price'] = $UserRecharge['price'];
|
||||
// $refund_data['refund_account']='REFUND_SOURCE_RECHARGE_FUNDS';
|
||||
if ($refund_price == 1) {
|
||||
$number = bcadd($UserRecharge['price'], $UserRecharge['give_price'], 2);
|
||||
} else {
|
||||
$number = $UserRecharge['price'];
|
||||
}
|
||||
|
||||
try {
|
||||
$recharge_type = $UserRecharge['recharge_type'];
|
||||
switch ($recharge_type) {
|
||||
case 'alipay'://支付宝
|
||||
mt_srand();
|
||||
$refund_id = $refundData['refund_id'] ?? $UserRecharge['order_id'] . rand(100, 999);
|
||||
//支付宝退款
|
||||
AliPayService::instance()->refund($UserRecharge['order_id'], $refund_data['refund_price'], $refund_id);
|
||||
break;
|
||||
case 'wexin'://微信
|
||||
$pay_routine_open = (bool)sys_config('pay_routine_open', 0);
|
||||
if ($pay_routine_open) {
|
||||
$refund_data['refund_no'] = $UserRecharge['order_id']; // 退款订单号
|
||||
/** @var WechatUserServices $wechatUserServices */
|
||||
$wechatUserServices = app()->make(WechatUserServices::class);
|
||||
$refund_data['open_id'] = $wechatUserServices->value(['uid' => (int)$UserRecharge['uid']], 'openid');
|
||||
$refund_data['routine_order_id'] = $UserRecharge['order_id'];
|
||||
$refund_data['pay_routine_open'] = true;
|
||||
}
|
||||
$transaction_id = $UserRecharge['trade_no'];
|
||||
if (!$transaction_id) {
|
||||
$refund_data['type'] = 'out_trade_no';
|
||||
$transaction_id = $UserRecharge['order_id'];
|
||||
} else {
|
||||
$refund_data['type'] = 'transaction_id';
|
||||
}
|
||||
|
||||
if (!sys_config('wechat_appid')) {
|
||||
//APP退款
|
||||
Payment::instance()->setAccessEnd(Payment::APP)->payOrderRefund($transaction_id, $refund_data);
|
||||
} else {
|
||||
//微信公众号退款
|
||||
Payment::instance()->setAccessEnd(Payment::WEB)->payOrderRefund($transaction_id, $refund_data);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 'routine'://小程序
|
||||
$transaction_id = $UserRecharge['trade_no'];
|
||||
if (!$transaction_id) {
|
||||
$refund_data['type'] = 'out_trade_no';
|
||||
$transaction_id = $UserRecharge['order_id'];
|
||||
} else {
|
||||
$refund_data['type'] = 'transaction_id';
|
||||
}
|
||||
Payment::instance()->setAccessEnd(Payment::MINI)->payOrderRefund($transaction_id, $refund_data);
|
||||
break;
|
||||
case 'cash'://现金
|
||||
break;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new AdminException($e->getMessage());
|
||||
}
|
||||
if (!$this->dao->update($id, $data)) {
|
||||
throw new AdminException('修改提现数据失败');
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo((int)$UserRecharge['uid']);
|
||||
if ($userInfo['now_money'] > $number) {
|
||||
$now_money = bcsub((string)$userInfo['now_money'], $number, 2);
|
||||
} else {
|
||||
$number = $userInfo['now_money'];
|
||||
$now_money = 0;
|
||||
}
|
||||
//修改用户余额
|
||||
$userServices->update((int)$UserRecharge['uid'], ['now_money' => $now_money], 'uid');
|
||||
$UserRecharge['nickname'] = $userInfo['nickname'];
|
||||
$UserRecharge['phone'] = $userInfo['phone'];
|
||||
|
||||
/** @var UserMoneyServices $userMoneyServices */
|
||||
$userMoneyServices = app()->make(UserMoneyServices::class);
|
||||
//保存余额记录
|
||||
$userMoneyServices->income('user_recharge_refund', $UserRecharge['uid'], $number, $now_money, $id);
|
||||
|
||||
//充值退款事件
|
||||
event('user.rechargeRefund', [$UserRecharge, $data]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delRecharge(int $id)
|
||||
{
|
||||
$rechargInfo = $this->getRecharge($id);
|
||||
if (!$rechargInfo) throw new AdminException('订单未找到');
|
||||
if ($rechargInfo->paid) {
|
||||
throw new AdminException('已支付的订单记录无法删除');
|
||||
}
|
||||
if ($this->dao->delete($id))
|
||||
return true;
|
||||
else
|
||||
throw new AdminException('删除失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成充值订单号
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getOrderId()
|
||||
{
|
||||
return 'wx' . date('YmdHis', time()) . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入佣金到余额
|
||||
* @param int $uid
|
||||
* @param $price
|
||||
* @param string $type recharge : 充值流程 extract:提现流程
|
||||
* @return bool
|
||||
*/
|
||||
public function importNowMoney(int $uid, $price, string $type = 'recharge')
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$broken_commission = $userBrokerageServices->getUserFrozenPrice($uid);
|
||||
$commissionCount = bcsub((string)$user['brokerage_price'], (string)$broken_commission, 2);
|
||||
if ($price > $commissionCount && $type == 'recharge') {
|
||||
throw new ValidateException('转入金额不能大于可提现佣金!');
|
||||
}
|
||||
return $this->transaction(function () use ($uid, $user, $price, $userServices, $type) {
|
||||
$edit_data = [];
|
||||
$edit_data['now_money'] = bcadd((string)$user['now_money'], (string)$price, 2);
|
||||
//写入充值记录
|
||||
$rechargeInfo = [
|
||||
'uid' => $uid,
|
||||
'order_id' => $this->getOrderId(),
|
||||
'recharge_type' => 'balance',
|
||||
'price' => $price,
|
||||
'give_price' => 0,
|
||||
'paid' => 1,
|
||||
'pay_time' => time(),
|
||||
'add_time' => time()
|
||||
];
|
||||
//写入充值记录
|
||||
$re = $this->dao->save($rechargeInfo);
|
||||
/** @var UserMoneyServices $userMoneyServices */
|
||||
$userMoneyServices = app()->make(UserMoneyServices::class);
|
||||
//余额记录
|
||||
$userMoneyServices->income('brokerage_to_nowMoney', $uid, $price, $edit_data['now_money'], $re['id']);
|
||||
//佣金充值写入提现记录
|
||||
if ($type == 'recharge') {
|
||||
//修改用户佣金
|
||||
$edit_data['brokerage_price'] = $user['brokerage_price'] > $price ? bcsub((string)$user['brokerage_price'], (string)$price, 2) : 0;
|
||||
$extractInfo = [
|
||||
'uid' => $uid,
|
||||
'real_name' => $user['nickname'],
|
||||
'extract_type' => 'balance',
|
||||
'extract_price' => $price,
|
||||
'balance' => $edit_data['brokerage_price'],
|
||||
'add_time' => time(),
|
||||
'status' => 1
|
||||
];
|
||||
/** @var UserExtractServices $userExtract */
|
||||
$userExtract = app()->make(UserExtractServices::class);
|
||||
//写入提现记录
|
||||
$userExtract->save($extractInfo);
|
||||
//佣金提现记录
|
||||
/** @var UserBrokerageServices $userBrokerageServices */
|
||||
$userBrokerageServices = app()->make(UserBrokerageServices::class);
|
||||
$userBrokerageServices->income('brokerage_to_nowMoney', $uid, $price, $edit_data['brokerage_price'], $re['id']);
|
||||
}
|
||||
//修改用户佣金、余额信息
|
||||
$userServices->update($uid, $edit_data, 'uid');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请充值
|
||||
* @param int $uid
|
||||
* @param $price
|
||||
* @param $recharId
|
||||
* @param $type
|
||||
* @param $from
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function recharge(int $uid, $price, $recharId, $type, $from)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$paid_price = 0;
|
||||
if ($recharId && $type != 1) {
|
||||
/** @var SystemGroupDataServices $systemGroupData */
|
||||
$systemGroupData = app()->make(SystemGroupDataServices::class);
|
||||
$data = $systemGroupData->getDateValue($recharId);
|
||||
if (!$data) {
|
||||
throw new ValidateException('您选择的充值方式已下架!');
|
||||
} else {
|
||||
$paid_price = $data['give_money'] ?? 0;
|
||||
}
|
||||
$price = $data['price'];
|
||||
}
|
||||
switch ((int)$type) {
|
||||
case 0: //支付充值余额
|
||||
/** @var StoreOrderCreateServices $orderCreateServices */
|
||||
$orderCreateServices = app()->make(StoreOrderCreateServices::class);
|
||||
$recharge_data = [];
|
||||
$recharge_data['order_id'] = $orderCreateServices->getNewOrderId('cz');
|
||||
$recharge_data['uid'] = $uid;
|
||||
$recharge_data['price'] = $price;
|
||||
$recharge_data['recharge_type'] = $from;
|
||||
$recharge_data['paid'] = 0;
|
||||
$recharge_data['add_time'] = time();
|
||||
$recharge_data['give_price'] = $paid_price;
|
||||
$recharge_data['channel_type'] = $user['user_type'];
|
||||
if (!$rechargeOrder = $this->dao->save($recharge_data)) {
|
||||
throw new ValidateException('充值订单生成失败');
|
||||
}
|
||||
return ['msg' => '', 'type' => $from, 'data' => $rechargeOrder];
|
||||
break;
|
||||
case 1: //佣金转入余额
|
||||
$this->importNowMoney($uid, $price);
|
||||
return ['msg' => '转入余额成功', 'type' => $from, 'data' => []];
|
||||
break;
|
||||
default:
|
||||
throw new ValidateException('缺少参数');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户充值成功
|
||||
* @param $orderId
|
||||
* @return bool
|
||||
* @throws \think\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function rechargeSuccess($orderId, array $other = [])
|
||||
{
|
||||
$order = $this->dao->getOne(['order_id' => $orderId, 'paid' => 0]);
|
||||
if (!$order) {
|
||||
throw new ValidateException('订单失效或者不存在');
|
||||
}
|
||||
$order = $order->toArray();
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo((int)$order['uid']);
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$price = bcadd((string)$order['price'], (string)$order['give_price'], 2);
|
||||
if (!$this->dao->update($order['id'], ['paid' => 1, 'pay_time' => time(), 'trade_no' => $other['trade_no'] ?? ''], 'id')) {
|
||||
throw new ValidateException('修改订单失败');
|
||||
}
|
||||
$now_money = bcadd((string)$user['now_money'], (string)$price, 2);
|
||||
/** @var UserMoneyServices $userMoneyServices */
|
||||
$userMoneyServices = app()->make(UserMoneyServices::class);
|
||||
$userMoneyServices->income('user_recharge', $user['uid'], ['number' => $price, 'price' => $order['price'], 'give_price' => $order['give_price']], $now_money, $order['id']);
|
||||
if (!$userServices->update((int)$order['uid'], ['now_money' => $now_money], 'uid')) {
|
||||
throw new ValidateException('修改用户信息失败');
|
||||
}
|
||||
|
||||
$order['nickname'] = $user['nickname'];
|
||||
$order['phone'] = $user['phone'];
|
||||
$order['trade_no'] = $other['trade_no'] ?? '';
|
||||
$order['pay_time'] = time();
|
||||
|
||||
//用户充值成功事件
|
||||
event('user.recharge', [$order, $now_money]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据查询用户充值金额
|
||||
* @param array $where
|
||||
* @return float|int
|
||||
*/
|
||||
public function getRechargeMoneyByWhere(array $where, string $rechargeSumField, string $selectType, string $group = "")
|
||||
{
|
||||
switch ($selectType) {
|
||||
case "sum" :
|
||||
return $this->dao->getWhereSumField($where, $rechargeSumField);
|
||||
case "group" :
|
||||
return $this->dao->getGroupField($where, $rechargeSumField, $group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 充值每日统计数据
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param array $time
|
||||
* @return array
|
||||
*/
|
||||
public function getDataPriceCount(int $store_id, int $staff_id = 0, $time = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where = ['paid' => 1, 'time' => $time];
|
||||
if ($staff_id) {
|
||||
$where['staff_id'] = $staff_id;
|
||||
}
|
||||
return $this->dao->getDataPriceCount($where, ['sum(price) as price', 'count(id) as count', 'FROM_UNIXTIME(add_time, \'%m-%d\') as time'], $page, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店充值统计详情列表
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param array $time
|
||||
* @return array|array[]
|
||||
*/
|
||||
public function time(int $store_id, int $staff_id, array $time = [])
|
||||
{
|
||||
if (!$time) {
|
||||
return [[], []];
|
||||
}
|
||||
[$start, $stop, $front, $front_stop] = $time;
|
||||
$where = ['paid' => 1];
|
||||
if ($staff_id) $where['staff_id'] = $staff_id;
|
||||
$frontPrice = $this->dao->sum($where + ['time' => [$front, $front_stop]], 'price', true);
|
||||
$nowPrice = $this->dao->sum($where + ['time' => [$start, $stop]], 'price', true);
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where + ['time' => [$start, $stop]], 'id,uid,order_id,price,add_time', $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
return [[$nowPrice, $frontPrice], $list];
|
||||
}
|
||||
}
|
||||
295
app/services/user/UserRelationServices.php
Normal file
295
app/services/user/UserRelationServices.php
Normal file
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
|
||||
use app\dao\user\UserRelationDao;
|
||||
use app\services\activity\video\VideoServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\services\user\level\SystemUserLevelServices;
|
||||
use app\services\user\member\MemberCardServices;
|
||||
use think\annotation\Inject;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class UserRelationServices
|
||||
* @package app\services\user
|
||||
* @mixin UserRelationDao
|
||||
*/
|
||||
class UserRelationServices extends BaseServices
|
||||
{
|
||||
|
||||
const CATEGORY_PRODUCT = 'product';//商品
|
||||
const CATEGORY_ARTICLE = 'article';//文章
|
||||
const CATEGORY_REPLY = 'reply';//评价
|
||||
const CATEGORY_COMMENT = 'comment';//评价回复
|
||||
const CATEGORY_VIDEO = 'video';//短视频
|
||||
const CATEGORY_VIDEO_COMMENT = 'video_comment';//短视频评价
|
||||
|
||||
const TYPE_COLLECT = 'collect';//收藏
|
||||
const TYPE_LIKE = 'like';//点赞
|
||||
const TYPE_SHARE = 'share';//分享
|
||||
const TYPE_PLAY = 'play';//播放
|
||||
|
||||
const TYPE_NAME = [
|
||||
'collect' => '收藏',
|
||||
'like' => '点赞',
|
||||
'share' => '分享',
|
||||
'play' => '播放',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var UserRelationDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserRelationDao $dao;
|
||||
|
||||
/**
|
||||
* 用户是否点赞或收藏商品
|
||||
* @param array $where
|
||||
* @return bool
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function isProductRelation(array $where)
|
||||
{
|
||||
$res = $this->dao->getOne($where, 'id');
|
||||
if ($res) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $where
|
||||
* @return mixed
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2022/11/17
|
||||
*/
|
||||
public function isProductRelationCache(array $where)
|
||||
{
|
||||
return $this->cacheTag()->remember(md5(json_encode($where)), function () use ($where) {
|
||||
return $this->isProductRelation($where);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户收藏数量
|
||||
* @param int $uid
|
||||
* @param int $relationId
|
||||
* @param string $type
|
||||
* @param string $category
|
||||
* @return int
|
||||
*/
|
||||
public function getUserCount(int $uid, int $relationId = 0, string $type = self::TYPE_COLLECT, string $category = self::CATEGORY_PRODUCT)
|
||||
{
|
||||
$where = ['uid' => $uid];
|
||||
if ($type) {
|
||||
$where['type'] = $type;
|
||||
}
|
||||
if ($category) {
|
||||
$where['category'] = $category;
|
||||
}
|
||||
if ($relationId) {
|
||||
$where['relation_id'] = $relationId;
|
||||
}
|
||||
return $this->dao->count($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @return mixed
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function getUserRelationList(int $uid, string $category = self::CATEGORY_PRODUCT, string $type = self::TYPE_COLLECT)
|
||||
{
|
||||
$where['uid'] = $uid;
|
||||
$where['type'] = $type;
|
||||
$where['category'] = $category;
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$with = [];
|
||||
switch ($category) {
|
||||
case 'product':
|
||||
$with = ['product'];
|
||||
break;
|
||||
case 'video':
|
||||
$with = ['video'];
|
||||
break;
|
||||
}
|
||||
//短视频未启用
|
||||
if ($category == 'video' && !sys_config('video_func_status', 1)) {
|
||||
$list = [];
|
||||
} else {
|
||||
$list = $this->dao->getList($where, 'relation_id,category', $with, $page, $limit);
|
||||
}
|
||||
$result = [];
|
||||
foreach ($list as $k => $item) {
|
||||
switch ($category) {
|
||||
case 'product':
|
||||
if (isset($item['product']) && isset($item['product']['id'])) {
|
||||
$product = $item['product'];
|
||||
$discount = 100;
|
||||
/** @var UserServices $user */
|
||||
$user = app()->make(UserServices::class);
|
||||
$userInfo = $user->getUserCacheInfo($uid);
|
||||
//用户等级是否开启
|
||||
/** @var SystemUserLevelServices $systemLevel */
|
||||
$systemLevel = app()->make(SystemUserLevelServices::class);
|
||||
$levelInfo = $systemLevel->getLevelCache((int)($userInfo['level'] ?? 0));
|
||||
if (sys_config('member_func_status', 1) && $levelInfo) {
|
||||
$discount = $levelInfo['discount'] ?? 100;
|
||||
}
|
||||
$level_name = $levelInfo['name'] ?? '';
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$vipStatus = $memberCardService->isOpenMemberCardCache('vip_price') && sys_config('svip_price_status', 1);
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
$minData = $productServices->getMinPrice($uid, $product, $discount);
|
||||
$vip_price = $level_price = 0.00;
|
||||
if (($minData['price_type'] ?? '') == 'member') {
|
||||
$vip_price = $minData['vip_price'] ?? 0;
|
||||
if (!$product['is_vip'] || !$vipStatus) {
|
||||
$vip_price = 0;
|
||||
}
|
||||
} else {
|
||||
$level_price = $minData['vip_price'] ?? 0;
|
||||
}
|
||||
$data = [
|
||||
'id' => $product['id'] ?? 0,
|
||||
'product_id' => $item['relation_id'],
|
||||
'store_name' => $product['store_name'] ?? 0,
|
||||
'price_type' => $minData['price_type'],
|
||||
'price' => $product['price'] ?? 0,
|
||||
'is_presale_product' => $product['is_presale_product'] ?? 0,
|
||||
'vip_price' => $vip_price ?? 0,
|
||||
'level_name' => $level_name,
|
||||
'level_price' => $level_price,
|
||||
'freight' => $product['freight'] ?? 0,
|
||||
'ot_price' => $product['ot_price'] ?? 0,
|
||||
'sales' => $product['sales'] ?? 0,
|
||||
'image' => get_thumb_water($product['image'] ?? 0),
|
||||
'is_del' => $product['is_del'] ?? 0,
|
||||
'is_show' => $product['is_show'] ?? 0,
|
||||
'is_fail' => $product['is_del'] && $product['is_show'],
|
||||
'activity' => $product['activity'] ?? ''
|
||||
];
|
||||
$result[] = $data;
|
||||
}
|
||||
break;
|
||||
case 'video':
|
||||
if (isset($item['video']) && isset($item['video']['id'])) {
|
||||
$video = $item['video'];
|
||||
$data = [
|
||||
'id' => $video['id'] ?? 0,
|
||||
'video_id' => $item['relation_id'],
|
||||
'image' => $video['image'] ?? '',
|
||||
'site_name' => sys_config('site_name'),
|
||||
'wap_login_logo' => sys_config('wap_login_logo'),
|
||||
'desc' => $video['desc'] ?? '',
|
||||
'video_url' => $video['video_url'] ?? '',
|
||||
'like_num' => $video['like_num'] ?? 0
|
||||
];
|
||||
$result[] = $data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($result && $category == 'product') {
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
$result = $productServices->getActivityList($result);
|
||||
$result = $productServices->getProductPromotions($result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加|取消 点赞 收藏
|
||||
* @param int $uid
|
||||
* @param array $productIds
|
||||
* @param string $relationType
|
||||
* @param string $category
|
||||
* @param bool $isDec
|
||||
* @return bool
|
||||
*/
|
||||
public function productRelation(int $uid, array $productIds, string $relationType = self::TYPE_COLLECT, string $category = self::CATEGORY_PRODUCT, bool $isDec = false)
|
||||
{
|
||||
$relationType = strtolower($relationType);
|
||||
$category = strtolower($category);
|
||||
if ($isDec) {//取消
|
||||
$storeProductRelation = $this->dao->delete(['uid' => $uid, 'relation_id' => $productIds, 'type' => $relationType, 'category' => $category]);
|
||||
if (!$storeProductRelation) throw new ValidateException('取消失败');
|
||||
if ($category == 'video') {
|
||||
/** @var VideoServices $videoServices */
|
||||
$videoServices = app()->make(VideoServices::class);
|
||||
foreach ($productIds as $id) {
|
||||
$videoServices->bcDec($id, $relationType . '_num', 1);
|
||||
}
|
||||
}
|
||||
$ids = $productIds;
|
||||
} else {
|
||||
$relationId = $this->dao->getColumn([['uid', '=', $uid], ['relation_id', 'IN', $productIds], ['type', '=', $relationType], ['category', '=', $category]], 'relation_id');
|
||||
$data = ['uid' => $uid, 'add_time' => time(), 'type' => $relationType, 'category' => $category];
|
||||
$dataAll = [];
|
||||
$ids = [];
|
||||
foreach ($productIds as $key => $product_id) {
|
||||
if (in_array($product_id, $relationId)) {
|
||||
continue;
|
||||
}
|
||||
$ids[] = $product_id;
|
||||
$data['relation_id'] = $product_id;
|
||||
$dataAll[] = $data;
|
||||
}
|
||||
if ($dataAll) {
|
||||
if (!$this->dao->saveAll($dataAll)) {
|
||||
throw new ValidateException('添加失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($ids && $category == 'product') {
|
||||
event('product.collect', [$uid, $ids, $isDec]);
|
||||
}
|
||||
$this->cacheTag()->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算商品收藏数
|
||||
* @param int $id
|
||||
* @return bool
|
||||
* @throws DbException
|
||||
*/
|
||||
public function computedProductCollect(int $id)
|
||||
{
|
||||
/** @var StoreProductServices $productServices */
|
||||
$productServices = app()->make(StoreProductServices::class);
|
||||
$productInfo = $productServices->get($id, ['id', 'collect']);
|
||||
if ($productInfo) {
|
||||
$collect = $this->dao->count(['relation_id' => $id, 'type' => self::TYPE_COLLECT, 'category'=> self::CATEGORY_PRODUCT]);
|
||||
$productServices->update(['id' => $id], ['collect' => $collect]);
|
||||
$productServices->cacheTag()->clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
129
app/services/user/UserSearchServices.php
Normal file
129
app/services/user/UserSearchServices.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use app\dao\user\UserSearchDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserLabelServices
|
||||
* @package app\services\user
|
||||
* @mixin UserSearchDao
|
||||
*/
|
||||
class UserSearchServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserSearchDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserSearchDao $dao;
|
||||
|
||||
/**
|
||||
* 分词搜索得到ids
|
||||
* @param int $uid
|
||||
* @param string $keyword
|
||||
* @param array $where
|
||||
* @param bool $isSearch
|
||||
* @return array|mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function vicSearch(int $uid, string $keyword, array $where, bool $isSearch = true)
|
||||
{
|
||||
//分词
|
||||
// try {
|
||||
// $vicWordArr = \crmeb\services\VicWordService::instance()->getWord($keyword);
|
||||
// } catch (\Throwable $e) {
|
||||
// $vicWordArr = [];
|
||||
// }
|
||||
$vicWordArr = [];
|
||||
if ($vicWordArr) {
|
||||
$vicword = $vicWordArr;
|
||||
unset($where['store_name']);
|
||||
$where['keyword'] = $vicWordArr;
|
||||
}
|
||||
$result = $this->dao->getKeywordResult(0, $keyword);
|
||||
$ids = [];
|
||||
if ($result && isset($result['result']) && $result['result']) {//之前查询结果记录
|
||||
$ids = $result['result'];
|
||||
} else {//分词查询
|
||||
|
||||
}
|
||||
//搜索没有记录
|
||||
if (!$ids && $where) {
|
||||
//查出所有结果ids存搜索记录表
|
||||
/** @var StoreProductServices $services */
|
||||
$services = app()->make(StoreProductServices::class);
|
||||
$idsArr = $services->getSearchList($where, 0, 0, ['id'], '', []);
|
||||
if ($idsArr) {
|
||||
$ids = array_column($idsArr, 'id');
|
||||
}
|
||||
}
|
||||
$vicword = [];
|
||||
// $vicword = is_string($vicword) ? [$vicword] : $vicword;
|
||||
if ($isSearch) {
|
||||
$this->saveUserSearch($uid, $keyword, $vicword, $ids);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户搜索关键词列表
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserList(int $uid)
|
||||
{
|
||||
if (!$uid) {
|
||||
return [];
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
return $this->dao->getList(['uid' => $uid, 'is_del' => 0], 'id,keyword,num', $page, $limit,'add_time desc,num desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户增加搜索记录
|
||||
* @param int $uid
|
||||
* @param string $key
|
||||
* @param array $result
|
||||
*/
|
||||
public function saveUserSearch(int $uid, string $keyword, array $vicword, array $result)
|
||||
{
|
||||
$result = json_encode($result);
|
||||
$vicword = json_encode($vicword, JSON_UNESCAPED_UNICODE);
|
||||
$userkeyword = $this->dao->getKeywordResult($uid, $keyword, 0);
|
||||
$data = [];
|
||||
$data['result'] = $result;
|
||||
$data['vicword'] = $vicword;
|
||||
$data['add_time'] = time();
|
||||
if ($userkeyword) {
|
||||
$data['num'] = $userkeyword['num'] + 1;
|
||||
$this->dao->update(['id' => $userkeyword['id']], $data);
|
||||
} else {
|
||||
$data['uid'] = $uid;
|
||||
$data['keyword'] = $keyword;
|
||||
$this->dao->save($data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
3094
app/services/user/UserServices.php
Normal file
3094
app/services/user/UserServices.php
Normal file
File diff suppressed because it is too large
Load Diff
545
app/services/user/UserSignServices.php
Normal file
545
app/services/user/UserSignServices.php
Normal file
@@ -0,0 +1,545 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\jobs\user\UserLevelJob;
|
||||
use app\services\BaseServices;
|
||||
use app\services\system\SystemSignRewardServices;
|
||||
use app\services\user\member\MemberCardServices;
|
||||
use app\dao\user\UserSignDao;
|
||||
use crmeb\exceptions\ApiException;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserSignServices
|
||||
* @package app\services\user
|
||||
* @mixin UserSignDao
|
||||
*/
|
||||
class UserSignServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserSignDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserSignDao $dao;
|
||||
|
||||
/**
|
||||
* 返回签到列表数据
|
||||
* @param $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function signConfig($uid)
|
||||
{
|
||||
//获取周签到还是月签到
|
||||
$signMode = (int)sys_config('sign_mode', 1);
|
||||
|
||||
//获取签到列表
|
||||
$startDate = $signMode == 1 ? strtotime('this week Monday') : strtotime('first day of this month midnight');
|
||||
$endDate = $signMode == 1 ? strtotime('this week Sunday') : strtotime('last day of this month midnight');
|
||||
$dateList = range($startDate, $endDate, 86400);
|
||||
|
||||
$checkSign = $this->getIsSign($uid, 'today');
|
||||
|
||||
|
||||
$sign_give_point = (int)sys_config('sign_give_point', 0);
|
||||
$sign_exp = sys_config('member_func_status', 1) ? sys_config('sign_give_exp', 0) : 0;
|
||||
[$signList, $continuousSignDays, $cumulativeSignDays, $nextContinuousDays, $nextCumulativeDays] = $this->signDataFilling($signMode, $uid, $sign_give_point, $sign_exp, $dateList, '');
|
||||
|
||||
//格式化签到数据
|
||||
// $signList = array_chunk($signList, 7);
|
||||
|
||||
//获取用户签到提醒状态
|
||||
$signRemindStatus = app()->make(UserServices::class)->value(['uid' => $uid], 'sign_remind');
|
||||
|
||||
//是否显示签到提醒开关
|
||||
$signRemindSwitch = (int)sys_config('sign_remind', 0);
|
||||
|
||||
//签到功能是否关闭
|
||||
$signStatus = (int)sys_config('sign_status', 0);
|
||||
|
||||
$signData['sign_point'] = $sign_give_point;
|
||||
$signData['sign_exp'] = $sign_exp;
|
||||
|
||||
|
||||
return compact('signList', 'continuousSignDays', 'cumulativeSignDays', 'nextContinuousDays', 'nextCumulativeDays', 'signMode', 'checkSign', 'signRemindStatus', 'signRemindSwitch', 'signStatus', 'signData');
|
||||
}
|
||||
|
||||
/**
|
||||
* 日历数据
|
||||
* @param $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getCalendarDate($uid, $time)
|
||||
{
|
||||
$startDate = strtotime(date('Y-m-01', strtotime($time)));
|
||||
$endDate = strtotime(date('Y-m-d', strtotime(date('Y-m-01', strtotime($time)) . ' +1 month -1 day')));
|
||||
$dateList = range($startDate, $endDate, 86400);
|
||||
$checkSign = $this->getIsSign($uid, 'today');
|
||||
$sign_give_point = (int)sys_config('sign_give_point', 0);
|
||||
$sign_exp = sys_config('member_func_status', 1) ? sys_config('sign_give_exp', 0) : 0;
|
||||
$today = date("Y-m-d"); // 今日日期
|
||||
$w = date('w', $startDate); //月初周几
|
||||
[$signList, $continuousSignDays, $cumulativeSignDays, $nextContinuousDays, $nextCumulativeDays] = $this->signDataFilling(0, $uid, $sign_give_point, $sign_exp, $dateList, $time);
|
||||
return compact('today', 'w', 'signList', 'continuousSignDays', 'cumulativeSignDays', 'nextContinuousDays', 'nextCumulativeDays', 'checkSign');
|
||||
}
|
||||
|
||||
/**
|
||||
* 整理签到列表数据
|
||||
* @param $signMode
|
||||
* @param $uid
|
||||
* @param $sign_give_point
|
||||
* @param $sign_exp
|
||||
* @param $dateList
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function signDataFilling($signMode, $uid, $sign_give_point, $sign_exp, $dateList, $time)
|
||||
{
|
||||
if (!$time) $time = date('Y-m', time());
|
||||
|
||||
//获取已经签到的列表
|
||||
$list = $this->dao->getUserSignList($signMode, $uid, $time);
|
||||
|
||||
$sign_mode = sys_config('sign_mode', -1);
|
||||
|
||||
//获取累积签到和连续签到
|
||||
$cumulativeSignDays = $this->dao->getCumulativeDays($uid, $sign_mode); //获取累积签到天数
|
||||
$continuousSignDays = app()->make(UserServices::class)->value(['uid' => $uid], 'sign_num');//获取连续签到天数
|
||||
|
||||
//获取累积签到和连续签到奖励
|
||||
$nextCumulativeSignRewardList = app()->make(SystemSignRewardServices::class)->selectList(['type' => 1], '*', 1, 200, 'days asc')->toArray(); //累计签到奖励
|
||||
$nextContinuousSignRewardList = app()->make(SystemSignRewardServices::class)->selectList(['type' => 0], '*', 1, 200, 'days asc')->toArray(); //连续签到奖励
|
||||
|
||||
//下一次连续签到奖励还需签到几天
|
||||
$nextContinuousDays = 0;
|
||||
foreach ($nextContinuousSignRewardList as $continuousNext) {
|
||||
if ($continuousSignDays < $continuousNext['days']) {
|
||||
$nextContinuousDays = $continuousNext['days'] - $continuousSignDays > 0 ?: 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$nextCumulativeDays = 0;
|
||||
foreach ($nextCumulativeSignRewardList as $cumulativeNext) {
|
||||
if ($cumulativeSignDays < $cumulativeNext['days']) {
|
||||
$nextCumulativeDays = $cumulativeNext['days'] - $cumulativeSignDays > 0 ?: 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//整理签到列表数据
|
||||
$signList = [];
|
||||
$i = 0;
|
||||
|
||||
foreach ($dateList as $key => $time) {
|
||||
$day = date('m/d', $time);
|
||||
if ($day[0] == '0') $day = substr($day, 1);
|
||||
$signList[$key]['day'] = $day;
|
||||
$signList[$key]['is_sign'] = false;
|
||||
|
||||
//判断当前签到日期
|
||||
$signList[$key]['sign_day'] = date('Y-m-d', $time) == date('Y-m-d', time());
|
||||
|
||||
//判断今日是否签到
|
||||
foreach ($list as $value) {
|
||||
if (date('Y-m-d', $time) == date('Y-m-d', $value['add_time'])) {
|
||||
$signList[$key]['is_sign'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//处理处理签到类型展示,type 1积分,2经验
|
||||
$signList[$key]['type'] = $sign_give_point == 0 && sys_config('member_func_status', 1) == 1 && $sign_exp > 0 ? 2 : 1;
|
||||
$signList[$key]['point'] = $sign_give_point;
|
||||
$signList[$key]['days'] = 0; //连续、累计 奖励天数
|
||||
$signList[$key]['sign_type'] = 0; // 3连续签到奖励,4累计签到奖励
|
||||
if (date('Y-m-d', $time) >= date('Y-m-d', time())) {
|
||||
// 连续签到奖励
|
||||
foreach ($nextContinuousSignRewardList as $continuous) {
|
||||
if (($continuous['days'] - $continuousSignDays) == $i) {
|
||||
$signList[$key]['sign_type'] = 3;
|
||||
$signList[$key]['days'] = $continuous['days'];
|
||||
$signList[$key]['point'] = $continuous['point'];
|
||||
}
|
||||
}
|
||||
// 累计签到奖励
|
||||
foreach ($nextCumulativeSignRewardList as $cumulative) {
|
||||
if (($cumulative['days'] - $cumulativeSignDays) == $i) {
|
||||
$signList[$key]['sign_type'] = 4;
|
||||
$signList[$key]['days'] = $cumulative['days'];
|
||||
$signList[$key]['point'] = $cumulative['point'];
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return [$signList, $continuousSignDays, $cumulativeSignDays, $nextContinuousDays, $nextCumulativeDays];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户是否签到
|
||||
* @param int $uid
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsSign(int $uid, string $type = 'today')
|
||||
{
|
||||
return (bool)$this->dao->count(['uid' => $uid, 'time' => $type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户累计签到次数
|
||||
* @Parma int $uid 用户id
|
||||
* @return int
|
||||
* */
|
||||
public function getSignSumDay(int $uid)
|
||||
{
|
||||
return $this->dao->count(['uid' => $uid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置签到数据
|
||||
* @param int $uid 用户uid
|
||||
* @param string $title 签到说明
|
||||
* @param int $number 签到获得积分
|
||||
* @param int $integral_balance
|
||||
* @param int $exp_balance
|
||||
* @param int $exp_num
|
||||
* @return bool
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
public function setSignData($uid, $title = '', $number = 0, $up_num = 0, $integral_balance = 0, $exp_balance = 0, $exp_num = 0)
|
||||
{
|
||||
$data = [];
|
||||
$data['uid'] = $uid;
|
||||
$data['title'] = $title;
|
||||
$data['number'] = $number;
|
||||
$data['svip_number'] = $up_num;
|
||||
$data['balance'] = $integral_balance;
|
||||
$data['exp_num'] = $exp_num;
|
||||
$data['exp_balance'] = $exp_balance;
|
||||
$data['add_time'] = time();
|
||||
if (!$this->dao->save($data)) {
|
||||
throw new ValidateException('添加签到数据失败');
|
||||
}
|
||||
/** @var UserBillServices $userBill */
|
||||
$userBill = app()->make(UserBillServices::class);
|
||||
$data['mark'] = $title;
|
||||
unset($data['exp_num'], $data['exp_balance']);
|
||||
$userBill->incomeIntegral($uid, 'sign', $data);
|
||||
|
||||
if ($exp_num) {
|
||||
$data['number'] = $exp_num;
|
||||
$data['category'] = 'exp';
|
||||
$data['type'] = 'sign';
|
||||
$data['title'] = $data['mark'] = '签到奖励';
|
||||
$data['balance'] = $exp_balance + $exp_num;
|
||||
$data['pm'] = 1;
|
||||
$data['status'] = 1;
|
||||
if (!$userBill->save($data)) {
|
||||
throw new ValidateException('赠送经验失败');
|
||||
}
|
||||
//检测会员等级
|
||||
UserLevelJob::dispatch([$uid]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户签到列表
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserSignList(int $uid, string $field = '*')
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList(['uid' => $uid], $field, $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['svip_title'] = $item['svip_number'] > 0 ? 'SVIP +' . $item['svip_number'] . ' 积分' : '';
|
||||
$item['add_time'] = $item['add_time'] ? date('Y-m-d', $item['add_time']) : '';
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户签到
|
||||
* @param $uid
|
||||
* @return bool|int|mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function sign(int $uid)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
|
||||
//检测用户是否存在
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ApiException('用户不存在');
|
||||
}
|
||||
//签到是否关闭
|
||||
if (!sys_config('sign_status', 1)) {
|
||||
throw new ApiException('签到暂未开放');
|
||||
}
|
||||
//检测今天是否已经签到
|
||||
if ($this->getIsSign($uid, 'today')) {
|
||||
throw new ApiException('今日已签到');
|
||||
}
|
||||
$title = '签到奖励';
|
||||
//检测昨天是否签到,如果没有签到,连续签到清0
|
||||
if (!$this->getIsSign($uid, 'yesterday')) $user->sign_num = 0;
|
||||
|
||||
//获取签到周期配置,如果周签到,每周一清空连续签到记录,如果月签到,每月一日清空连续签到记录
|
||||
$sign_mode = sys_config('sign_mode', -1);
|
||||
if ($sign_mode == 1 && date('w') == 1) $user->sign_num = 0;
|
||||
if ($sign_mode == 0 && date('d') == 1) $user->sign_num = 0;
|
||||
|
||||
//连续签到天数
|
||||
$user->sign_num += 1;
|
||||
$continuousDays = $user->sign_num;
|
||||
//累积签到天数
|
||||
$cumulativeDays = $this->dao->getCumulativeDays($uid, $sign_mode) + 1;
|
||||
|
||||
//基础签到奖励
|
||||
$sign_point = sys_config('sign_give_point', 0);
|
||||
$sign_exp = sys_config('member_func_status', 1) ? sys_config('sign_give_exp', 0) : 0;
|
||||
|
||||
//连续签到和累积签到奖励
|
||||
$signRewardsServices = app()->make(SystemSignRewardServices::class);
|
||||
[$continuousStatus, $continuousRewardPoint, $continuousRewardExp] = $signRewardsServices->getSignRewards(0, $continuousDays);
|
||||
[$cumulativeStatus, $cumulativeRewardPoint, $cumulativeRewardExp] = $signRewardsServices->getSignRewards(1, $cumulativeDays);
|
||||
if ($continuousStatus && $cumulativeStatus) {
|
||||
$sign_point = $continuousRewardPoint + $cumulativeRewardPoint;
|
||||
$sign_exp = $continuousRewardExp + $cumulativeRewardExp;
|
||||
} elseif ($continuousStatus) {
|
||||
$sign_point = $continuousRewardPoint;
|
||||
$sign_exp = $continuousRewardExp;
|
||||
} elseif ($cumulativeStatus) {
|
||||
$sign_point = $cumulativeRewardPoint;
|
||||
$sign_exp = $cumulativeRewardExp;
|
||||
}
|
||||
$up_num = 0;
|
||||
//会员签到积分会员奖励
|
||||
if ($user->is_money_level > 0) {
|
||||
//看是否开启签到积分翻倍奖励
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$sign_rule_number = $memberCardService->isOpenMemberCard('sign');
|
||||
if ($sign_rule_number) {
|
||||
$up_num = (int)$sign_rule_number * $sign_point - $sign_point;
|
||||
$sign_point = (int)$sign_rule_number * $sign_point;
|
||||
// if (!$this->getIsSign($uid, 'yesterday')) $title = '签到奖励(SVIP+' . $up_num . '积分)';
|
||||
}
|
||||
}
|
||||
|
||||
//增加签到数据
|
||||
$this->transaction(function () use ($uid, $title, $sign_point, $user, $sign_exp, $up_num) {
|
||||
$this->setSignData($uid, $title, $sign_point, $up_num, $user['integral'], (int)$user['exp'], $sign_exp);
|
||||
if ($sign_point) $user->integral = (int)$user->integral + (int)$sign_point;
|
||||
if ($sign_exp && $user['level_status']) {//有经验 && 用户等级已经激活
|
||||
$user->exp = (int)$user->exp + (int)$sign_exp;
|
||||
}
|
||||
if (!$user->save()) {
|
||||
throw new ApiException('修改用户数据失败');
|
||||
}
|
||||
});
|
||||
return compact('sign_point', 'sign_exp');
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到用户信息
|
||||
* @param int $uid
|
||||
* @param $sign
|
||||
* @param $integral
|
||||
* @param $all
|
||||
* @return mixed
|
||||
*/
|
||||
public function signUser(int $uid, $sign, $integral, $all)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserCacheInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('数据不存在');
|
||||
}
|
||||
$data = ['uid' => $user['uid'], 'nickname' => $user['nickname'], 'phone' => $user['phone'], 'now_money' => $user['now_money'], 'integral' => $user['integral'], 'is_promoter' => $user['is_promoter'] ?? 0];
|
||||
//是否统计签到
|
||||
if ($sign || $all) {
|
||||
$data['sum_sgin_day'] = $this->getSignSumDay($uid);
|
||||
$data['is_day_sgin'] = $this->getIsSign($uid);
|
||||
$data['is_YesterDay_sgin'] = $this->getIsSign($uid, 'yesterday');
|
||||
if (!$data['is_day_sgin'] && !$data['is_YesterDay_sgin']) {
|
||||
$data['sign_num'] = 0;
|
||||
}
|
||||
}
|
||||
/** @var UserIntegralServices $userIntegralServices */
|
||||
$userIntegralServices = app()->make(UserIntegralServices::class);
|
||||
[$clear_integral, $clear_time] = $userIntegralServices->getUserClearIntegral($uid, $user);
|
||||
$data['clear_integral'] = $clear_integral;
|
||||
$data['clear_time'] = $clear_time;
|
||||
//是否统计积分使用情况
|
||||
if ($integral || $all) {
|
||||
/** @var UserBillServices $userBill */
|
||||
$userBill = app()->make(UserBillServices::class);
|
||||
$data['sum_integral'] = intval($userBill->getRecordCount($uid, 'integral', [], '', true));
|
||||
$data['deduction_integral'] = intval($userBill->getRecordCount($uid, 'integral') ?? 0);
|
||||
$data['today_integral'] = intval($userBill->getRecordCount($uid, 'integral', [], 'today', true));
|
||||
|
||||
$data['frozen_integral'] = $userBill->getBillSum(['uid' => $uid, 'is_frozen' => 1]);
|
||||
$data['integral_effective_status'] = (int)sys_config('integral_effective_status');
|
||||
$data['clear_end'] = '';
|
||||
if ($data['integral_effective_status']) {
|
||||
[$clear_end, $start, $end] = $userIntegralServices->getTime();
|
||||
$data['clear_end'] = date('Y-m-d', $clear_end);
|
||||
}
|
||||
}
|
||||
if (!$user['is_promoter']) {
|
||||
$data['is_promoter'] = (int)sys_config('store_brokerage_statu') == 2;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取签到
|
||||
* @param $uid
|
||||
* @return array
|
||||
*/
|
||||
public function getSignMonthList($uid)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$data = $this->dao->getListGroup(['uid' => $uid], 'FROM_UNIXTIME(add_time,"%Y-%m") as time,group_concat(id SEPARATOR ",") ids', $page, $limit, 'time');
|
||||
$list = [];
|
||||
if ($data) {
|
||||
$ids = array_unique(array_column($data, 'ids'));
|
||||
$dataIdsList = $this->dao->getList(['id' => $ids], 'FROM_UNIXTIME(add_time,"%Y-%m-%d") as add_time,title,number,exp_num,id,uid', 0, 0);
|
||||
foreach ($data as $item) {
|
||||
$value['month'] = $item['time'];
|
||||
$value['list'] = array_merge(array_filter($dataIdsList, function ($val) use ($item) {
|
||||
if (in_array($val['id'], explode(',', $item['ids']))) {
|
||||
return $val;
|
||||
}
|
||||
}));
|
||||
$list[] = $value;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到提醒设置
|
||||
* @param $uid
|
||||
* @param $status
|
||||
* @return bool
|
||||
*/
|
||||
public function setSignRemind($uid, $status)
|
||||
{
|
||||
app()->make(UserServices::class)->update($uid, ['sign_remind' => $status]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户签到提醒
|
||||
* @return bool
|
||||
*/
|
||||
public function userSignRemind()
|
||||
{
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$where = ['is_del' => 0, 'status' => 1, 'sign_remind' => 1];
|
||||
$userList = $userService->getColumn($where, 'uid,phone,sign_remind', 'uid');
|
||||
foreach ($userList as $key => $item) {
|
||||
if (!$this->getIsSign($item['uid'], 'today')) {
|
||||
event('notice.notice', [$item, 'sign_remind_time']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页diy签到数据
|
||||
* @param int $uid
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function homeDiysignData(int $uid = 0)
|
||||
{
|
||||
//获取签到列表
|
||||
$startDate = strtotime('this week Monday');
|
||||
$endDate = strtotime('this week Sunday');
|
||||
$dateList = range($startDate, $endDate, 86400);
|
||||
|
||||
$checkSign = $this->getIsSign($uid, 'today');
|
||||
|
||||
$sign_give_point = (int)sys_config('sign_give_point', 0);
|
||||
$sign_exp = sys_config('member_func_status', 1) ? sys_config('sign_give_exp', 0) : 0;
|
||||
|
||||
//获取连续签到奖励
|
||||
$nextContinuousSignRewardList = app()->make(SystemSignRewardServices::class)->selectList(['type' => 0], '*', 1, 1, 'days asc')->toArray(); //连续签到奖励
|
||||
$list = [];
|
||||
|
||||
if ($uid) {
|
||||
//获取已经签到的列表
|
||||
$list = $this->dao->getUserSignList(1, $uid, '');
|
||||
}
|
||||
//整理签到列表数据
|
||||
$signList = [];
|
||||
|
||||
foreach ($dateList as $key => $time) {
|
||||
$day = date('m/d', $time);
|
||||
if ($day[0] == '0') $day = substr($day, 1);
|
||||
$signList[$key]['day'] = $day;
|
||||
$signList[$key]['is_sign'] = false;
|
||||
|
||||
//判断当前签到日期
|
||||
$signList[$key]['sign_day'] = date('Y-m-d', $time) == date('Y-m-d', time());
|
||||
if ($list) {
|
||||
//判断今日是否签到
|
||||
foreach ($list as $value) {
|
||||
if (date('Y-m-d', $time) == date('Y-m-d', $value['add_time'])) {
|
||||
$signList[$key]['is_sign'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//处理处理签到类型展示,type 1积分,2经验
|
||||
$signList[$key]['type'] = $sign_give_point == 0 && sys_config('member_func_status', 1) == 1 && $sign_exp > 0 ? 2 : 1;
|
||||
$signList[$key]['point'] = $sign_give_point;
|
||||
}
|
||||
|
||||
//格式化签到数据
|
||||
$signList = array_chunk($signList, 7);
|
||||
|
||||
//签到功能是否关闭
|
||||
$signStatus = (int)sys_config('sign_status', 0);
|
||||
|
||||
return compact('signList', 'nextContinuousSignRewardList', 'checkSign', 'signStatus', 'sign_give_point');
|
||||
}
|
||||
}
|
||||
209
app/services/user/UserSpreadServices.php
Normal file
209
app/services/user/UserSpreadServices.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserSpreadDao;
|
||||
use app\services\order\store\BranchOrderServices;
|
||||
use app\services\user\level\SystemUserLevelServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class UserSpreadServices
|
||||
* @package app\services\user
|
||||
* @mixin UserSpreadDao
|
||||
*/
|
||||
class UserSpreadServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserSpreadDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserSpreadDao $dao;
|
||||
|
||||
/**
|
||||
* 记录推广关系
|
||||
* @param int $uid
|
||||
* @param int $spread_uid
|
||||
* @param int $spread_time
|
||||
* @param int $admin_id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function setSpread(int $uid, int $spread_uid, int $spread_time = 0, int $admin_id = 0)
|
||||
{
|
||||
if (!$uid || !$spread_uid) return false;
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if (!$userServices->userExist($uid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$userServices->userExist($spread_uid)) {
|
||||
return false;
|
||||
}
|
||||
$data = ['uid' => $uid, 'spread_uid' => $spread_uid, 'spread_time' => $spread_time ?: time(), 'admin_id' => $admin_id];
|
||||
if ($this->dao->save($data)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询推广用户uids
|
||||
* @param int $uid
|
||||
* @param int $type 1:一级2:二级 0:所有
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSpreadUids(int $uid, int $type = 0, array $where = [])
|
||||
{
|
||||
if (!$uid) return [];
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if (!$userServices->userExist($uid)) {
|
||||
return [];
|
||||
}
|
||||
if ($where && isset($where['time'])) {
|
||||
$where['timeKey'] = 'spread_time';
|
||||
}
|
||||
$where['spread_uid'] = $uid;
|
||||
$spread_one = $this->dao->getSpreadUids($where);
|
||||
if ($type == 1) {
|
||||
return $spread_one;
|
||||
}
|
||||
$where['spread_uid'] = $spread_one;
|
||||
$spread_two = $this->dao->getSpreadUids($where);
|
||||
if ($type == 2) {
|
||||
return $spread_two;
|
||||
}
|
||||
return array_unique(array_merge($spread_one, $spread_two));
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店推广统计详情列表
|
||||
* @param int $store_id
|
||||
* @param int $staff_id
|
||||
* @param array $time
|
||||
* @return array|array[]
|
||||
*/
|
||||
public function time(int $store_id, int $staff_id, array $time = [])
|
||||
{
|
||||
if (!$time) {
|
||||
return [[], []];
|
||||
}
|
||||
[$start, $stop, $front, $front_stop] = $time;
|
||||
$where = ['store_id' => $store_id];
|
||||
if ($staff_id) {
|
||||
$where['staff_id'] = $staff_id;
|
||||
}
|
||||
$frontPrice = $this->dao->count($where + ['time' => [$front, $front_stop], 'timeKey' => 'spread_time']);
|
||||
$nowPrice = $this->dao->count($where + ['time' => [$start, $stop], 'timeKey' => 'spread_time']);
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where + ['time' => [$start, $stop], 'timeKey' => 'spread_time'], '*', ['user'], $page, $limit);
|
||||
/** @var BranchOrderServices $order */
|
||||
$order = app()->make(BranchOrderServices::class);
|
||||
$order_where = ['time' => $time, 'is_del' => 0, 'is_system_del' => 0, 'paid' => 1, 'pid' => 0, 'refund_status' => [0, 3]];
|
||||
foreach ($list as &$item) {
|
||||
$item['spread_time'] = $item['spread_time'] ? date('Y-m-d H:i:s', $item['spread_time']) : '';
|
||||
$orderCount = $order->column($order_where + ['uid' => $item['uid']], 'count(`id`) as count,sum(`pay_price`) as price');
|
||||
$item['order_count'] = $orderCount[0]['count'] ?? 0;
|
||||
$item['order_price'] = $orderCount[0]['price'] ?? 0.00;
|
||||
}
|
||||
return [[$nowPrice, $frontPrice], $list];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推广列表
|
||||
* @param int $uid
|
||||
* @param UserServices $userServices
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSpreadList(array $where, string $field = '*', array $with = ['user'], bool $type = true)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $field, $with, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
/** @var BranchOrderServices $order */
|
||||
$order = app()->make(BranchOrderServices::class);
|
||||
foreach ($list as &$item) {
|
||||
$item['spread_time'] = $item['spread_time'] ? date('Y-m-d H:i:s', $item['spread_time']) : '';
|
||||
$item['type'] = $item['admin_id'] ? ('手动变更(' . ($item['real_name'] ?? '') . ')') : '自动变更';
|
||||
if ($type) {
|
||||
$orderCount = $order->column(['uid' => $item['uid'], 'is_del' => 0, 'is_system_del' => 0, 'paid' => 1, 'pid' => 0, 'refund_status' => [0, 3]], 'count(`id`) as count,sum(`pay_price`) as price');
|
||||
$item['order_count'] = $orderCount[0]['count'] ?? 0;
|
||||
$item['order_price'] = $orderCount[0]['price'] ?? 0.00;
|
||||
}
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友uids 我推广的 推广我的
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function getFriendUids(int $uid)
|
||||
{
|
||||
$result = [];
|
||||
if ($uid) {
|
||||
$spread = $this->dao->getColumn(['spread_uid' => $uid], 'uid');
|
||||
$sup_spread = $this->dao->getColumn(['uid' => $uid], 'spread_uid');
|
||||
$result = array_unique(array_merge($spread, $sup_spread));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友
|
||||
* @param int $id
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getFriendList(int $uid, string $field = 'uid,nickname,level,add_time')
|
||||
{
|
||||
$uids = $this->getFriendUids($uid);
|
||||
$list = [];
|
||||
$count = 0;
|
||||
if ($uids) {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$list = $userServices->getList(['uid' => $uids], $field, $page, $limit);
|
||||
/** @var SystemUserLevelServices $systemLevelServices */
|
||||
$systemLevelServices = app()->make(SystemUserLevelServices::class);
|
||||
$systemLevelList = $systemLevelServices->getWhereLevelList([], 'id,name');
|
||||
if ($systemLevelList) $systemLevelServices = array_combine(array_column($systemLevelList, 'id'), $systemLevelList);
|
||||
foreach ($list as &$item) {
|
||||
$item['type'] = $systemLevelServices[$item['level']]['name'] ?? '暂无';
|
||||
$item['add_time'] = $item['add_time'] && is_numeric($item['add_time']) ? date('Y-m-d H:i:s', $item['add_time']) : '';
|
||||
}
|
||||
$count = $this->dao->count(['spread_uid' => $uid]);
|
||||
}
|
||||
|
||||
return compact('list', 'count');
|
||||
}
|
||||
}
|
||||
70
app/services/user/UserStoreOrderServices.php
Normal file
70
app/services/user/UserStoreOrderServices.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserStoreOrderDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserStoreOrderServices
|
||||
* @package app\services\user
|
||||
* @mixin UserStoreOrderDao
|
||||
*/
|
||||
class UserStoreOrderServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserStoreOrderDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserStoreOrderDao $dao;
|
||||
|
||||
/**
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2023/9/18
|
||||
* @param $uid
|
||||
* @param string $orderBy
|
||||
* @param string $keyword
|
||||
* @param array $time
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserSpreadCountList($uid, $orderBy = '', $keyword = '', $time = [])
|
||||
{
|
||||
if ($orderBy === '') {
|
||||
$orderBy = 'u.add_time desc';
|
||||
}
|
||||
$where = [];
|
||||
$where[] = ['u.uid', 'IN', $uid];
|
||||
if (strlen(trim($keyword))) {
|
||||
$where[] = ['u.nickname|u.phone', 'LIKE', "%$keyword%"];
|
||||
}
|
||||
if ($time[0] || $time[1]) {
|
||||
$where[] = ['spread_time', 'between', $time];
|
||||
}
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$field = "u.uid,u.nickname,u.avatar,from_unixtime(u.add_time,'%Y/%m/%d') as time,u.spread_time,u.spread_count as childCount,p.orderCount,p.numberCount";
|
||||
$list = $this->dao->getUserSpreadCountList($where, $field, $orderBy, $page, $limit);
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
foreach ($list as &$item) {
|
||||
$item['childCount'] = count($userServices->getUserSpredadUids($item['uid'], 1)) ?? 0;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
53
app/services/user/UserUserBrokerageServices.php
Normal file
53
app/services/user/UserUserBrokerageServices.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserUserBrokerageDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 用户关联佣金
|
||||
* Class UserUserBrokerageServices
|
||||
* @package app\services\user
|
||||
* @mixin UserUserBrokerageDao
|
||||
*/
|
||||
class UserUserBrokerageServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserUserBrokerageDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserUserBrokerageDao $dao;
|
||||
|
||||
/**
|
||||
* 获取佣金列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getBrokerageList(array $where, string $field = '*', string $order = '', int $limit = 0)
|
||||
{
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$list = $this->dao->getList($where, $field, $order, $page, $limit);
|
||||
$count = $this->dao->getCount($where);
|
||||
return [$count, $list];
|
||||
}
|
||||
}
|
||||
60
app/services/user/UserVisitServices.php
Normal file
60
app/services/user/UserVisitServices.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserVisitDao;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class UserVisitServices
|
||||
* @package app\services\user
|
||||
* @mixin UserVisitDao
|
||||
*/
|
||||
class UserVisitServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserVisitDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserVisitDao $dao;
|
||||
|
||||
/**
|
||||
* 登录后记录访问记录
|
||||
* @param array|object $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function loginSaveVisit($user)
|
||||
{
|
||||
try {
|
||||
$data = [
|
||||
'url' => '/pages/index/index',
|
||||
'uid' => $user['uid'] ?? 0,
|
||||
'ip' => request()->ip(),
|
||||
'add_time' => time(),
|
||||
'province' => $user['province'] ?? '',
|
||||
'channel_type' => $user['user_type'] ?? 'h5'
|
||||
];
|
||||
if (!$data['uid']) {
|
||||
return false;
|
||||
}
|
||||
return $this->dao->save($data);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('登录记录访问日志错误,错误原因:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
app/services/user/UserWechatuserServices.php
Normal file
61
app/services/user/UserWechatuserServices.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserWechatUserDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class UserWechatuserServices
|
||||
* @package app\services\user
|
||||
* @mixin UserWechatUserDao
|
||||
*/
|
||||
class UserWechatuserServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserWechatUserDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserWechatUserDao $dao;
|
||||
|
||||
/**
|
||||
* 自定义简单查询总数
|
||||
* @param array $where
|
||||
* @return int
|
||||
*/
|
||||
public function getCount(array $where): int
|
||||
{
|
||||
return $this->dao->getCount($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复杂条件搜索列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getWhereUserList(array $where, string $field): array
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$order_string = '';
|
||||
$order_arr = ['asc', 'desc'];
|
||||
if (isset($where['now_money']) && in_array($where['now_money'], $order_arr)) {
|
||||
$order_string = 'now_money ' . $where['now_money'];
|
||||
}
|
||||
$list = $this->dao->getListByModel($where, $field, $order_string, $page, $limit);
|
||||
$count = $this->dao->getCountByWhere($where);
|
||||
return [$list, $count];
|
||||
}
|
||||
}
|
||||
161
app/services/user/channel/ChannelMerchantIdentityServices.php
Normal file
161
app/services/user/channel/ChannelMerchantIdentityServices.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\channel;
|
||||
|
||||
use app\dao\user\channel\ChannelMerchantIdentityDao;
|
||||
use app\dao\user\UserBillDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 采购商身份服务
|
||||
* Class ChannelMerchantIdentityServices
|
||||
* @package app\services\user\channel
|
||||
* @mixin ChannelMerchantIdentityDao
|
||||
*/
|
||||
class ChannelMerchantIdentityServices extends BaseServices
|
||||
{
|
||||
/**
|
||||
* @var ChannelMerchantIdentityDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected ChannelMerchantIdentityDao $dao;
|
||||
|
||||
|
||||
/**
|
||||
* 获取采购商身份列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有采购商身份
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getAllIdentities(array $where = [])
|
||||
{
|
||||
$where['is_del'] = 0;
|
||||
return $this->dao->search($where,false)->column('name,id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加采购商身份
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function add(array $data)
|
||||
{
|
||||
if ($this->dao->isNameExist($data['name'])) {
|
||||
throw new AdminException('该身份名称已存在');
|
||||
}
|
||||
// if ($this->dao->isLevelExist($data['level'])) {
|
||||
// throw new AdminException('该等级已存在');
|
||||
// }
|
||||
$data['add_time'] = time();
|
||||
$res = $this->dao->save($data);
|
||||
return $res != false;;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑采购商身份
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function edit(int $id, array $data)
|
||||
{
|
||||
if ($this->dao->isNameExist($data['name'], $id)) {
|
||||
throw new AdminException('该身份名称已存在');
|
||||
}
|
||||
// if ($this->dao->isLevelExist($data['level'], $id)) {
|
||||
// throw new AdminException('该等级已存在');
|
||||
// }
|
||||
$res = $this->dao->update($id, $data);
|
||||
return $res != false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采购商身份
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(int $id)
|
||||
{
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取采购商身份表单
|
||||
* @param array $data
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function getForm(array $data = [])
|
||||
{
|
||||
$f = [];
|
||||
$f[] = Form::input('name', '身份名称:', $data['name'] ?? '')->required();
|
||||
$f[] = Form::number('discount', '享受折扣:', $data['discount'] ?? 100)->info('采购商采购商品的折扣(1-100)例:95折输入95')->min(0)->max(100)->precision(0)->required();
|
||||
$f[] = Form::radio('is_show', '是否显示:', $data['is_show'] ?? 1)->options([
|
||||
['label' => '显示', 'value' => 1],
|
||||
['label' => '隐藏', 'value' => 0],
|
||||
]);
|
||||
return $f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取创建数据表单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm(int $id = 0)
|
||||
{
|
||||
if ($id) {
|
||||
$info = $this->dao->get($id);
|
||||
$info = $info ? $info->toArray() : [];
|
||||
$action = Url::buildUrl('/channel/identity/' . $id)->build();
|
||||
$title = '编辑采购商身份';
|
||||
$method = 'PUT';
|
||||
} else {
|
||||
$info = [];
|
||||
$action = Url::buildUrl('/channel/identity')->build();
|
||||
$title = '添加采购商身份';
|
||||
$method = 'POST';
|
||||
}
|
||||
return create_form($title, $this->getForm($info), $action, $method);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置状态
|
||||
* @param int $id
|
||||
* @param int $status
|
||||
* @return \crmeb\basic\BaseModel
|
||||
* User: liusl
|
||||
* DateTime: 2025/3/27 上午9:59
|
||||
*/
|
||||
public function setStatus(int $id, int $status)
|
||||
{
|
||||
if (!$id) {
|
||||
return $this->fail('参数错误');
|
||||
}
|
||||
return $this->dao->update($id, ['is_show' => $status]);
|
||||
}
|
||||
}
|
||||
377
app/services/user/channel/ChannelMerchantServices.php
Normal file
377
app/services/user/channel/ChannelMerchantServices.php
Normal file
@@ -0,0 +1,377 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\channel;
|
||||
|
||||
use app\dao\user\channel\ChannelMerchantDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\StoreOrderServices;
|
||||
use app\services\user\UserServices;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use FormBuilder\Factory\Iview;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 采购商服务类
|
||||
* Class ChannelMerchantServices
|
||||
* @package app\services\user\channel
|
||||
* @mixin ChannelMerchantDao
|
||||
*/
|
||||
class ChannelMerchantServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ChannelMerchantDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected ChannelMerchantDao $dao;
|
||||
|
||||
/**
|
||||
* 获取采购商信息
|
||||
* @param int $id
|
||||
* @return array|\think\Response
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2025/5/10
|
||||
*/
|
||||
public function read(int $id)
|
||||
{
|
||||
$info = $this->dao->get($id);
|
||||
if (!$info) {
|
||||
return app('json')->fail('数据不存在');
|
||||
}
|
||||
$info = $info->toArray();
|
||||
$info['avatar'] = app()->make(UserServices::class)->getUserCacheInfo($info['uid'])['avatar'] ?? '';
|
||||
$orderData = app()->make(StoreOrderServices::class)->getOneData(['uid' => $info['uid'], 'channel' => 1, ['pid', '<=', 0], 'paid' => 1, 'is_del' => 0, 'is_system_del' => 0], 'COUNT(*) as order_count,SUM(pay_price) as order_price');
|
||||
$info['order_count'] = $orderData['order_count'] ?? 0;
|
||||
$info['order_price'] = $orderData['order_price'] ?? 0;
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取采购商列表
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getChannelList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getChannelList($where, $page, $limit);
|
||||
$userService = app()->make(UserServices::class);
|
||||
$identityService = app()->make(ChannelMerchantIdentityServices::class);
|
||||
$identityIds = array_column($list, 'channel_type');
|
||||
$identityList = $identityService->search(['id' => $identityIds, 'is_del' => 0])->column('name,discount', 'id');
|
||||
$userIds = array_column($list, 'uid');
|
||||
$userList = $userService->getColumn([['uid', 'in', $userIds]], 'uid,nickname,avatar,phone', 'uid');
|
||||
foreach ($list as &$item) {
|
||||
$item['identity_name'] = $identityList[$item['channel_type']]['name'] ?? '';
|
||||
$item['identity_discount'] = $identityList[$item['channel_type']]['discount'] ?? '';
|
||||
$item['user_nickname'] = $userList[$item['uid']]['nickname'] ?? '';
|
||||
$item['user_avatar'] = $userList[$item['uid']]['avatar'] ?? '';
|
||||
$item['user_phone'] = $userList[$item['uid']]['phone'] ?? '';
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存采购商数据
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveChannel(array $data)
|
||||
{
|
||||
$data['add_time'] = time();
|
||||
if ($this->dao->count(['uid' => $data['uid'], 'is_del' => 0])) {
|
||||
throw new ValidateException('该用户已经是采购商了,无需重复添加!');
|
||||
}
|
||||
$res = $this->dao->save($data);
|
||||
return $res && $this->updateUserChannelFlag($data['uid'], 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改采购商数据
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateChannel(int $id, array $data)
|
||||
{
|
||||
return $this->dao->update($id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核采购商
|
||||
* @param int $id
|
||||
* @param int $verifyStatus
|
||||
* @param string $reason
|
||||
* @param int $channelType
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function verifyChannel(int $id, int $verifyStatus, int $channelType = 0, string $reason = '')
|
||||
{
|
||||
$channel = $this->dao->getInfo($id);
|
||||
if (!$channel) {
|
||||
throw new ValidateException('采购商不存在');
|
||||
}
|
||||
if ($channel['verify_status'] == $verifyStatus) {
|
||||
throw new ValidateException('请勿重复审核');
|
||||
}
|
||||
|
||||
$updateData = [
|
||||
'verify_status' => $verifyStatus,
|
||||
'verify_time' => time(),
|
||||
];
|
||||
|
||||
// 如果是审核通过,需要更新采购商身份和状态
|
||||
if ($verifyStatus == 1) {
|
||||
$updateData['channel_type'] = $channelType;
|
||||
$updateData['status'] = 1; // 审核通过后自动开启
|
||||
}
|
||||
|
||||
// 如果有备注,更新备注
|
||||
if ($verifyStatus == 2) {
|
||||
$updateData['reject'] = $reason;
|
||||
}
|
||||
|
||||
$this->dao->update($id, $updateData);
|
||||
|
||||
// 审核通过后,更新用户表的采购商标识
|
||||
if ($verifyStatus == 1) {
|
||||
$this->updateUserChannelFlag($channel['uid'], 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户采购商标识
|
||||
* @param int $uid 用户ID
|
||||
* @param int $isChannel 采购商标识 0-否 1-是
|
||||
* @return bool
|
||||
*/
|
||||
public function updateUserChannelFlag(int $uid, int $isChannel)
|
||||
{
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userServices->update($uid, ['is_channel' => $isChannel]);
|
||||
$userServices->cacheTag()->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建审核表单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function createVerifyForm(int $id)
|
||||
{
|
||||
$channel = $this->dao->getInfo($id);
|
||||
if (!$channel) {
|
||||
throw new ValidateException('采购商不存在');
|
||||
}
|
||||
|
||||
$identityService = app()->make(ChannelMerchantIdentityServices::class);
|
||||
$identity = $identityService->getAllIdentities(['is_show' => 1]);
|
||||
$options = [];
|
||||
foreach ($identity as $v) {
|
||||
$options[] = [
|
||||
'label' => $v['name'],
|
||||
'value' => $v['id']
|
||||
];
|
||||
}
|
||||
// 创建表单
|
||||
$form = [];
|
||||
|
||||
// 基本信息展示(只读)
|
||||
$form[] = Form::hidden('id', $id);
|
||||
$form[] = Form::input('channel_name', '采购商名称:', $channel['channel_name'])->disabled(true);
|
||||
$form[] = Form::input('real_name', '联系人:', $channel['real_name'])->disabled(true);
|
||||
$form[] = Form::input('phone', '联系电话:', $channel['phone'])->disabled(true);
|
||||
|
||||
// 审核状态选择
|
||||
$form[] = Form::radio('verify_status', '审核结果:', 1)
|
||||
->options([
|
||||
['label' => '通过', 'value' => 1],
|
||||
['label' => '拒绝', 'value' => 2]
|
||||
])
|
||||
->control([
|
||||
[
|
||||
'value' => 1,
|
||||
'rule' => [
|
||||
Form::select('channel_type', '采购商身份:', $channel['channel_type'] ?: 1)->setOptions($options)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择采购商身份')->required())
|
||||
]
|
||||
],
|
||||
[
|
||||
'value' => 2,
|
||||
'rule' => [
|
||||
Form::textarea('reject', '拒绝原因:', '')
|
||||
->placeholder('请填写拒绝原因')
|
||||
->required('请填写拒绝原因')
|
||||
]
|
||||
]
|
||||
]);
|
||||
return create_form('采购商审核', $form, Url::buildUrl('/channel/merchant/verify'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改采购商状态
|
||||
* @param int $id
|
||||
* @param int $status
|
||||
* @return mixed
|
||||
*/
|
||||
public function setStatus(int $id, int $status)
|
||||
{
|
||||
if (!$this->dao->getInfo($id)) {
|
||||
throw new ValidateException('采购商不存在');
|
||||
}
|
||||
$this->updateUserChannelFlag($id, $status);
|
||||
return $this->dao->update($id, ['status' => $status]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采购商
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function deleteChannel(int $id)
|
||||
{
|
||||
if (!$info = $this->dao->getInfo($id)) {
|
||||
throw new ValidateException('采购商不存在');
|
||||
}
|
||||
$this->updateUserChannelFlag($info['uid'], 0);
|
||||
return $this->dao->update($id, ['is_del' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表单
|
||||
* @param array $formData
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm(array $formData = [])
|
||||
{
|
||||
$id = $formData['id'] ?? 0;
|
||||
$form = [];
|
||||
if (!$formData) {
|
||||
$form[] = Form::frameImage('image', '商城用户:', $this->url('admin/system.user/list', ['fodder' => 'image'], true))
|
||||
->icon('ios-add')->width('960px')->height('550px')->modal(['footer-hide' => true])->Props(['srcKey' => 'image']);
|
||||
$form[] = Form::hidden('uid', 0);
|
||||
}
|
||||
$form = $form + [
|
||||
Form::hidden('id', $id),
|
||||
Form::input('channel_name', '采购商名称:', $formData['channel_name'] ?? '')->required('请填写采购商名称'),
|
||||
Form::input('real_name', '联系人:', $formData['real_name'] ?? '')->required('请填写联系人'),
|
||||
Form::input('phone', '联系电话:', $formData['phone'] ?? '')->required('请填写联系电话'),
|
||||
Form::cityArea('province', '所在地区:', $formData['province'] ?? '')->type('city_area')->info('请选择省市区')->required('请选择地区'),
|
||||
Form::input('address', '详细地址:', $formData['address'] ?? '')->required('请填写详细地址'),
|
||||
Form::radio('channel_type', '采购商身份:', $formData['channel_type'] ?? 1)->options([
|
||||
['label' => '省级', 'value' => 1],
|
||||
['label' => '市级', 'value' => 2],
|
||||
['label' => '区级', 'value' => 3],
|
||||
]),
|
||||
Form::frameImages('certificate', '资质照片:', url('admin/widget.images/index', ['fodder' => 'certificate']), $formData['certificate'] ?? [])->maxLength(5),
|
||||
Form::radio('status', '状态', $formData['status'] ?? 1)->options([
|
||||
['label' => '开启', 'value' => 1],
|
||||
['label' => '关闭', 'value' => 0],
|
||||
]),
|
||||
Form::textarea('admin_remark', '备注信息:', $formData['remark'] ?? ''),
|
||||
];
|
||||
return create_form($id ? '编辑采购商' : '添加采购商', $form, Url::buildUrl('/channel/merchant/save'), 'POST');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 申请成为采购商
|
||||
* @param array $data
|
||||
* @param array $userInfo
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function apply(array $data, int $id = 0)
|
||||
{
|
||||
|
||||
// 检查是否有正在审核的申请
|
||||
$existApply = $this->dao->getChannelInfo(['uid' => $data['uid'], 'verify_status' => 0]);
|
||||
if ($existApply) {
|
||||
throw new ValidateException('您有正在审核的申请,请耐心等待');
|
||||
}
|
||||
$data['province_ids'] = is_array($data['province_ids']) ? implode(',', $data['province_ids']) : '';
|
||||
$channelData = [
|
||||
'uid' => $data['uid'],
|
||||
'channel_name' => $data['channel_name'] ?? '',
|
||||
'real_name' => $data['real_name'],
|
||||
'phone' => $data['phone'],
|
||||
'province' => $data['province'] ?? '',
|
||||
'province_ids' => $data['province_ids'],
|
||||
'address' => $data['address'] ?? '',
|
||||
'certificate' => $data['certificate'] ?? '',
|
||||
'remark' => $data['remark'] ?? '',
|
||||
'verify_status' => 0,
|
||||
'status' => 0,
|
||||
];
|
||||
if ($id) {
|
||||
$result = $this->dao->update($id, $channelData);
|
||||
} else {
|
||||
$channelData['add_time'] = time();
|
||||
$result = $this->dao->save($channelData);
|
||||
}
|
||||
if (!$result) {
|
||||
throw new ValidateException('申请提交失败');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否采购商
|
||||
* @param $uid
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* User: liusl
|
||||
* DateTime: 2025/4/8 下午3:07
|
||||
*/
|
||||
public function isChannel(int $uid, bool $is_discount = false)
|
||||
{
|
||||
if (!$uid) {
|
||||
return false;
|
||||
}
|
||||
$info = $this->dao->getChannelInfo(['uid' => $uid, 'status' => 1, 'is_del' => 0]);
|
||||
if (!$info) {
|
||||
return false;
|
||||
}
|
||||
if ($is_discount) {
|
||||
$iden_info = app()->make(ChannelMerchantIdentityServices::class)->search(['id' => $info['channel_type']])->find();
|
||||
$discount = $iden_info['discount'] ?? 100;
|
||||
$discount = bcmul($discount, 0.01, 2);
|
||||
$iden_name = $iden_info['name'] ?? '';
|
||||
$channel_type = $info['channel_type'];
|
||||
return compact('iden_name', 'discount', 'channel_type');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
154
app/services/user/group/UserGroupServices.php
Normal file
154
app/services/user/group/UserGroupServices.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\group;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\group\UserGroupDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use think\annotation\Inject;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 用户分组
|
||||
* Class UserGroupServices
|
||||
* @package app\services\user\group
|
||||
* @mixin UserGroupDao
|
||||
*/
|
||||
class UserGroupServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserGroupDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserGroupDao $dao;
|
||||
|
||||
/**
|
||||
* 获取某一个分组
|
||||
* @param int $id
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getGroup(int $id)
|
||||
{
|
||||
return $this->dao->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分组列表
|
||||
* @param string $field
|
||||
* @param bool $is_page
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getGroupList(string $field = 'id,group_name', bool $is_page = false)
|
||||
{
|
||||
$page = $limit = 0;
|
||||
if ($is_page) {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$count = $this->dao->count([]);
|
||||
}
|
||||
$list = $this->dao->getList([], $field, $page, $limit);
|
||||
|
||||
return $is_page ? compact('list', 'count') : $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一些用户的分组名称
|
||||
* @param array $ids
|
||||
* @return array
|
||||
*/
|
||||
public function getUsersGroupName(array $ids)
|
||||
{
|
||||
return $this->dao->getColumn([['id', 'IN', $ids]], 'group_name', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加/修改分组页面
|
||||
* @param int $id
|
||||
* @return string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function add(int $id)
|
||||
{
|
||||
$group = $this->getGroup($id);
|
||||
$field = array();
|
||||
if (!$group) {
|
||||
$title = '添加分组';
|
||||
$field[] = Form::input('group_name', '分组名称:', '')->maxlength(20)->required();
|
||||
} else {
|
||||
$title = '修改分组';
|
||||
$field[] = Form::hidden('id', $id);
|
||||
$field[] = Form::input('group_name', '分组名称:', $group->getData('group_name'))->maxlength(20)->required();
|
||||
}
|
||||
return create_form($title, $field, Url::buildUrl('/user/user_group/save'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加|修改
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
$groupName = $this->dao->getOne(['group_name' => $data['group_name']]);
|
||||
if ($id) {
|
||||
if (!$this->getGroup($id)) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
if ($groupName && $id != $groupName['id']) {
|
||||
throw new AdminException('该分组已经存在');
|
||||
}
|
||||
if ($this->dao->update($id, $data)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('修改失败或者您没有修改什么!');
|
||||
}
|
||||
} else {
|
||||
unset($data['id']);
|
||||
if ($groupName) {
|
||||
throw new AdminException('该分组已经存在');
|
||||
}
|
||||
if ($this->dao->save($data)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('添加失败!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param int $id
|
||||
*/
|
||||
public function delGroup(int $id)
|
||||
{
|
||||
if ($this->getGroup($id)) {
|
||||
if (!$this->dao->delete($id)) {
|
||||
throw new AdminException('删除失败,请稍候再试!');
|
||||
}
|
||||
}
|
||||
return '删除成功!';
|
||||
}
|
||||
}
|
||||
263
app/services/user/label/UserLabelBatchProcessServices.php
Normal file
263
app/services/user/label/UserLabelBatchProcessServices.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\services\user\UserServices;
|
||||
use app\jobs\user\UserAutoLabelJob;
|
||||
use think\facade\Log;
|
||||
use crmeb\traits\ServicesTrait;
|
||||
|
||||
/**
|
||||
* 用户标签批量处理服务
|
||||
* Class UserLabelBatchProcessServices
|
||||
* @package app\services\user\label
|
||||
*/
|
||||
class UserLabelBatchProcessServices extends BaseServices
|
||||
{
|
||||
use ServicesTrait;
|
||||
|
||||
/**
|
||||
* 批量大小
|
||||
*/
|
||||
const BATCH_SIZE = 1000;
|
||||
|
||||
/**
|
||||
* 处理标签变更后的用户批量检查
|
||||
* @param array $labelIds 标签ID数组
|
||||
* @param string $action 操作类型:create(新建) 或 update(修改)
|
||||
* @return bool
|
||||
*/
|
||||
public function processLabelChange(array $labelIds, string $action = 'update')
|
||||
{
|
||||
try {
|
||||
Log::info('开始处理标签变更批量用户检查:' . var_export([
|
||||
'label_ids' => $labelIds,
|
||||
'action' => $action
|
||||
], true));
|
||||
|
||||
// 获取所有用户ID
|
||||
$userIds = $this->getAllUserIds();
|
||||
|
||||
if (empty($userIds)) {
|
||||
Log::info('没有找到用户,跳过处理');
|
||||
return true;
|
||||
}
|
||||
|
||||
// 初始化处理状态缓存
|
||||
$cacheKey = "label_batch_process_" . implode('_', $labelIds);
|
||||
$statusData = [
|
||||
'label_ids' => $labelIds,
|
||||
'status' => 'processing',
|
||||
'processed_count' => 0,
|
||||
'total_count' => count($userIds),
|
||||
'start_time' => date('Y-m-d H:i:s'),
|
||||
'end_time' => null,
|
||||
'message' => '正在处理中...'
|
||||
];
|
||||
cache($cacheKey, $statusData, 3600); // 缓存1小时
|
||||
|
||||
// 分批处理用户
|
||||
$batches = array_chunk($userIds, self::BATCH_SIZE);
|
||||
$totalBatches = count($batches);
|
||||
|
||||
Log::info('开始分批处理用户:' . var_export([
|
||||
'total_users' => count($userIds),
|
||||
'batch_size' => self::BATCH_SIZE,
|
||||
'total_batches' => $totalBatches
|
||||
], true));
|
||||
|
||||
$processedCount = 0;
|
||||
foreach ($batches as $index => $batchUserIds) {
|
||||
$this->processBatchUsers($batchUserIds, $labelIds, $action, $index + 1, $totalBatches);
|
||||
|
||||
$processedCount += count($batchUserIds);
|
||||
|
||||
// 更新处理状态
|
||||
$statusData['processed_count'] = $processedCount;
|
||||
$statusData['message'] = "已处理 {$processedCount}/{$statusData['total_count']} 个用户";
|
||||
cache($cacheKey, $statusData, 3600);
|
||||
}
|
||||
|
||||
// 更新最终状态
|
||||
$statusData['status'] = 'completed';
|
||||
$statusData['end_time'] = date('Y-m-d H:i:s');
|
||||
$statusData['message'] = '处理完成';
|
||||
cache($cacheKey, $statusData, 3600);
|
||||
|
||||
Log::info('标签变更批量用户检查处理完成:' . var_export([
|
||||
'label_ids' => $labelIds,
|
||||
'total_users' => count($userIds)
|
||||
], true));
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
// 更新错误状态
|
||||
$cacheKey = "label_batch_process_" . implode('_', $labelIds);
|
||||
$errorStatus = [
|
||||
'label_ids' => $labelIds,
|
||||
'status' => 'error',
|
||||
'processed_count' => 0,
|
||||
'total_count' => 0,
|
||||
'start_time' => date('Y-m-d H:i:s'),
|
||||
'end_time' => date('Y-m-d H:i:s'),
|
||||
'message' => '处理失败:' . $e->getMessage()
|
||||
];
|
||||
cache($cacheKey, $errorStatus, 3600);
|
||||
|
||||
Log::error('标签变更批量用户检查处理失败:' . var_export([
|
||||
'label_ids' => $labelIds,
|
||||
'action' => $action,
|
||||
'error' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine()
|
||||
], true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有用户ID
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllUserIds(): array
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
|
||||
// 获取所有启用的用户ID
|
||||
$where = [
|
||||
'status' => 1, // 启用状态
|
||||
'is_del' => 0 // 未删除
|
||||
];
|
||||
|
||||
// 分批获取用户ID,避免内存溢出
|
||||
$userIds = [];
|
||||
$page = 1;
|
||||
$limit = 5000; // 每次获取5000个用户ID
|
||||
|
||||
do {
|
||||
$users = $userServices->getList($where, 'uid', $page, $limit);
|
||||
$batchIds = array_column($users, 'uid');
|
||||
$userIds = array_merge($userIds, $batchIds);
|
||||
$page++;
|
||||
} while (count($batchIds) === $limit);
|
||||
|
||||
return array_unique($userIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理批次用户
|
||||
* @param array $userIds 用户ID数组
|
||||
* @param array $labelIds 标签ID数组
|
||||
* @param string $action 操作类型
|
||||
* @param int $batchIndex 当前批次索引
|
||||
* @param int $totalBatches 总批次数
|
||||
*/
|
||||
protected function processBatchUsers(array $userIds, array $labelIds, string $action, int $batchIndex, int $totalBatches)
|
||||
{
|
||||
try {
|
||||
Log::info('处理用户批次:' . var_export([
|
||||
'batch_index' => $batchIndex,
|
||||
'total_batches' => $totalBatches,
|
||||
'user_ids' => $userIds,
|
||||
'user_count' => count($userIds),
|
||||
'label_ids' => $labelIds
|
||||
], true));
|
||||
|
||||
// 批量分发自动标签检查任务,每100个用户一个任务
|
||||
$batchSize = 100;
|
||||
$userBatches = array_chunk($userIds, $batchSize);
|
||||
|
||||
foreach ($userBatches as $userBatch) {
|
||||
// 分发批量处理任务,传入用户数组而不是单个用户
|
||||
|
||||
UserAutoLabelJob::dispatch([
|
||||
$userBatch,
|
||||
'label_change', // 触发类型:标签变更
|
||||
[
|
||||
'action' => $action,
|
||||
'changed_labels' => $labelIds,
|
||||
'timestamp' => time()
|
||||
],
|
||||
$labelIds // 只检查变更的标签
|
||||
]);
|
||||
}
|
||||
|
||||
Log::info('批次用户处理完成:' . var_export([
|
||||
'batch_index' => $batchIndex,
|
||||
'user_batches' => count($userBatches),
|
||||
'dispatched_jobs' => count($userBatches),
|
||||
'total_users' => count($userIds)
|
||||
], true));
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('处理用户批次失败:' . var_export([
|
||||
'batch_index' => $batchIndex,
|
||||
'user_count' => count($userIds),
|
||||
'error' => $e->getMessage()
|
||||
], true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个标签的用户检查
|
||||
* @param int $labelId 标签ID
|
||||
* @param string $action 操作类型
|
||||
* @return bool
|
||||
*/
|
||||
public function processSingleLabel(int $labelId, string $action = 'update')
|
||||
{
|
||||
return $this->processLabelChange([$labelId], $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取批量处理状态
|
||||
* @param int $labelId
|
||||
* @return array
|
||||
*/
|
||||
public function getBatchProcessStatus(int $labelId): array
|
||||
{
|
||||
try {
|
||||
// 从缓存中获取处理状态
|
||||
$cacheKey = "label_batch_process_{$labelId}";
|
||||
$status = cache($cacheKey);
|
||||
|
||||
if (!$status) {
|
||||
return [
|
||||
'label_id' => $labelId,
|
||||
'status' => 'not_started',
|
||||
'processed_count' => 0,
|
||||
'total_count' => 0,
|
||||
'start_time' => null,
|
||||
'end_time' => null,
|
||||
'message' => '未找到处理记录'
|
||||
];
|
||||
}
|
||||
|
||||
return $status;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('获取批量处理状态失败:' . var_export([
|
||||
'label_id' => $labelId,
|
||||
'error' => $e->getMessage()
|
||||
], true));
|
||||
|
||||
return [
|
||||
'label_id' => $labelId,
|
||||
'status' => 'error',
|
||||
'processed_count' => 0,
|
||||
'total_count' => 0,
|
||||
'start_time' => null,
|
||||
'end_time' => null,
|
||||
'message' => '获取状态失败:' . $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
175
app/services/user/label/UserLabelCateServices.php
Normal file
175
app/services/user/label/UserLabelCateServices.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
|
||||
use app\dao\other\CategoryDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\services\CacheService;
|
||||
use crmeb\services\FormBuilder;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 用户标签分类
|
||||
* Class UserLabelCateServices
|
||||
* @package app\services\user\label
|
||||
* @mixin CategoryDao
|
||||
*/
|
||||
class UserLabelCateServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* 标签分类缓存
|
||||
* @var string
|
||||
*/
|
||||
protected string $cacheName = 'label_list_all';
|
||||
|
||||
/**
|
||||
* @var CategoryDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected CategoryDao $dao;
|
||||
|
||||
/**
|
||||
* 获取标签分类
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLabelList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getCateList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取tree数据
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @param array $with
|
||||
* @return array
|
||||
*/
|
||||
public function getLabelTree(array $where, array $field = ['*'], array $with = [])
|
||||
{
|
||||
return $this->dao->getCateList($where, 0, 0, $field, $with);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类缓存
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return bool
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
*/
|
||||
public function deleteCateCache(int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$key = $this->cacheName . '_' . $type . '_' . $relation_id;
|
||||
return CacheService::delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签全部分类
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return bool|mixed|null
|
||||
*/
|
||||
public function getLabelCateAll(int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$key = $this->cacheName . '_' . $type . '_' . $relation_id;
|
||||
return CacheService::get($key, function () use ($type, $relation_id) {
|
||||
return $this->dao->getCateList(['type' => $type, 'owner_id' => 0, 'relation_id' => $relation_id, 'group' => 0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 标签分类表单
|
||||
* @param array $cataData
|
||||
* @return mixed
|
||||
*/
|
||||
public function labelCateForm(array $cataData = [])
|
||||
{
|
||||
$f[] = FormBuilder::input('name', '分类名称:', $cataData['name'] ?? '')->maxlength(20)->required();
|
||||
$f[] = FormBuilder::number('sort', '排序:', (int)($cataData['sort'] ?? 0))->min(0);
|
||||
return $f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建表单
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function createForm()
|
||||
{
|
||||
return create_form('添加标签分类', $this->labelCateForm(), $this->url('/user/user_label_cate'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分类标签表单
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function updateForm(int $id)
|
||||
{
|
||||
$labelCate = $this->dao->get($id);
|
||||
if (!$labelCate) {
|
||||
throw new ValidateException('分类标签没有查到');
|
||||
}
|
||||
return create_form('编辑标签分类', $this->labelCateForm($labelCate->toArray()), $this->url('user/user_label_cate/' . $id), 'PUT');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户标签列表
|
||||
* @param int $uid
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserLabel(int $uid = 0, int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$list = $this->dao->getAll(['group' => 0, 'type' => $type, 'relation_id' => $relation_id], ['label']);
|
||||
$labelIds = [];
|
||||
if ($uid) {
|
||||
/** @var UserLabelRelationServices $services */
|
||||
$services = app()->make(UserLabelRelationServices::class);
|
||||
$labelIds = $services->getUserLabels($uid, $type, $relation_id);
|
||||
}
|
||||
foreach ($list as $key => &$item) {
|
||||
if (is_array($item['label'])) {
|
||||
if (!$item['label']) {
|
||||
unset($list[$key]);
|
||||
continue;
|
||||
}
|
||||
foreach ($item['label'] as &$value) {
|
||||
if (in_array($value['id'], $labelIds)) {
|
||||
$value['disabled'] = true;
|
||||
} else {
|
||||
$value['disabled'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return array_merge($list);
|
||||
}
|
||||
}
|
||||
250
app/services/user/label/UserLabelExtendRelationServices.php
Normal file
250
app/services/user/label/UserLabelExtendRelationServices.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\label\UserLabelExtendRelationDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use FormBuilder\Factory\Iview;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 标签规则扩展表
|
||||
* Class UserLabelExtendRelationServices
|
||||
* @package app\services\user\label
|
||||
* @mixin UserLabelExtendRelationDao
|
||||
*/
|
||||
class UserLabelExtendRelationServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserLabelExtendRelationDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserLabelExtendRelationDao $dao;
|
||||
|
||||
/**
|
||||
* 获取某一条标签扩展关联关系
|
||||
* @param $id
|
||||
* @return array|\think\Model|null
|
||||
*/
|
||||
public function getLabelExtendRelation($id)
|
||||
{
|
||||
return $this->dao->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有标签扩展关联关系
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLabelExtendRelationList(array $where = [], array $field = ['*'])
|
||||
{
|
||||
return $this->dao->getList(0, 0, $where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($page, $limit, $where);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据左侧ID获取关联关系
|
||||
* @param int $leftId
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getByLeftId(int $leftId, int $type = 0): array
|
||||
{
|
||||
return $this->dao->getByLeftId($leftId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据右侧ID获取关联关系
|
||||
* @param int $rightId
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getByRightId(int $rightId, int $type = 0): array
|
||||
{
|
||||
return $this->dao->getByRightId($rightId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型获取关联关系
|
||||
* @param int $type
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getByType(int $type, array $where = []): array
|
||||
{
|
||||
return $this->dao->getByType($type, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加修改标签扩展关联关系表单
|
||||
* @param int $id
|
||||
* @param int $leftId
|
||||
* @return mixed
|
||||
*/
|
||||
public function add(int $id, int $leftId = 0)
|
||||
{
|
||||
$labelExtendRelation = $this->getLabelExtendRelation($id);
|
||||
$field = array();
|
||||
|
||||
// 类型选项
|
||||
$typeOptions = [
|
||||
['value' => 1, 'label' => '商品'],
|
||||
['value' => 2, 'label' => '分类'],
|
||||
['value' => 3, 'label' => '标签']
|
||||
];
|
||||
|
||||
/** @var UserLabelExtendServices $labelExtendService */
|
||||
$labelExtendService = app()->make(UserLabelExtendServices::class);
|
||||
$labelExtendOptions = [];
|
||||
foreach ($labelExtendService->getLabelExtendList() as $item) {
|
||||
$labelExtendOptions[] = ['value' => $item['id'], 'label' => '标签扩展规则-' . $item['id']];
|
||||
}
|
||||
|
||||
if (!$labelExtendRelation) {
|
||||
$title = '添加标签扩展关联关系';
|
||||
$field[] = Form::select('left_id', '关联标签扩展', $leftId)->setOptions($labelExtendOptions)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择关联标签扩展')->required());
|
||||
} else {
|
||||
$title = '编辑标签扩展关联关系';
|
||||
$field[] = Form::select('left_id', '关联标签扩展', $labelExtendRelation['left_id'])->setOptions($labelExtendOptions)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择关联标签扩展')->required());
|
||||
}
|
||||
|
||||
$field[] = Form::select('type', '类型', $labelExtendRelation['type'] ?? 0)->setOptions($typeOptions)->appendValidate(Iview::validateInt()->message('请选择类型')->required());
|
||||
$field[] = Form::number('right_id', '关联ID', $labelExtendRelation['right_id'] ?? 0)->appendValidate(Iview::validateInt()->message('请输入关联ID')->required());
|
||||
|
||||
return create_form($title, $field, '/admin/user/label_extend_relation/save/' . $id, 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存标签扩展关联关系
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
if ($id) {
|
||||
$res = $this->dao->update($id, $data);
|
||||
if (!$res) throw new AdminException('修改失败');
|
||||
} else {
|
||||
$res = $this->dao->save($data);
|
||||
if (!$res) throw new AdminException('添加失败');
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签扩展关联关系
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function del(int $id)
|
||||
{
|
||||
$labelExtendRelation = $this->getLabelExtendRelation($id);
|
||||
if (!$labelExtendRelation) {
|
||||
throw new AdminException('标签扩展关联关系不存在');
|
||||
}
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存关联关系
|
||||
* @param int $leftId
|
||||
* @param int $type
|
||||
* @param array $rightIds
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function saveBatch(int $leftId, int $type, array $rightIds): bool
|
||||
{
|
||||
// 先删除原有关联关系
|
||||
$this->dao->deleteByLeftId($leftId, $type);
|
||||
|
||||
// 批量保存新的关联关系
|
||||
if (!empty($rightIds)) {
|
||||
$data = [];
|
||||
foreach ($rightIds as $rightId) {
|
||||
$data[] = [
|
||||
'type' => $type,
|
||||
'left_id' => $leftId,
|
||||
'right_id' => $rightId
|
||||
];
|
||||
}
|
||||
return $this->dao->saveAll($data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联的右侧ID列表
|
||||
* @param int $leftId
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getRightIds(int $leftId, int $type = 0): array
|
||||
{
|
||||
$list = $this->getByLeftId($leftId, $type);
|
||||
return array_column($list, 'right_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联的左侧ID列表
|
||||
* @param int $rightId
|
||||
* @param int $type
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLeftIds(int $rightId, int $type = 0): array
|
||||
{
|
||||
$list = $this->getByRightId($rightId, $type);
|
||||
return array_column($list, 'left_id');
|
||||
}
|
||||
}
|
||||
242
app/services/user/label/UserLabelExtendServices.php
Normal file
242
app/services/user/label/UserLabelExtendServices.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\label\UserLabelExtendDao;
|
||||
use app\services\product\category\StoreProductCategoryServices;
|
||||
use app\services\product\label\StoreProductLabelServices;
|
||||
use app\services\product\product\StoreProductServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use FormBuilder\Factory\Iview;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* 标签规则关联表
|
||||
* Class UserLabelExtendServices
|
||||
* @package app\services\user\label
|
||||
* @mixin UserLabelExtendDao
|
||||
*/
|
||||
class UserLabelExtendServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserLabelExtendDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserLabelExtendDao $dao;
|
||||
|
||||
/**
|
||||
* 获取某一条标签扩展规则
|
||||
* @param $id
|
||||
* @return array|\think\Model|null
|
||||
*/
|
||||
public function getLabelExtend($id)
|
||||
{
|
||||
return $this->dao->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有标签扩展规则
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLabelExtendList(array $where = [], array $field = ['*'])
|
||||
{
|
||||
return $this->dao->getList(0, 0, $where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($page, $limit, $where);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据标签ID获取扩展规则
|
||||
* @param int $labelId
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getByLabelId(int $labelId): array
|
||||
{
|
||||
return $this->dao->getByLabelId($labelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据规则类型获取扩展规则
|
||||
* @param int $ruleType
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getByRuleType(int $ruleType, array $where = []): array
|
||||
{
|
||||
return $this->dao->getByRuleType($ruleType, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加修改标签扩展规则表单
|
||||
* @param int $id
|
||||
* @param int $labelId
|
||||
* @return mixed
|
||||
*/
|
||||
public function add(int $id, int $labelId = 0)
|
||||
{
|
||||
$labelExtend = $this->getLabelExtend($id);
|
||||
$field = array();
|
||||
|
||||
/** @var UserLabelServices $labelService */
|
||||
$labelService = app()->make(UserLabelServices::class);
|
||||
$labelOptions = [];
|
||||
foreach ($labelService->getLabelList() as $item) {
|
||||
$labelOptions[] = ['value' => $item['id'], 'label' => $item['label_name']];
|
||||
}
|
||||
|
||||
// 规则类型选项
|
||||
$ruleTypeOptions = [
|
||||
['value' => 1, 'label' => '商品'],
|
||||
['value' => 2, 'label' => '资产'],
|
||||
['value' => 3, 'label' => '交易'],
|
||||
['value' => 4, 'label' => '客户(所有)']
|
||||
];
|
||||
|
||||
// 规则子类型选项
|
||||
$subTypeOptions = [
|
||||
['value' => 1, 'label' => '积分'],
|
||||
['value' => 2, 'label' => '余额']
|
||||
];
|
||||
|
||||
// 余额类型选项
|
||||
$balanceTypeOptions = [
|
||||
['value' => 1, 'label' => '充值'],
|
||||
['value' => 2, 'label' => '消耗']
|
||||
];
|
||||
|
||||
// 次数/金额选项
|
||||
$operationTypeOptions = [
|
||||
['value' => 1, 'label' => '次数'],
|
||||
['value' => 2, 'label' => '金额']
|
||||
];
|
||||
|
||||
// 时间维度选项
|
||||
$timeDimensionOptions = [
|
||||
['value' => 1, 'label' => '历史'],
|
||||
['value' => 2, 'label' => '最近'],
|
||||
['value' => 3, 'label' => '累计']
|
||||
];
|
||||
|
||||
// 商品维度选项
|
||||
$specifyDimensionOptions = [
|
||||
['value' => 1, 'label' => '商品'],
|
||||
['value' => 2, 'label' => '分类'],
|
||||
['value' => 3, 'label' => '标签']
|
||||
];
|
||||
|
||||
// 客户身份选项
|
||||
$customerIdentityOptions = [
|
||||
['value' => 1, 'label' => '注册时间'],
|
||||
['value' => 2, 'label' => '访问时间'],
|
||||
['value' => 3, 'label' => '用户等级'],
|
||||
['value' => 4, 'label' => '客户身份']
|
||||
];
|
||||
|
||||
if (!$labelExtend) {
|
||||
$title = '添加标签扩展规则';
|
||||
$field[] = Form::select('label_id', '关联标签', $labelId)->setOptions($labelOptions)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择关联标签')->required());
|
||||
} else {
|
||||
$title = '编辑标签扩展规则';
|
||||
$field[] = Form::select('label_id', '关联标签', $labelExtend['label_id'])->setOptions($labelOptions)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择关联标签')->required());
|
||||
}
|
||||
|
||||
$field[] = Form::select('rule_type', '规则类型', $labelExtend['rule_type'] ?? 0)->setOptions($ruleTypeOptions)->appendValidate(Iview::validateInt()->message('请选择规则类型')->required());
|
||||
$field[] = Form::select('sub_type', '规则子类型', $labelExtend['sub_type'] ?? 0)->setOptions($subTypeOptions);
|
||||
$field[] = Form::select('balance_type', '余额类型', $labelExtend['balance_type'] ?? 0)->setOptions($balanceTypeOptions);
|
||||
$field[] = Form::select('operation_type', '次数/金额', $labelExtend['operation_type'] ?? 0)->setOptions($operationTypeOptions);
|
||||
$field[] = Form::select('time_dimension', '时间维度', $labelExtend['time_dimension'] ?? 0)->setOptions($timeDimensionOptions);
|
||||
$field[] = Form::number('time_value', '时间值(天)', $labelExtend['time_value'] ?? 0);
|
||||
$field[] = Form::select('specify_dimension', '商品维度', $labelExtend['specify_dimension'] ?? 0)->setOptions($specifyDimensionOptions);
|
||||
$field[] = Form::number('amount_value_min', '金额/数值最小', $labelExtend['amount_value_min'] ?? 0)->precision(2);
|
||||
$field[] = Form::number('amount_value_max', '金额/数值最大', $labelExtend['amount_value_max'] ?? 0)->precision(2);
|
||||
$field[] = Form::number('operation_times_min', '操作次数最小', $labelExtend['operation_times_min'] ?? 0);
|
||||
$field[] = Form::number('operation_times_max', '操作次数最大', $labelExtend['operation_times_max'] ?? 0);
|
||||
$field[] = Form::select('customer_identity', '客户身份', $labelExtend['customer_identity'] ?? 0)->setOptions($customerIdentityOptions);
|
||||
$field[] = Form::number('customer_num', '客户身份数据', $labelExtend['customer_num'] ?? 0);
|
||||
|
||||
return create_form($title, $field, '/admin/user/label_extend/save/' . $id, 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签扩展规则
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function del(int $id)
|
||||
{
|
||||
$labelExtend = $this->getLabelExtend($id);
|
||||
if (!$labelExtend) {
|
||||
throw new AdminException('标签扩展规则不存在');
|
||||
}
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据商品维度获取商品/分类/标签信息
|
||||
* @param int $id 标签扩展ID
|
||||
* @return array
|
||||
*/
|
||||
public function getLabelSpecify(int $id)
|
||||
{
|
||||
$labelExtend = $this->getLabelExtend($id);
|
||||
if (!$labelExtend) {
|
||||
return [];
|
||||
}
|
||||
$product_ids = $labelExtend['product_ids'] ? explode(',', $labelExtend['product_ids']) : [];
|
||||
$data = [];
|
||||
switch ($labelExtend['specify_dimension']) {
|
||||
case 1:
|
||||
//商品
|
||||
$data = app()->make(StoreProductServices::class)->search([])->whereIn('id', $product_ids)->column('id,store_name,image');
|
||||
break;
|
||||
case 2:
|
||||
//分类
|
||||
$data = app()->make(StoreProductCategoryServices::class)->search([])->whereIn('id', $product_ids)->column('id,cate_name');
|
||||
break;
|
||||
case 3:
|
||||
//标签
|
||||
$data = app()->make(StoreProductLabelServices::class)->search([])->whereIn('id', $product_ids)->column('id,label_name');
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
174
app/services/user/label/UserLabelRelationServices.php
Normal file
174
app/services/user/label/UserLabelRelationServices.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\label\UserLabelRelationDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 用户关联标签
|
||||
* Class UserLabelRelationServices
|
||||
* @package app\services\user\label
|
||||
* @mixin UserLabelRelationDao
|
||||
*/
|
||||
class UserLabelRelationServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserLabelRelationDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserLabelRelationDao $dao;
|
||||
|
||||
/**
|
||||
* 获取某个用户标签ids
|
||||
* @param int $uid
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return array
|
||||
*/
|
||||
public function getUserLabels(int $uid, int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
return $this->dao->getColumn(['uid' => $uid, 'type' => $type, 'relation_id' => $relation_id], 'label_id', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户设置标签
|
||||
* @param $uids
|
||||
* @param array $labels
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @param bool $group
|
||||
* @return bool
|
||||
*/
|
||||
public function setUserLable($uids, array $labels, int $type = 0, int $relation_id = 0, bool $group = false, $label_type = 0)
|
||||
{
|
||||
if (!$uids) {
|
||||
return true;
|
||||
}
|
||||
if (!is_array($uids)) {
|
||||
$uids = [$uids];
|
||||
}
|
||||
//增加标签
|
||||
$data = [];
|
||||
foreach ($uids as $uid) {
|
||||
if ($label_type == 0) {
|
||||
//用户已经存在的标签
|
||||
$user_label_ids = $this->dao->delete([
|
||||
['uid', '=', $uid],
|
||||
['type', '=', $type],
|
||||
['relation_id', '=', $relation_id]
|
||||
]);
|
||||
if ($labels) {
|
||||
foreach ($labels as $label) {
|
||||
$label = (int)$label;
|
||||
if (!$label) continue;
|
||||
$data[] = ['uid' => $uid, 'label_id' => $label, 'type' => $type, 'relation_id' => $relation_id];
|
||||
}
|
||||
}
|
||||
} elseif ($label_type == 1) {
|
||||
foreach ($labels as $label) {
|
||||
$label = (int)$label;
|
||||
if (!$label) continue;
|
||||
$data[] = ['uid' => $uid, 'label_id' => $label, 'type' => $type, 'relation_id' => $relation_id];
|
||||
}
|
||||
} else {
|
||||
$this->dao->delete([
|
||||
['uid', '=', $uid],
|
||||
['label_id', 'in', $labels],
|
||||
['type', '=', $type],
|
||||
['relation_id', '=', $relation_id]
|
||||
]);
|
||||
}
|
||||
}
|
||||
if ($data) {
|
||||
if (!$this->dao->saveAll($data))
|
||||
throw new AdminException('设置标签失败');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消用户标签
|
||||
* @param int $uid
|
||||
* @param array $labels
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return bool
|
||||
*/
|
||||
public function unUserLabel(int $uid, array $labels = [], int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
$where = [
|
||||
['uid', '=', $uid],
|
||||
['type', '=', $type],
|
||||
['relation_id', '=', $relation_id]
|
||||
];
|
||||
//不传入 清空用户所有标签
|
||||
if (count($labels)) {
|
||||
$where[] = ['label_id', 'in', $labels];
|
||||
}
|
||||
$this->dao->delete($where);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户标签
|
||||
* @param array $uids
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getUserLabelList(array $uids, int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
return $this->dao->getLabelList($uids, $type, $relation_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取用户标签关系映射
|
||||
* @param array $uids 用户ID数组
|
||||
* @param int $type 类型
|
||||
* @param int $relation_id 关联ID
|
||||
* @return array 返回格式:[uid => [label_id1, label_id2, ...]]
|
||||
*/
|
||||
public function getUserLabelsMap(array $uids, int $type = 0, int $relation_id = 0): array
|
||||
{
|
||||
if (empty($uids)) {
|
||||
return [];
|
||||
}
|
||||
$where = [
|
||||
'uid' => $uids,
|
||||
'type' => $type,
|
||||
'relation_id' => $relation_id
|
||||
];
|
||||
|
||||
|
||||
$relations = $this->dao->search($where)->field(['uid', 'label_id'])->select()->toArray();
|
||||
|
||||
$userLabelsMap = [];
|
||||
foreach ($uids as $uid) {
|
||||
$userLabelsMap[$uid] = [];
|
||||
}
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$userLabelsMap[$relation['uid']][] = $relation['label_id'];
|
||||
}
|
||||
|
||||
return $userLabelsMap;
|
||||
}
|
||||
}
|
||||
554
app/services/user/label/UserLabelServices.php
Normal file
554
app/services/user/label/UserLabelServices.php
Normal file
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\label;
|
||||
|
||||
use app\jobs\user\UserLabelJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\label\UserLabelDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use crmeb\services\wechat\Work;
|
||||
use FormBuilder\Factory\Iview;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
/**
|
||||
* 用户标签
|
||||
* Class UserLabelServices
|
||||
* @package app\services\user\label
|
||||
* @mixin UserLabelDao
|
||||
*/
|
||||
class UserLabelServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserLabelDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserLabelDao $dao;
|
||||
|
||||
/**
|
||||
* 获取某一本标签
|
||||
* @param $id
|
||||
* @return array|\think\Model|null
|
||||
*/
|
||||
public function getLable($id)
|
||||
{
|
||||
return $this->dao->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有用户标签
|
||||
* @param array $where
|
||||
* @param array|string[] $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLabelList(array $where = [], array $field = ['*'])
|
||||
{
|
||||
return $this->dao->getList(0, 0, $where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getList(array $where)
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($page, $limit, $where, ['*'], ['category']);
|
||||
$ids = array_column($list, 'id');
|
||||
$userCount = app()->make(UserLabelRelationServices::class)->getLabelUserCount($ids ?: []);
|
||||
$count = $this->dao->count($where);
|
||||
foreach ($list as &$item) {
|
||||
$item['user_count'] = $userCount[$item['id']] ?? 0;
|
||||
}
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加修改标签表单
|
||||
* @param int $id
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @param int $label_cate
|
||||
* @return mixed
|
||||
*/
|
||||
public function add(int $id, int $type = 0, int $relation_id = 0, int $label_cate = 0)
|
||||
{
|
||||
$label = $this->getLable($id);
|
||||
$field = array();
|
||||
/** @var UserLabelCateServices $service */
|
||||
$service = app()->make(UserLabelCateServices::class);
|
||||
$options = [];
|
||||
foreach ($service->getLabelCateAll($type, $relation_id) as $item) {
|
||||
$options[] = ['value' => $item['id'], 'label' => $item['name']];
|
||||
}
|
||||
if (!$label) {
|
||||
$title = '添加标签';
|
||||
$field[] = Form::select('label_cate', '标签分类', $label_cate)->setOptions($options)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择标签分类')->required());
|
||||
$field[] = Form::input('label_name', '标签名称', '')->maxlength(20)->required('请填写标签名称');
|
||||
} else {
|
||||
$title = '修改标签';
|
||||
$field[] = Form::select('label_cate', '分类', (int)$label->getData('label_cate'))->setOptions($options)->filterable(true)->appendValidate(Iview::validateInt()->message('请选择标签分类')->required());
|
||||
$field[] = Form::hidden('id', $label->getData('id'));
|
||||
$field[] = Form::input('label_name', '标签名称', $label->getData('label_name'))->maxlength(20)->required('请填写标签名称');
|
||||
}
|
||||
return create_form($title, $field, Url::buildUrl('/user/user_label/save'), 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存标签表单数据
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $type
|
||||
* @param int $relation_id
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function saveData(int $id, array $data, int $type = 0, int $relation_id = 0)
|
||||
{
|
||||
if (!$data['label_cate']) {
|
||||
throw new ValidateException('请选择标签分类');
|
||||
}
|
||||
|
||||
$processedIds = [];
|
||||
$action = $id ? 'update' : 'create';
|
||||
|
||||
$this->transaction(function () use ($id, $data, $type, $relation_id, &$processedIds) {
|
||||
$data['type'] = $type;
|
||||
$data['relation_id'] = $relation_id;
|
||||
unset($data['id']);
|
||||
if ($id) {
|
||||
if (!$this->getLable($id)) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
$this->dao->update($id, $data);
|
||||
//删除旧标签
|
||||
app()->make(UserLabelExtendServices::class)->searchDel(['label_id' => $id]);
|
||||
app()->make(UserLabelExtendRelationServices::class)->search(['left_id' => $id])->delete();
|
||||
$processedIds = [$id];
|
||||
} else {
|
||||
//组合标签数据
|
||||
$processedIds = [];
|
||||
foreach ($data['label_name'] as $key => $item) {
|
||||
$allLabelData = [
|
||||
'label_name' => $item,
|
||||
'label_cate' => $data['label_cate'],
|
||||
'type' => $data['type'],
|
||||
'relation_id' => $data['relation_id'],
|
||||
'label_type' => $data['label_type'],
|
||||
'is_product' => $data['is_product'],
|
||||
'is_property' => $data['is_property'],
|
||||
'is_trade' => $data['is_trade'],
|
||||
'is_customer' => $data['is_customer'],
|
||||
'is_condition' => $data['is_condition'],
|
||||
'status' => $data['status'],
|
||||
'add_time' => time(),
|
||||
];
|
||||
$processedIds[] = $this->dao->save($allLabelData)->id;
|
||||
}
|
||||
}
|
||||
//批量保存
|
||||
$this->saveExtend($processedIds, $data);
|
||||
return true;
|
||||
});
|
||||
|
||||
// 如果是自动标签,触发批量用户处理
|
||||
if (!empty($processedIds) && isset($data['label_type']) && $data['label_type'] == 2) {
|
||||
try {
|
||||
/** @var UserLabelBatchProcessServices $batchProcessServices */
|
||||
$batchProcessServices = app()->make(UserLabelBatchProcessServices::class);
|
||||
$batchProcessServices->processLabelChange($processedIds, $action);
|
||||
} catch (\Throwable $e) {
|
||||
// 记录错误但不影响标签保存
|
||||
\think\facade\Log::error('触发标签批量处理失败', [
|
||||
'label_ids' => $processedIds,
|
||||
'action' => $action,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签详情
|
||||
* @param int $id 标签ID
|
||||
* @return array
|
||||
* @throws AdminException
|
||||
*/
|
||||
public function getInfo($id)
|
||||
{
|
||||
$info = $this->getLable($id);
|
||||
if (!$info) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
$info = $info->toArray();
|
||||
$userLabelExtendServices = app()->make(UserLabelExtendServices::class);
|
||||
$extendList = $userLabelExtendServices->getLabelExtendList(['label_id' => $id]);
|
||||
// getLabelSpecify
|
||||
$specifyId = 0;
|
||||
foreach ($extendList as &$item) {
|
||||
switch ($item['rule_type']) {
|
||||
case 1:
|
||||
$specifyId = $item['id'];
|
||||
$product_ids = $item['product_ids'] ? explode(',', $item['product_ids']) : [];
|
||||
$info['product'] = [
|
||||
'specify_dimension' => $item['specify_dimension'],
|
||||
'time_dimension' => $item['time_dimension'],
|
||||
'time_value' => $item['time_value'],
|
||||
'ids' => $product_ids,
|
||||
];
|
||||
break;
|
||||
case 2:
|
||||
$info['property']['property_rule'][] = $item;
|
||||
break;
|
||||
case 3:
|
||||
$info['trade']['trade_rule'][] = $item;
|
||||
break;
|
||||
case 4:
|
||||
if ($item['customer_time_start']) {
|
||||
$item['customer_time_start'] = date('Y-m-d', $item['customer_time_start']);
|
||||
}
|
||||
if ($item['customer_time_end']) {
|
||||
$item['customer_time_end'] = date('Y-m-d', $item['customer_time_end']);
|
||||
}
|
||||
$item['time_val'] = [$item['customer_time_start'], $item['customer_time_end']];
|
||||
$info['customer']['customer_rule'][] = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$info['specifyData'] = [];
|
||||
if ($specifyId) {
|
||||
$info['specifyData'] = $userLabelExtendServices->getLabelSpecify($specifyId);
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存标签扩展规则
|
||||
* @param array $ids 标签ID数组
|
||||
* @param array $data 扩展规则数据
|
||||
* @return bool
|
||||
*/
|
||||
public function saveExtend(array $ids, array $data)
|
||||
{
|
||||
if (count($ids) == 0 || count($data) == 0) {
|
||||
return true;
|
||||
}
|
||||
$extendData = [];
|
||||
$relationData = [];
|
||||
foreach ($ids as $id) {
|
||||
//组合商品数据
|
||||
if ($data['is_product'] == 1) {
|
||||
$product = $data['product'];
|
||||
foreach ($product['ids'] as $productId) {
|
||||
$relationData[] = [
|
||||
'type' => $product['specify_dimension'],
|
||||
'left_id' => $id,
|
||||
'right_id' => $productId,
|
||||
];
|
||||
}
|
||||
$extendData[] = [
|
||||
'label_id' => $id,
|
||||
'rule_type' => 1,
|
||||
'time_dimension' => $product['time_dimension'],
|
||||
'time_value' => $product['time_value'],
|
||||
'specify_dimension' => $product['specify_dimension'],
|
||||
'product_ids' => $product['ids'] ? implode(',', $product['ids']) : '',
|
||||
];
|
||||
}
|
||||
//资产
|
||||
if ($data['is_property'] == 1) {
|
||||
$property = $data['property'];
|
||||
foreach ($property['property_rule'] as $item) {
|
||||
$extendData[] = [
|
||||
'label_id' => $id,
|
||||
'rule_type' => 2,
|
||||
'sub_type' => $item['sub_type'],
|
||||
'balance_type' => $item['balance_type'],
|
||||
'operation_type' => $item['operation_type'],
|
||||
'time_dimension' => $item['time_dimension'],
|
||||
'amount_value_max' => $item['amount_value_max'],
|
||||
'amount_value_min' => $item['amount_value_min'],
|
||||
'operation_times_max' => $item['operation_times_max'],
|
||||
'operation_times_min' => $item['operation_times_min'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
//交易
|
||||
if ($data['is_trade'] == 1) {
|
||||
$trade_rule = $data['trade']['trade_rule'];
|
||||
foreach ($trade_rule as $item) {
|
||||
$extendData[] = [
|
||||
'label_id' => $id,
|
||||
'rule_type' => 3,
|
||||
'amount_value_max' => $item['amount_value_max'],
|
||||
'amount_value_min' => $item['amount_value_min'],
|
||||
'operation_times_max' => $item['operation_times_max'],
|
||||
'operation_times_min' => $item['operation_times_min'],
|
||||
'operation_type' => $item['operation_type'],
|
||||
'time_dimension' => $item['time_dimension'],
|
||||
];
|
||||
}
|
||||
}
|
||||
//客户
|
||||
if ($data['is_customer'] == 1) {
|
||||
$customer_rule = $data['customer']['customer_rule'];
|
||||
foreach ($customer_rule as $item) {
|
||||
$time_val = $item['time_val'];
|
||||
$customer_time_start = isset($item['time_val'][0]) && $item['time_val'][0] ? strtotime($time_val[0]) : 0;
|
||||
$customer_time_end = isset($item['time_val'][1]) && $item['time_val'][1] ? strtotime($time_val[1]) + 86399 : 0;
|
||||
$extendData[] = [
|
||||
'label_id' => $id,
|
||||
'rule_type' => 4,
|
||||
'customer_identity' => $item['customer_identity'],
|
||||
'customer_num' => $item['customer_num'],
|
||||
'customer_time_start' => $customer_time_start,
|
||||
'customer_time_end' => $customer_time_end,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($extendData as $v) {
|
||||
app()->make(UserLabelExtendServices::class)->save($v);
|
||||
}
|
||||
|
||||
if (count($relationData) > 0) {
|
||||
app()->make(UserLabelExtendRelationServices::class)->saveAll($relationData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param $id
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delLabel(int $id)
|
||||
{
|
||||
if ($this->getLable($id)) {
|
||||
//删除旧标签
|
||||
app()->make(UserLabelExtendServices::class)->searchDel(['label_id' => $id]);
|
||||
app()->make(UserLabelExtendRelationServices::class)->search(['left_id' => $id])->delete();
|
||||
app()->make(UserLabelRelationServices::class)->search(['label_id' => $id])->delete();
|
||||
if (!$this->dao->delete($id)) {
|
||||
throw new AdminException('删除失败,请稍候再试!');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步标签
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function authWorkClientLabel()
|
||||
{
|
||||
/** @var UserLabelCateServices $cateService */
|
||||
$cateService = app()->make(UserLabelCateServices::class);
|
||||
$data = $cateService->getLabelList(['group' => 0, 'owner_id' => 0]);
|
||||
if ($data['list']) {
|
||||
foreach ($data['list'] as $item) {
|
||||
UserLabelJob::dispatchDo('authLabel', [$item['id'], $item['name']]);
|
||||
}
|
||||
}
|
||||
UserLabelJob::dispatchSece(count($data['list']) + 1, 'authWorkLabel');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步平台标签到企业微信客户
|
||||
* @param int $cateId
|
||||
* @param string $groupName
|
||||
* @return bool
|
||||
*/
|
||||
public function addCorpClientLabel(int $cateId, string $groupName)
|
||||
{
|
||||
try {
|
||||
$list = $this->dao->getList(0, 0, ['not_tag_id' => 1, 'type' => 0, 'label_cate' => $cateId], ['label_name as name', 'id']);
|
||||
if (!$list) {
|
||||
return true;
|
||||
}
|
||||
$data = [];
|
||||
foreach ($list as $item) {
|
||||
$data[] = ['name' => $item['name']];
|
||||
}
|
||||
|
||||
$res = Work::addCorpTag($groupName, $data);
|
||||
/** @var UserLabelCateServices $categoryService */
|
||||
$categoryService = app()->make(UserLabelCateServices::class);
|
||||
$categoryService->update($cateId, ['other' => $res['tag_group']['group_id']]);
|
||||
foreach ($res['tag_group']['tag'] ?? [] as $item) {
|
||||
foreach ($list as $value) {
|
||||
if ($item['name'] == $value['name']) {
|
||||
$this->dao->update($value['id'], ['tag_id' => $item['id']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户标签同步到平台
|
||||
* @param array $tagIds
|
||||
* @param array $group
|
||||
* @return bool
|
||||
*/
|
||||
public function authWorkLabel(array $tagIds = [], array $group = [])
|
||||
{
|
||||
$res = Work::getCorpTags($tagIds, $group);
|
||||
$tagGroup = $res['tag_group'] ?? [];
|
||||
$cateData = [];
|
||||
$labelData = [];
|
||||
$groupIds = [];
|
||||
/** @var UserLabelCateServices $cateService */
|
||||
$cateService = app()->make(UserLabelCateServices::class);
|
||||
$this->transaction(function () use ($tagGroup, $cateData, $cateService, $labelData, $groupIds) {
|
||||
foreach ($tagGroup as $item) {
|
||||
if ($id = $cateService->value(['other' => $item['group_id']], 'id')) {
|
||||
$cateService->update(['id' => $id], ['name' => $item['group_name'], 'other' => $item['group_id'], 'sort' => $item['order']]);
|
||||
} else {
|
||||
$cateData[] = [
|
||||
'name' => $item['group_name'],
|
||||
'sort' => $item['order'],
|
||||
'add_time' => $item['create_time'],
|
||||
'other' => $item['group_id'],
|
||||
'group' => 0
|
||||
];
|
||||
}
|
||||
$groupIds[] = $item['group_id'];
|
||||
foreach ($item['tag'] as $tag) {
|
||||
if ($labelId = $this->dao->value(['tag_id' => $tag['id']], 'id')) {
|
||||
$this->dao->update($labelId, ['tag_id' => $tag['id']]);
|
||||
} else {
|
||||
$labelData[$item['group_id']][] = [
|
||||
'label_name' => $tag['name'],
|
||||
'type' => 0,
|
||||
'tag_id' => $tag['id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($cateData) {
|
||||
$cateService->saveAll($cateData);
|
||||
}
|
||||
$cateIds = $cateService->getColumn([
|
||||
['other', 'in', $groupIds],
|
||||
['type', '=', 0],
|
||||
['owner_id', '=', 0],
|
||||
['group', '=', 0],
|
||||
], 'id', 'other');
|
||||
if ($labelData) {
|
||||
$saveData = [];
|
||||
foreach ($labelData as $groupId => $labels) {
|
||||
$cateId = $cateIds[$groupId];
|
||||
foreach ($labels as $label) {
|
||||
$label['label_cate'] = $cateId;
|
||||
$saveData[] = $label;
|
||||
}
|
||||
}
|
||||
$this->dao->saveAll($saveData);
|
||||
}
|
||||
});
|
||||
$cateService->deleteCateCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取同步企业微信的标签数据
|
||||
* @return array
|
||||
*/
|
||||
public function getWorkLabel()
|
||||
{
|
||||
/** @var UserLabelCateServices $cateService */
|
||||
$cateService = app()->make(UserLabelCateServices::class);
|
||||
$list = $cateService->getLabelTree(['type' => 0, 'owner_id' => 0, 'group' => 0, 'other' => true], ['name', 'id', 'other as value'], [
|
||||
'label' => function ($query) {
|
||||
$query->where('tag_id', '<>', '')->where('type', 0)->field(['id', 'label_cate', 'tag_id as value', 'label_name as label']);
|
||||
}
|
||||
]);
|
||||
foreach ($list as &$item) {
|
||||
$label = $item['label'];
|
||||
$item['children'] = $label;
|
||||
unset($item['label']);
|
||||
$item['label'] = $item['name'];
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信创建客户标签事件
|
||||
* @param string $corpId
|
||||
* @param string $strId
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function createUserLabel(string $corpId, string $strId, string $type)
|
||||
{
|
||||
return $this->authWorkLabel($type === 'tag' ? [$strId] : [], $type === 'tag_group' ? [$strId] : []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信更新客户标签事件
|
||||
* @param string $corpId
|
||||
* @param string $strId
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function updateUserLabel(string $corpId, string $strId, string $type)
|
||||
{
|
||||
return $this->authWorkLabel($type === 'tag' ? [$strId] : [], $type === 'tag_group' ? [$strId] : []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签
|
||||
* @param string $corpId
|
||||
* @param string $strId
|
||||
* @param string $type
|
||||
*/
|
||||
public function deleteUserLabel(string $corpId, string $strId, string $type)
|
||||
{
|
||||
if ('tag' === $type) {
|
||||
$this->dao->delete(['tag_id' => $strId]);
|
||||
} else if ('tag_group' === $type) {
|
||||
/** @var UserLabelCateServices $cateService */
|
||||
$cateService = app()->make(UserLabelCateServices::class);
|
||||
$cateInfo = $cateService->get(['type' => 0, 'owner_id' => 0, 'group' => 0, 'other' => $strId]);
|
||||
if ($cateInfo) {
|
||||
$this->dao->delete(['label_cate' => $cateInfo->id, 'type' => 0]);
|
||||
$cateInfo->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
189
app/services/user/level/SystemUserLevelServices.php
Normal file
189
app/services/user/level/SystemUserLevelServices.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\level;
|
||||
|
||||
use app\jobs\user\UserLevelJob;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\level\SystemUserLevelDao;
|
||||
use app\services\user\UserServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* 系统设置用户等级
|
||||
* Class SystemUserLevelServices
|
||||
* @package app\services\user\level
|
||||
* @mixin SystemUserLevelDao
|
||||
*/
|
||||
class SystemUserLevelServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SystemUserLevelDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected SystemUserLevelDao $dao;
|
||||
|
||||
/**
|
||||
* 单个等级
|
||||
* @param int $id
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLevel(int $id, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne(['id' => $id, 'is_del' => 0], $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员等级信息缓存
|
||||
* @param int $id
|
||||
* @return array|false|mixed|string|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2022/11/14
|
||||
*/
|
||||
public function getLevelCache(int $id)
|
||||
{
|
||||
$level = $this->dao->cacheRemember($id, function () use ($id) {
|
||||
$level = $this->getLevel($id);
|
||||
if ($level) {
|
||||
return $level->toArray();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某条件等级
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getWhereLevel(array $where, string $field = '*')
|
||||
{
|
||||
return $this->dao->getOne($where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有等级列表
|
||||
* @param string $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getLevelList(array $where, string $field = '*',$is_page = true)
|
||||
{
|
||||
$where_data = [];
|
||||
if (isset($where['is_show']) && $where['is_show'] !== '') $where_data[] = ['is_show', '=', $where['is_show']];
|
||||
if (isset($where['title']) && $where['title']) $where_data[] = ['name', 'LIKE', "%$where[title]%"];
|
||||
$where_data[] = ['is_del', '=', '0'];
|
||||
$page = $limit = 0;
|
||||
if($is_page){
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$list = $this->dao->getList($where_data, $field ?? '*', $page, $limit);
|
||||
foreach ($list as &$item) {
|
||||
$item['image'] = set_file_url($item['image']);
|
||||
$item['icon'] = set_file_url($item['icon']);
|
||||
}
|
||||
$count = $this->dao->getCount($where_data);
|
||||
return $is_page ? compact('list', 'count') : $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取条件的会员等级列表
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
*/
|
||||
public function getWhereLevelList(array $where, string $field = '*')
|
||||
{
|
||||
if ($where) {
|
||||
$whereData = [['is_show', '=', 1], ['is_del', '=', 0], $where];
|
||||
} else {
|
||||
$whereData = [['is_show', '=', 1], ['is_del', '=', 0]];
|
||||
}
|
||||
return $this->dao->getList($whereData, $field ?? '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一些用户等级名称
|
||||
* @param $ids
|
||||
* @return array
|
||||
*/
|
||||
public function getUsersLevel($ids)
|
||||
{
|
||||
return $this->dao->getColumn([['id', 'IN', $ids]], 'name', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员等级列表
|
||||
* @param int $leval_id
|
||||
* @return array
|
||||
*/
|
||||
public function getLevelListAndGrade(int $leval_id = 0, string $field = 'name,discount,image,icon,explain,id,grade,is_forever,valid_date,exp_num')
|
||||
{
|
||||
$list = $this->dao->getList(['is_del' => 0, 'is_show' => 1], $field);
|
||||
if ($list) {
|
||||
$listNew = array_combine(array_column($list, 'id'), $list);
|
||||
$grade = $listNew[$leval_id]['grade'] ?? 0;
|
||||
foreach ($list as &$item) {
|
||||
if ($grade < $item['grade'])
|
||||
$item['is_clear'] = true;
|
||||
else
|
||||
$item['is_clear'] = false;
|
||||
$item['task_list'] = [];
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户等级折扣
|
||||
* @param int $uid
|
||||
* @param int $id
|
||||
* @return null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getDiscount(int $uid, int $id)
|
||||
{
|
||||
$discount = null;
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getOne(['uid' => $uid], 'uid,level,level_status');
|
||||
//需要会员是激活状态
|
||||
if ($id && $userInfo && $userInfo['level_status']) {
|
||||
$level = $this->dao->getOne(['id' => $id, 'is_del' => 0, 'is_show' => 1], 'id,discount');
|
||||
if (!$level) {//用户存在等级ID 但是被删除或者下架重新检测升级
|
||||
UserLevelJob::dispatch([$uid]);
|
||||
$level = $this->dao->getOne(['id' => $userInfo['level'], 'is_del' => 0, 'is_show' => 1], 'id,discount');
|
||||
}
|
||||
$discount = $level['discount'] ?? null;
|
||||
}
|
||||
return $discount;
|
||||
}
|
||||
}
|
||||
680
app/services/user/level/UserLevelServices.php
Normal file
680
app/services/user/level/UserLevelServices.php
Normal file
@@ -0,0 +1,680 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\services\user\level;
|
||||
|
||||
use app\jobs\user\UserLevelJob;
|
||||
use app\services\activity\coupon\StoreCouponIssueServices;
|
||||
use app\services\activity\coupon\StoreCouponUserServices;
|
||||
use app\services\BaseServices;
|
||||
use app\services\user\UserServices;
|
||||
use app\services\user\UserBillServices;
|
||||
use app\services\user\UserSignServices;
|
||||
use app\dao\user\level\UserLevelDao;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use FormBuilder\Factory\Iview;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Route as Url;
|
||||
|
||||
|
||||
/**
|
||||
* 用户等级
|
||||
* Class UserLevelServices
|
||||
* @package app\services\user\level
|
||||
* @mixin UserLevelDao
|
||||
*/
|
||||
class UserLevelServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserLevelDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserLevelDao $dao;
|
||||
|
||||
/**
|
||||
* 某些条件获取单个
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWhereLevel(array $where, string $field = '*')
|
||||
{
|
||||
return $this->getOne($where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一些用户等级信息
|
||||
* @param array $uids
|
||||
* @param string $field
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function getUsersLevelInfo(array $uids)
|
||||
{
|
||||
return $this->dao->getColumn([['uid', 'in', $uids]], 'level_id,is_forever,valid_time,grade', 'uid');
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除会员等级
|
||||
* @param $uids
|
||||
* @return \crmeb\basic\BaseModel|mixed
|
||||
*/
|
||||
public function delUserLevel($uids)
|
||||
{
|
||||
$where = [];
|
||||
if (is_array($uids)) {
|
||||
$where[] = ['uid', 'IN', $uids];
|
||||
$re = $this->dao->batchUpdate($uids, ['is_del' => 1, 'status' => 0], 'uid');
|
||||
} else {
|
||||
$where[] = ['uid', '=', $uids];
|
||||
$re = $this->dao->update($uids, ['is_del' => 1, 'status' => 0], 'uid');
|
||||
}
|
||||
if (!$re)
|
||||
throw new AdminException('修改会员信息失败');
|
||||
$where[] = ['category', 'IN', ['exp']];
|
||||
/** @var UserBillServices $userbillServices */
|
||||
$userbillServices = app()->make(UserBillServices::class);
|
||||
$userbillServices->update($where, ['status' => -1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人中心获取用户等级信息
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function homeGetUserLevel(int $uid, $userInfo = [])
|
||||
{
|
||||
$data = ['vip' => false, 'vip_id' => 0, 'vip_icon' => '', 'vip_name' => '', 'vip_discount' => 100];
|
||||
//用户存在
|
||||
if ($uid && sys_config('member_func_status', 0)) {
|
||||
if (!$userInfo) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserInfo($uid);
|
||||
}
|
||||
if ($userInfo) {
|
||||
$levelInfo = $this->getUerLevelInfoByUid($uid);
|
||||
if (!$levelInfo) {//不存在等级 展示最低等级
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$alllevelInfo = $systemUserLevel->getList([['is_del', '=', 0], ['is_show', '=', 1]], 'id,name,icon,grade,discount', 1, 1);
|
||||
$levelInfo = $alllevelInfo[0] ?? [];
|
||||
if ($levelInfo) {
|
||||
$levelInfo['id'] = 0;
|
||||
$levelInfo['icon'] = set_file_url($levelInfo['icon'] ?? '');
|
||||
}
|
||||
}
|
||||
if ($levelInfo) {
|
||||
$data['vip'] = true;
|
||||
$data['vip_id'] = $levelInfo['id'];
|
||||
$data['vip_icon'] = $levelInfo['icon'];
|
||||
$data['vip_name'] = $levelInfo['name'];
|
||||
$data['vip_discount'] = $levelInfo['discount'] ? bcdiv((string)$levelInfo['discount'], '10', 1) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户uid 获取会员详细信息
|
||||
* @param int $uid
|
||||
* @param string $field
|
||||
*/
|
||||
public function getUerLevelInfoByUid(int $uid, string $field = '')
|
||||
{
|
||||
$userLevelInfo = $this->dao->getUserLevel($uid);
|
||||
$data = [];
|
||||
if ($userLevelInfo) {
|
||||
$data = ['id' => $userLevelInfo['id'], 'level_id' => $userLevelInfo['level_id'], 'add_time' => $userLevelInfo['add_time']];
|
||||
$data['discount'] = $userLevelInfo['levelInfo']['discount'] ?? 0;
|
||||
$data['name'] = $userLevelInfo['levelInfo']['name'] ?? '';
|
||||
$data['money'] = $userLevelInfo['levelInfo']['money'] ?? 0;
|
||||
$data['icon'] = set_file_url($userLevelInfo['levelInfo']['icon'] ?? '');
|
||||
$data['image'] = set_file_url($userLevelInfo['levelInfo']['image'] ?? '');
|
||||
$data['is_pay'] = $userLevelInfo['levelInfo']['is_pay'] ?? 0;
|
||||
$data['grade'] = $userLevelInfo['levelInfo']['grade'] ?? 0;
|
||||
$data['exp_num'] = $userLevelInfo['levelInfo']['exp_num'] ?? 0;
|
||||
}
|
||||
if ($field) return $data[$field] ?? '';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置会员等级
|
||||
* @param $uid 用户uid
|
||||
* @param $level_id 等级id
|
||||
* @return UserLevel|bool|\think\Model
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function setUserLevel(int $uid, int $level_id, $vipinfo = [])
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemLevelServices */
|
||||
$systemLevelServices = app()->make(SystemUserLevelServices::class);
|
||||
if (!$vipinfo) {
|
||||
$vipinfo = $systemLevelServices->getLevel($level_id);
|
||||
if (!$vipinfo) {
|
||||
throw new AdminException('会员等级不存在');
|
||||
}
|
||||
}
|
||||
/** @var UserServices $user */
|
||||
$user = app()->make(UserServices::class);
|
||||
$userinfo = $user->getUserInfo($uid);
|
||||
//把之前等级作废
|
||||
$this->dao->update(['uid' => $uid], ['status' => 0, 'is_del' => 1]);
|
||||
//检查是否购买过
|
||||
$uservipinfo = $this->getWhereLevel(['uid' => $uid, 'level_id' => $level_id]);
|
||||
$data['mark'] = '尊敬的用户' . $userinfo['nickname'] . '在' . date('Y-m-d H:i:s', time()) . '成为了' . $vipinfo['name'];
|
||||
$data['add_time'] = time();
|
||||
if ($uservipinfo) {
|
||||
$data['status'] = 1;
|
||||
$data['is_del'] = 0;
|
||||
if (!$this->dao->update(['id' => $uservipinfo['id']], $data))
|
||||
throw new AdminException('修改会员信息失败');
|
||||
} else {
|
||||
$data = array_merge($data, [
|
||||
'is_forever' => $vipinfo->is_forever,
|
||||
'status' => 1,
|
||||
'is_del' => 0,
|
||||
'grade' => $vipinfo->grade,
|
||||
'uid' => $uid,
|
||||
'level_id' => $level_id,
|
||||
'discount' => $vipinfo->discount,
|
||||
]);
|
||||
$data['valid_time'] = 0;
|
||||
if (!$this->dao->save($data)) throw new AdminException('写入会员信息失败');
|
||||
}
|
||||
if (!$user->update(['uid' => $uid], ['level' => $level_id, 'exp' => $vipinfo['exp_num'], 'level_status' => 1]))
|
||||
throw new AdminException('修改用户会员等级失败');
|
||||
//自动打标签
|
||||
event('user.auto.label', [$uid, '', [], []]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员列表
|
||||
* @param $where
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSytemList($where)
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemLevelServices */
|
||||
$systemLevelServices = app()->make(SystemUserLevelServices::class);
|
||||
return $systemLevelServices->getLevelList($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加修改需要表单数据
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @throws \FormBuilder\Exception\FormBuilderException
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
|
||||
if ($id) {
|
||||
$vipinfo = app()->make(SystemUserLevelServices::class)->getlevel($id);
|
||||
if (!$vipinfo) {
|
||||
throw new AdminException('数据不存在');
|
||||
}
|
||||
$field[] = Form::hidden('id', $id);
|
||||
$msg = '编辑会员等级';
|
||||
} else {
|
||||
$msg = '添加会员等级';
|
||||
}
|
||||
$field[] = Form::input('name', '等级名称:', $vipinfo['name'] ?? '')->required('请填写等级名称');
|
||||
// $field[] = Form::number('valid_date', '有效时间(天)', $vipinfo['valid_date'] ?? 0)->min(0)->col(12);
|
||||
$field[] = Form::number('grade', '等级:', $vipinfo['grade'] ?? 0)->min(0)->precision(0);
|
||||
$field[] = Form::number('discount', '享受折扣:', $vipinfo['discount'] ?? 100)->min(0)->max(100)->info('输入折扣数100,代表划线价,90代表9折')->placeholder('输入折扣数100,代表原价,90代表9折');
|
||||
$field[] = Form::number('exp_num', '解锁需经验值达到:', $vipinfo['exp_num'] ?? 0)->min(0)->precision(0);
|
||||
$field[] = Form::frameImage('icon', '卡片(656*300):', Url::buildUrl('admin/widget.images/index', array('fodder' => 'icon')), $vipinfo['icon'] ?? '')->icon('ios-add')->width('960px')->height('505px')->modal(['footer-hide' => true])->appendValidate(Iview::validateStr()->required()->message('请选择图标'));
|
||||
$field[] = Form::frameImage('image', '卡背景(750*990):', Url::buildUrl('admin/widget.images/index', array('fodder' => 'image')), $vipinfo['image'] ?? '')->icon('ios-add')->width('960px')->height('505px')->modal(['footer-hide' => true])->appendValidate(Iview::validateStr()->required()->message('请选择背景'));
|
||||
$field[] = Form::color('color', '字体颜色:', $vipinfo['color'] ?? '#000000')->required('请选择字体颜色');
|
||||
$field[] = Form::radio('is_show', '是否显示:', $vipinfo['is_show'] ?? 0)->options([['label' => '显示', 'value' => 1], ['label' => '隐藏', 'value' => 0]]);
|
||||
$field[] = Form::textarea('explain', '等级说明:', $vipinfo['explain'] ?? '')->required('请添加等级说明');
|
||||
return create_form($msg, $field, Url::buildUrl('/user/user_level'), 'POST');
|
||||
}
|
||||
|
||||
/*
|
||||
* 会员等级添加或者修改
|
||||
* @param $id 修改的等级id
|
||||
* @return json
|
||||
* */
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$levelOne = $systemUserLevel->getWhereLevel(['is_del' => 0, 'grade' => $data['grade']]);
|
||||
$levelTwo = $systemUserLevel->getWhereLevel(['is_del' => 0, 'exp_num' => $data['exp_num']]);
|
||||
$levelThree = $systemUserLevel->getWhereLevel(['is_del' => 0, 'name' => $data['name']]);
|
||||
$levelPre = $systemUserLevel->getPreLevel($data['grade']);
|
||||
$levelNext = $systemUserLevel->getNextLevel($data['grade']);
|
||||
if ($levelPre && $data['exp_num'] <= $levelPre['exp_num']) {
|
||||
throw new AdminException('会员经验必须大于上一等级设置的经验');
|
||||
}
|
||||
if ($levelNext && $data['exp_num'] >= $levelNext['exp_num']) {
|
||||
throw new AdminException('会员经验必须小于下一等级设置的经验');
|
||||
}
|
||||
//修改
|
||||
if ($id) {
|
||||
if (($levelOne && $levelOne['id'] != $id) || ($levelThree && $levelThree['id'] != $id)) {
|
||||
throw new AdminException('已检测到您设置过的会员等级,此等级不可重复');
|
||||
}
|
||||
if ($levelTwo && $levelTwo['id'] != $id) {
|
||||
throw new AdminException('已检测到您设置过该会员经验值,经验值不可重复');
|
||||
}
|
||||
if (!$systemUserLevel->update($id, $data)) {
|
||||
throw new AdminException('修改失败');
|
||||
}
|
||||
|
||||
$data['id'] = $id;
|
||||
$systemUserLevel->cacheUpdate($data);
|
||||
|
||||
return '修改成功';
|
||||
} else {
|
||||
if ($levelOne || $levelThree) {
|
||||
throw new AdminException('已检测到您设置过的会员等级,此等级不可重复');
|
||||
}
|
||||
if ($levelTwo) {
|
||||
throw new AdminException('已检测到您设置过该会员经验值,经验值不可重复');
|
||||
}
|
||||
//新增
|
||||
$data['add_time'] = time();
|
||||
$res = $systemUserLevel->save($data);
|
||||
if (!$res) {
|
||||
throw new AdminException('添加失败');
|
||||
}
|
||||
|
||||
$data['id'] = $res->id;
|
||||
$systemUserLevel->cacheUpdate($data);
|
||||
|
||||
return '添加成功';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 假删除
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function delLevel(int $id)
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$level = $systemUserLevel->getWhereLevel(['id' => $id]);
|
||||
if ($level && $level['is_del'] != 1) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
if ($userServices->count(['level' => $level['id']])) {
|
||||
throw new AdminException('存在用户已是该等级,无法删除');
|
||||
}
|
||||
if (!$systemUserLevel->update($id, ['is_del' => 1]))
|
||||
throw new AdminException('删除失败');
|
||||
if (!$this->dao->update(['level_id' => $id], ['is_del' => 1])) {
|
||||
throw new AdminException('删除失败');
|
||||
}
|
||||
$systemUserLevel->cacheDelById($id);
|
||||
}
|
||||
return '删除成功';
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否显示
|
||||
* @param int $id
|
||||
* @param $is_show
|
||||
* @return mixed
|
||||
*/
|
||||
public function setShow(int $id, int $is_show)
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
if (!$systemUserLevel->getWhereLevel(['id' => $id]))
|
||||
throw new AdminException('数据不存在');
|
||||
if ($systemUserLevel->update($id, ['is_show' => $is_show])) {
|
||||
$systemUserLevel->cacheSaveValue($id, 'is_show', $is_show);
|
||||
return $is_show == 1 ? '显示成功' : '隐藏成功';
|
||||
} else {
|
||||
throw new AdminException($is_show == 1 ? '显示失败' : '隐藏失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速修改
|
||||
* @param int $id
|
||||
* @param $is_show
|
||||
* @return mixed
|
||||
*/
|
||||
public function setValue(int $id, array $data)
|
||||
{
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
if (!$systemUserLevel->getWhereLevel(['id' => $id]))
|
||||
throw new AdminException('数据不存在');
|
||||
if ($systemUserLevel->update($id, [$data['field'] => $data['value']])) {
|
||||
$systemUserLevel->cacheSaveValue($id, $data['field'], $data['value']);
|
||||
return true;
|
||||
} else {
|
||||
throw new AdminException('保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测用户会员升级
|
||||
* @param $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function detection(int $uid)
|
||||
{
|
||||
//商城会员是否开启
|
||||
if (!sys_config('member_func_status')) {
|
||||
return true;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserCacheInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('没有此用户,无法检测升级会员');
|
||||
}
|
||||
if (!$user['level_status'] && sys_config('level_activate_status') == 0) {
|
||||
$userServices->update($uid, ['level_status' => 1]);
|
||||
$userServices->cacheTag()->clear();
|
||||
}
|
||||
//没有激活暂不升级
|
||||
if (!$user['level_status']) {
|
||||
return true;
|
||||
}
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$userAllLevel = $systemUserLevel->getList([['is_del', '=', 0], ['is_show', '=', 1], ['exp_num', '<=', (float)$user['exp']]]);
|
||||
if (!$userAllLevel) {
|
||||
return true;
|
||||
}
|
||||
$data = [];
|
||||
$data['add_time'] = time();
|
||||
$userLevel = $this->dao->getColumn(['uid' => $uid, 'status' => 1, 'is_del' => 0], 'level_id');
|
||||
foreach ($userAllLevel as $vipinfo) {
|
||||
if (in_array($vipinfo['id'], $userLevel)) {
|
||||
continue;
|
||||
}
|
||||
$data['mark'] = '尊敬的用户' . $user['nickname'] . '在' . date('Y-m-d H:i:s', time()) . '成为了' . $vipinfo['name'];
|
||||
$uservip = $this->dao->getOne(['uid' => $uid, 'level_id' => $vipinfo['id']], 'id');
|
||||
if ($uservip) {
|
||||
//降级在升级情况
|
||||
$data['status'] = 1;
|
||||
$data['is_del'] = 0;
|
||||
if (!$this->dao->update($uservip['id'], $data, 'id')) {
|
||||
throw new ValidateException('检测升级失败');
|
||||
}
|
||||
} else {
|
||||
$data = array_merge($data, [
|
||||
'is_forever' => $vipinfo['is_forever'],
|
||||
'status' => 1,
|
||||
'is_del' => 0,
|
||||
'grade' => $vipinfo['grade'],
|
||||
'uid' => $uid,
|
||||
'level_id' => $vipinfo['id'],
|
||||
'discount' => $vipinfo['discount'],
|
||||
]);
|
||||
if (!$this->dao->save($data)) {
|
||||
throw new ValidateException('检测升级失败');
|
||||
}
|
||||
}
|
||||
$data['add_time'] += 1;
|
||||
}
|
||||
if (!$userServices->update($uid, ['level' => end($userAllLevel)['id']], 'uid')) {
|
||||
throw new ValidateException('检测升级失败');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员等级列表
|
||||
* @param int $uid
|
||||
*/
|
||||
public function grade(int $uid)
|
||||
{
|
||||
//商城会员是否开启
|
||||
if (!sys_config('member_func_status')) {
|
||||
return [];
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserCacheInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('没有此用户,无法检测升级会员');
|
||||
}
|
||||
$userLevelInfo = $this->getUerLevelInfoByUid($uid);
|
||||
if (empty($userLevelInfo)) {
|
||||
$level_id = 0;
|
||||
} else {
|
||||
$level_id = $userLevelInfo['level_id'];
|
||||
}
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
return $systemUserLevel->getLevelListAndGrade($level_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员信息
|
||||
* @param int $uid
|
||||
* @return array[]
|
||||
*/
|
||||
public function getUserLevelInfo(int $uid)
|
||||
{
|
||||
$data = ['user' => [], 'level_info' => [], 'level_list' => [], 'task' => []];
|
||||
//商城会员是否开启
|
||||
if (!sys_config('member_func_status')) {
|
||||
return $data;
|
||||
}
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('没有此会员');
|
||||
}
|
||||
/** @var StoreCouponUserServices $storeCoupon */
|
||||
$storeCoupon = app()->make(StoreCouponUserServices::class);
|
||||
$user['couponCount'] = $storeCoupon->getUserValidCouponCount((int)$uid);
|
||||
$data['user'] = $user;
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$levelList = $systemUserLevel->getList(['is_del' => 0, 'is_show' => 1]);
|
||||
$i = 0;
|
||||
foreach ($levelList as &$level) {
|
||||
$level['next_exp_num'] = $levelList[$i + 1]['exp_num'] ?? $level['exp_num'];
|
||||
$level['image'] = set_file_url($level['image']);
|
||||
$level['icon'] = set_file_url($level['icon']);
|
||||
$i++;
|
||||
}
|
||||
$data['level_list'] = $levelList;
|
||||
$levelInfo = $this->getUerLevelInfoByUid($uid);
|
||||
if (!$levelInfo) {//不存在等级 展示最低等级
|
||||
/** @var SystemUserLevelServices $systemUserLevel */
|
||||
$systemUserLevel = app()->make(SystemUserLevelServices::class);
|
||||
$alllevelInfo = $systemUserLevel->getList([['is_del', '=', 0], ['is_show', '=', 1]], 'id,name,icon,grade', 1, 1);
|
||||
$levelInfo = $alllevelInfo[0] ?? [];
|
||||
if ($levelInfo) {
|
||||
$levelInfo['id'] = 0;
|
||||
}
|
||||
}
|
||||
if ($levelInfo) {
|
||||
$levelInfo['vip'] = true;
|
||||
$levelInfo['vip_id'] = $levelInfo['id'];
|
||||
$levelInfo['vip_icon'] = $levelInfo['icon'];
|
||||
$levelInfo['vip_name'] = $levelInfo['name'];
|
||||
}
|
||||
$data['level_info'] = $levelInfo;
|
||||
$i = 0;
|
||||
foreach ($levelList as &$level) {
|
||||
if ($level['grade'] < $levelInfo['grade']) {
|
||||
$level['next_exp_num'] = $levelList[$i + 1]['exp_num'] ?? $level['exp_num'];
|
||||
$level['lack_exp_num'] = 0;
|
||||
} else {
|
||||
$level['next_exp_num'] = $level['exp_num'];
|
||||
if ($user['exp'] > $level['exp_num']) {
|
||||
$level['lack_exp_num'] = 0;
|
||||
} else {
|
||||
$level['lack_exp_num'] = bcsub((string)$level['exp_num'], (string)$user['exp'], 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$level['image'] = set_file_url($level['image']);
|
||||
$level['icon'] = set_file_url($level['icon']);
|
||||
$i++;
|
||||
}
|
||||
$data['level_list'] = $levelList;
|
||||
|
||||
|
||||
$data['level_info']['exp'] = $user['exp'] ?? 0;
|
||||
|
||||
|
||||
/** @var UserBillServices $userBillservices */
|
||||
$userBillservices = app()->make(UserBillServices::class);
|
||||
$data['level_info']['today_exp'] = $userBillservices->getExpSum($uid, 'today');
|
||||
$task = [];
|
||||
/** @var UserSignServices $userSignServices */
|
||||
$userSignServices = app()->make(UserSignServices::class);
|
||||
$task['sign_count'] = $userSignServices->getSignSumDay($uid);
|
||||
$config = SystemConfigService::more(['sign_give_exp', 'order_give_exp', 'invite_user_exp']);
|
||||
$task['sign'] = $config['sign_give_exp'] ?? 0;
|
||||
$task['order'] = $config['order_give_exp'] ?? 0;
|
||||
$task['invite'] = $config['invite_user_exp'] ?? 0;
|
||||
$data['task'] = $task;
|
||||
|
||||
|
||||
//检测升级
|
||||
UserLevelJob::dispatch([$uid]);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 经验列表
|
||||
* @param int $uid
|
||||
* @return array
|
||||
*/
|
||||
public function expList(int $uid)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserCacheInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('没有此用户');
|
||||
}
|
||||
/** @var UserBillServices $userBill */
|
||||
$userBill = app()->make(UserBillServices::class);
|
||||
$data = $userBill->getExpList($uid, [], 'id,title,number,pm,add_time');
|
||||
$list = $data['list'] ?? [];
|
||||
$count = $data['count'] ?? 0;
|
||||
$times = [];
|
||||
if ($list) {
|
||||
foreach ($list as $key => &$item) {
|
||||
$addTime = strtotime($item['add_time']);
|
||||
$item['time_key'] = $item['time'] = $addTime ? date('Y-m', (int)$addTime) : '';
|
||||
}
|
||||
$times = array_merge(array_unique(array_column($list, 'time_key')));
|
||||
}
|
||||
return ['count' => $count, 'list' => $list, 'time' => $times];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取激活会员卡需要的信息
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActivateInfo()
|
||||
{
|
||||
//商城会员是否开启
|
||||
if (!sys_config('member_func_status')) {
|
||||
throw new ValidateException('会员卡功能暂未开启');
|
||||
}
|
||||
//是否需要激活
|
||||
if (!sys_config('level_activate_status')) {
|
||||
throw new ValidateException('会员卡功能暂不需要激活');
|
||||
}
|
||||
return SystemConfigService::get('level_extend_info');
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活会员卡
|
||||
* @param int $uid
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function userActivatelevel(int $uid, array $data)
|
||||
{
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->getUserInfo($uid);
|
||||
if (!$user) {
|
||||
throw new ValidateException('用户已注销,或不存在');
|
||||
}
|
||||
if ($user['level_status']) {
|
||||
throw new ValidateException('不需要重复激活');
|
||||
}
|
||||
$extend_info = $userServices->handelExtendInfo($data, true) ?: [];
|
||||
$update = ['level_status' => 1];
|
||||
if ($extend_info) {
|
||||
$default = $userServices->defaultExtendInfo;
|
||||
$params = array_column($default, 'param');
|
||||
$sex = $userServices->sex;
|
||||
$update['level_extend_info'] = $extend_info;
|
||||
foreach ($extend_info as $info) {
|
||||
if (isset($info['param']) && in_array($info['param'], $params) && isset($info['value'])) {
|
||||
if ($info['param'] == 'sex') {
|
||||
$update['sex'] = $sex[$info['value']] ?? 0;
|
||||
} elseif ($info['param'] == 'birthday') {
|
||||
$update['birthday'] = $info['value'];
|
||||
} else {
|
||||
$update[$info['param']] = $info['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$userServices->update($uid, $update);
|
||||
|
||||
$data = [];
|
||||
//获取激活送好礼
|
||||
$data = SystemConfigService::more([
|
||||
'level_integral_status',
|
||||
'level_give_integral',
|
||||
'level_money_status',
|
||||
'level_give_money',
|
||||
'level_coupon_status',
|
||||
'level_give_coupon',
|
||||
]);
|
||||
$ids = $data['level_give_coupon'] ?? [];
|
||||
$data['level_give_coupon'] = [];
|
||||
if ($data['level_coupon_status'] && $ids) {
|
||||
/** @var StoreCouponIssueServices $couponServices */
|
||||
$couponServices = app()->make(StoreCouponIssueServices::class);
|
||||
$coupon = $couponServices->getList(['id' => $ids]);
|
||||
$data['level_give_coupon'] = $coupon;
|
||||
}
|
||||
if (!$data['level_integral_status']) {
|
||||
$data['level_give_integral'] = 0;
|
||||
}
|
||||
if (!$data['level_money_status']) {
|
||||
$data['level_give_money'] = 0;
|
||||
}
|
||||
//激活会员卡事件
|
||||
event('user.activate.level', [$uid]);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
156
app/services/user/member/MemberCardBatchServices.php
Normal file
156
app/services/user/member/MemberCardBatchServices.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\member;
|
||||
|
||||
|
||||
use app\dao\user\member\MemberCardBatchDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class MemberCardBatchServices
|
||||
* @package app\services\user\member
|
||||
* @mixin MemberCardBatchDao
|
||||
*/
|
||||
class MemberCardBatchServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MemberCardBatchDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected MemberCardBatchDao $dao;
|
||||
|
||||
/**
|
||||
* 获取会员卡批次列表
|
||||
* @param array $where
|
||||
*/
|
||||
public function getList(array $where = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getList($where, $page, $limit);
|
||||
|
||||
if ($list) {
|
||||
foreach ($list as &$v) {
|
||||
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
|
||||
//$v['qrcode'] = json_decode($v['qrcode'], true);
|
||||
}
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
if (!$data['title']) throw new AdminException("请填写批次名称");
|
||||
if (!$data['total_num']) throw new AdminException("请填写要生成卡的数量");
|
||||
if (!is_numeric($data['total_num']) || $data['total_num'] < 0) throw new AdminException("卡片数量只能为正整数");
|
||||
if ($data['total_num'] > 6000) throw new AdminException("单次制卡数量最高不得超过6000张");
|
||||
if (!$data['use_day'] || !is_numeric($data['use_day'])) throw new AdminException("请填写免费使用天数");
|
||||
if ($data['use_day'] < 0) throw new AdminException("免费使用天数只能为正整数");
|
||||
/**
|
||||
* 具体时间段试用,业务需要打开即可
|
||||
*/
|
||||
/* $use_start_time = strtotime($data['use_start_time']);
|
||||
$use_end_time = strtotime($data['use_end_time']);
|
||||
if (!$use_start_time) {
|
||||
$use_start_time = strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')));
|
||||
}else{
|
||||
$use_start_time = strtotime($data['use_start_time']);
|
||||
}
|
||||
if (!$use_end_time) {
|
||||
$use_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('+1 day')));
|
||||
}else{
|
||||
$use_end_time = strtotime($data['use_end_time']);
|
||||
}
|
||||
if ($use_end_time < time()) throw new AdminException("体验结束时间不能小于当天");
|
||||
if ($use_end_time < $use_start_time) throw new AdminException("体验结束时间不能小于体验开始时间");
|
||||
$data['use_start_time'] = $use_start_time;
|
||||
$data['use_end_time'] = $use_end_time;*/
|
||||
$data['use_day'] = abs(ceil($data['use_day']));
|
||||
$data['total_num'] = abs(ceil($data['total_num']));
|
||||
$data['add_time'] = time();
|
||||
$this->transaction(function () use ($id, $data) {
|
||||
if ($id) {
|
||||
unset($data['total_num']);
|
||||
$data['update_time'] = time();
|
||||
return $this->dao->update($id, $data);
|
||||
} else {
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$res = $this->dao->save($data);
|
||||
$add_card['card_batch_id'] = $res->id;
|
||||
$add_card['total_num'] = $data['total_num'];
|
||||
return $memberCardService->addCard($add_card);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表操作
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function setValue(int $id, array $data)
|
||||
{
|
||||
if (!is_numeric($id) || !$id) throw new AdminException("参数缺失");
|
||||
if (!isset($data['field']) || !isset($data['value']) || !$data['field']) throw new AdminException("参数错误");
|
||||
$res = true;
|
||||
if ($data['field'] == 'status') {
|
||||
/** @var MemberCardServices $memberCardService */
|
||||
$memberCardService = app()->make(MemberCardServices::class);
|
||||
$res = $memberCardService->update(['card_batch_id' => $id], ['status' => $data['value']]);
|
||||
}
|
||||
if ($res) {
|
||||
$this->dao->update($id, [$data['field'] => $data['value']]);
|
||||
} else {
|
||||
throw new AdminException("操作错误");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取单条卡批次资源
|
||||
* @param array $uid
|
||||
* @param string $field
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOne(int $bid, $field = '*')
|
||||
{
|
||||
if (is_string($field)) $field = explode(',', $field);
|
||||
return $this->dao->get($bid, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批次卡数量统计
|
||||
* @param int $id
|
||||
* @param string $field
|
||||
* @param int $inc
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function useCardSetInc(int $id, string $field, int $inc = 1)
|
||||
{
|
||||
return $this->dao->bcInc($id, $field, $inc);
|
||||
}
|
||||
|
||||
}
|
||||
453
app/services/user/member/MemberCardServices.php
Normal file
453
app/services/user/member/MemberCardServices.php
Normal file
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\member;
|
||||
|
||||
|
||||
use app\dao\user\member\MemberCardDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\order\OtherOrderServices;
|
||||
use app\services\order\StoreOrderCreateServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
use app\services\user\UserServices;
|
||||
|
||||
/**
|
||||
* Class MemberCardServices
|
||||
* @package app\services\user\member
|
||||
* @mixin MemberCardDao
|
||||
*/
|
||||
class MemberCardServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array|string[]
|
||||
*/
|
||||
public static array $_memberTypePrefix = ['month', 'quarter', 'year', 'ever', 'free'];
|
||||
|
||||
/**
|
||||
* @var MemberCardDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected MemberCardDao $dao;
|
||||
|
||||
/**
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2023/9/18
|
||||
*/
|
||||
public function getSearchList(array $where = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$where['batch_card_id'] = $where['card_batch_id'];
|
||||
if ($where['is_use'] != "") {
|
||||
if ($where['is_use'] == 0) {
|
||||
$where['use_time'] = 0;
|
||||
} else {
|
||||
$where['use_time'] = 1;
|
||||
}
|
||||
}
|
||||
unset($where['is_use']);
|
||||
$list = $this->dao->getSearchList($where, $page, $limit);
|
||||
if ($list) {
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userInfos = $userService->getColumn([['uid', 'in', array_unique(array_column($list, 'use_uid'))]], 'uid,real_name,nickname,phone', 'uid');
|
||||
foreach ($list as $k => $v) {
|
||||
$list[$k]['username'] = $list[$k]['phone'] = '';
|
||||
$user_info = $userInfos[$v['use_uid']] ?? [];
|
||||
if ($v['use_uid'] && $user_info) {
|
||||
$list[$k]['username'] = $user_info['real_name'] ? $user_info['real_name'] : $user_info['nickname'];
|
||||
$list[$k]['phone'] = $user_info ? $user_info['phone'] : "";
|
||||
}
|
||||
$list[$k]['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
|
||||
$list[$k]['use_time'] = $v['use_time'] != 0 ? date('Y-m-d H:i:s', $v['use_time']) : "未使用";
|
||||
}
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成免费会员卡
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function addCard(array $data)
|
||||
{
|
||||
if (!isset($data['card_batch_id']) || !$data['card_batch_id'] || $data['card_batch_id'] == 0 || !isset($data['total_num']) || !$data['total_num'] || $data['total_num'] == 0) {
|
||||
throw new AdminException("非法参数");
|
||||
}
|
||||
try {
|
||||
if (!isset($data['total_num'])) throw new AdminException("数据缺失");
|
||||
$num = $data['total_num'];
|
||||
unset($data['total_num']);
|
||||
for ($i = 0; $i < $num; $i++) {
|
||||
$data['card_number'] = $this->makeRandomNumber("CR", $data['card_batch_id']);
|
||||
$data['card_password'] = $this->makeRandomNumber();
|
||||
$data['status'] = 1;
|
||||
$data['add_time'] = time();
|
||||
$res[] = $data;
|
||||
}
|
||||
//数据切片批量插入,提高性能。
|
||||
$chunk_inster_card = array_chunk($res, 100, true);
|
||||
foreach ($chunk_inster_card as $v) {
|
||||
$this->dao->saveAll($v);
|
||||
}
|
||||
return true;
|
||||
} catch (\Exception $exception) {
|
||||
throw new AdminException("生成卡失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取制卡卡号随机数
|
||||
* @param false $prefix
|
||||
* @param false $random
|
||||
* @return string
|
||||
*/
|
||||
public function makeRandomNumber($prefix = false, $random = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$prefix = "";
|
||||
}
|
||||
if (!$random || !is_numeric($random)) {
|
||||
mt_srand();
|
||||
$one_random = mt_rand(11111, 99999);
|
||||
} else {
|
||||
$one_random = sprintf("%05d", $random);
|
||||
}
|
||||
$date_random = date('ymd', time());
|
||||
$random_tmp = strlen($one_random);
|
||||
mt_srand();
|
||||
$two_randow = str_pad(mt_rand(1, 99999), $random_tmp, '0', STR_PAD_LEFT);
|
||||
if (!$random) {
|
||||
return $two_randow;
|
||||
} else {
|
||||
return $prefix . $one_random . $date_random . $two_randow;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取会员卡
|
||||
* @param array $data
|
||||
* @param int $uid
|
||||
*/
|
||||
public function drawMemberCard(array $data, int $uid)
|
||||
{
|
||||
if (!$uid || !$data) throw new ValidateException('参数缺失!');
|
||||
$isOpenMember = $this->isOpenMemberCardCache();
|
||||
if (!$isOpenMember) throw new ValidateException('会员功能暂未开启!');
|
||||
if (!isset($data['member_card_code']) || !$data['member_card_code']) throw new ValidateException('请输入会员卡号!');
|
||||
if (!isset($data['member_card_code']) || !$data['member_card_pwd']) throw new ValidateException('请输入领取卡密!');
|
||||
$card_info = $this->dao->getOneByWhere(['card_number' => trim($data['member_card_code'])]);
|
||||
if (!$card_info) throw new ValidateException('会员卡不存在!');
|
||||
/** @var MemberCardBatchServices $memberBatchServices */
|
||||
$memberBatchServices = app()->make(MemberCardBatchServices::class);
|
||||
$batch_info = $memberBatchServices->getOne($card_info['card_batch_id']);
|
||||
if (!$batch_info) throw new ValidateException('会员卡未激活,暂无法使用.');
|
||||
if ($batch_info->status != 1) throw new ValidateException('会员卡未激活,暂无法使用..');
|
||||
if ($card_info['status'] == 0) throw new ValidateException('会员卡暂未激活');
|
||||
if ($card_info['card_password'] != trim($data['member_card_pwd'])) throw new ValidateException('会员卡密码有误!');
|
||||
if ($card_info['use_uid'] && $card_info['use_time']) throw new ValidateException('会员卡已使用!');
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user_info = $userServices->getUserInfo($uid);
|
||||
if (!$user_info) throw new ValidateException('用户不存在,请重新登录');
|
||||
if ($user_info->is_money_level > 0 && $user_info->is_ever_level == 1) throw new ValidateException('您已是永久会员,无需再领取,可以将此卡转送亲朋好友,一起享受优惠');
|
||||
|
||||
/**
|
||||
* 批次卡具体使用期限,业务需要打开即可,勿删。
|
||||
*/
|
||||
//if ($batch_info->use_start_time > time()) throw new ValidateException('卡片未在合法有效期内,暂无法使用');
|
||||
//if ($batch_info->use_end_time < time()) throw new ValidateException('卡片已经失效,无法使用');
|
||||
if ($card_info->status != 1) throw new ValidateException('会员卡未激活,暂无法使用...');
|
||||
$this->transaction(function () use ($card_info, $user_info, $batch_info, $memberBatchServices, $userServices, $data) {
|
||||
$res1 = $this->dao->update($card_info->id, ['use_uid' => $user_info->uid, 'use_time' => time(), 'update_time' => time()], 'id');
|
||||
if ($res1) {
|
||||
$res2 = $memberBatchServices->useCardSetInc($batch_info->id, 'use_num', 1);
|
||||
if ($user_info->overdue_time > time()) {
|
||||
$overdue_time = bcadd(bcmul($batch_info->use_day, 86400, 0), $user_info->overdue_time, 0);
|
||||
} else {
|
||||
$overdue_time = bcadd(bcmul($batch_info->use_day, 86400, 0), time(), 0);
|
||||
}
|
||||
$channel_type = $data['from'];
|
||||
/** @var OtherOrderServices $OtherOrderServices */
|
||||
$OtherOrderServices = app()->make(OtherOrderServices::class);
|
||||
$storeOrderCreateService = app()->make(StoreOrderCreateServices::class);
|
||||
$record_data['uid'] = $user_info->uid;
|
||||
$record_data['member_code'] = $card_info->card_number;
|
||||
$record_data['use_day'] = $batch_info->use_day;
|
||||
$record_data['overdue_time'] = $overdue_time;
|
||||
$record_data['order_id'] = $storeOrderCreateService->getNewOrderId();
|
||||
$record_data['channel_type'] = $channel_type;
|
||||
$record_data['member_type'] = "free";
|
||||
$record_data['vip_day'] = $batch_info->use_day;
|
||||
$record_data['type'] = 2;
|
||||
$record_data['paid'] = 1;
|
||||
$record_data['pay_time'] = time();
|
||||
$res3 = $OtherOrderServices->addOtherOrderData($record_data);
|
||||
//if ($res3) $res4 = $userServices->update($user_info->uid, ['level' => 1, 'overdue_time' => $overdue_time, 'is_permanent' => 0], 'uid');
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$res4 = $userServices->setMemberOverdueTime($batch_info->use_day, $user_info->uid, 2, $record_data['member_type']);
|
||||
$res5 = $res1 && $res2 && $res3 && $res4;
|
||||
return $res5;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** 验证是否存在此类型会员卡
|
||||
* @param string $member_type
|
||||
* @return bool
|
||||
*/
|
||||
public function checkmemberType(string $member_type)
|
||||
{
|
||||
$member_type_arr = $this->getMemberTypeInfo();
|
||||
if (!array_key_exists($member_type, $member_type_arr)) throw new ValidateException('暂无此类型会员卡');
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 获取会员权益和说明配置
|
||||
* @return array
|
||||
*/
|
||||
public function getMemberRightsInfo()
|
||||
{
|
||||
/** @var MemberRightServices $memberRightService */
|
||||
$memberRightService = app()->make(MemberRightServices::class);
|
||||
$memberRight = $memberRightService->getSearchList(['status' => 1], ['id', 'right_type', 'title', 'show_title', 'image', 'explain','content', 'number']);
|
||||
if ($memberRight['list']) {
|
||||
foreach ($memberRight['list'] as $k => &$v) {
|
||||
$v['title'] = $v['show_title'];
|
||||
$v['pic'] = $v['image'];
|
||||
unset($v['show_title'], $v['image']);
|
||||
}
|
||||
}
|
||||
return ['member_right' => $memberRight['list']];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员卡配置
|
||||
* @return array
|
||||
*/
|
||||
public function getMemberTypeInfo()
|
||||
{
|
||||
/** @var SystemConfigService $systemConfigService */
|
||||
$systemConfigService = app()->make(SystemConfigService::class);
|
||||
$data = [];
|
||||
foreach (self::$_memberTypePrefix as $v) {
|
||||
$data[$v] = $systemConfigService::more([$v . '_title', $v . '_vip_day', $v . '_pre_price', $v . '_price']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员卡数据处理
|
||||
* @param int $uid
|
||||
* @param bool $is_free
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function DoMemberType(int $uid = 0, bool $is_free = true)
|
||||
{
|
||||
$data = array();
|
||||
/** @var MemberShipServices $memberShipService */
|
||||
$memberShipService = app()->make(MemberShipServices::class);
|
||||
if ($is_free) {
|
||||
$where = [['is_del', '=', 0]];
|
||||
} else {
|
||||
$where = [['is_del', '=', 0], ['type', '<>', 'free']];
|
||||
}
|
||||
$list = $memberShipService->getApiList($where);
|
||||
foreach ($list as $v) {
|
||||
$data[] = [
|
||||
'id' => $v['id'],
|
||||
'title' => $v['title'],
|
||||
'type' => $v['type'],
|
||||
'vip_day' => $v['vip_day'],
|
||||
'pre_price' => $v['pre_price'],
|
||||
'is_label' => $v['is_label'],
|
||||
'price' => $v['price'],
|
||||
'overdue_time' => $memberShipService->getOverdueTime($uid, (int)$v['id'], [], $v, true)
|
||||
];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员类型数据
|
||||
* @return array|bool
|
||||
*/
|
||||
public function getMemberTypeValue(int $uid = 0)
|
||||
{
|
||||
$member_type = $this->DoMemberType($uid);
|
||||
if (!$member_type) return false;
|
||||
foreach ($member_type as $k => $v) {
|
||||
$new_member_data[$v['id']] = $v;
|
||||
}
|
||||
return $new_member_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出会员卡
|
||||
* @param $where
|
||||
* @return array|\think\Collection
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getExportData($where, int $limit = 0)
|
||||
{
|
||||
if ($limit) {
|
||||
[$page] = $this->getPageValue();
|
||||
} else {
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
}
|
||||
$data = $this->dao->getSearchList($where, $page, $limit);
|
||||
if ($data) {
|
||||
/** @var UserServices $userService */
|
||||
$userService = app()->make(UserServices::class);
|
||||
$userInfos = $userService->getColumn([['uid', 'in', array_unique(array_column($data, 'use_uid'))]], 'uid,real_name,nickname,phone', 'uid');
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k]['use_time'] = $v['use_time'] != 0 ? date('Y-m-d H:i:s', $v['use_time']) : "";
|
||||
$data[$k]['user_name'] = '';
|
||||
$data[$k]['user_phone'] = '';
|
||||
$userInfo = $userInfos[$v['use_uid']] ?? [];
|
||||
if ($v['use_uid'] && $userInfo) {
|
||||
$data[$k]['user_name'] = $userInfo['real_name'] ? $userInfo['real_name'] : $userInfo['nickname'];
|
||||
$data[$k]['user_phone'] = $userInfo['phone'];
|
||||
}
|
||||
}
|
||||
}
|
||||
/** @var MemberCardBatchServices $batchService */
|
||||
$batchService = app()->make(MemberCardBatchServices::class);
|
||||
$batchInfo = $batchService->getOne($where['batch_card_id']);
|
||||
$dataArray['title'] = $batchInfo ? $batchInfo['title'] : "";
|
||||
$dataArray['data'] = $data;
|
||||
return $dataArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员记录
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getSearchRecordList(array $where)
|
||||
{
|
||||
/** @var OtherOrderServices $otherOrderSevice */
|
||||
$otherOrderSevice = app()->make(OtherOrderServices::class);
|
||||
return $otherOrderSevice->getMemberRecord($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 看是会员权益时候开启|并返回数据
|
||||
* @param string $rightType
|
||||
* @param bool $get_number
|
||||
* @param int $member_status
|
||||
* @return bool|mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function isOpenMemberCard(string $rightType = '', bool $get_number = true, $member_status = -1)
|
||||
{
|
||||
if ($member_status == -1) {
|
||||
$isOpen = sys_config('member_card_status', 1);
|
||||
} else {
|
||||
$isOpen = $member_status;
|
||||
}
|
||||
//如果传入权益类别,查看是否具有某权益
|
||||
if (!$rightType) {
|
||||
if ($isOpen) return true;
|
||||
return false;
|
||||
} else {
|
||||
if ($isOpen) {
|
||||
/** @var MemberRightServices $memberRightService */
|
||||
$memberRightService = app()->make(MemberRightServices::class);
|
||||
$memberRight = $memberRightService->getOne(['right_type' => $rightType], 'status,number');
|
||||
if ($memberRight && $memberRight['status']) {
|
||||
if ($get_number) {
|
||||
$number = $memberRight['number'];
|
||||
if (!$number) return false;
|
||||
return $number;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 看是会员权益时候开启|并返回数据
|
||||
* @param string $rightType
|
||||
* @param bool $get_number
|
||||
* @param int $member_status
|
||||
* @param int $expire
|
||||
* @return bool|mixed|null
|
||||
* @throws \throwable
|
||||
*/
|
||||
public function isOpenMemberCardCache(string $rightType = '', bool $get_number = true, $member_status = -1, int $expire = 30)
|
||||
{
|
||||
if ($member_status == -1) {
|
||||
$isOpen = sys_config('member_card_status', 1);
|
||||
} else {
|
||||
$isOpen = $member_status;
|
||||
}
|
||||
//如果传入权益类别,查看是否具有某权益
|
||||
if (!$rightType) {
|
||||
if ($isOpen) return true;
|
||||
return false;
|
||||
} else {
|
||||
if ($isOpen) {
|
||||
/** @var MemberRightServices $memberRightService */
|
||||
$memberRightService = app()->make(MemberRightServices::class);
|
||||
$memberRight = $memberRightService->getMemberRightCache($rightType);
|
||||
if ($memberRight && $memberRight['status']) {
|
||||
if ($get_number) {
|
||||
$number = $memberRight['number'];
|
||||
if (!$number) return false;
|
||||
return $number;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改会员卡状态
|
||||
* @param $id
|
||||
* @param $status
|
||||
* @return bool
|
||||
*/
|
||||
public function setStatus($id, $status)
|
||||
{
|
||||
$res = $this->dao->update($id, ['status' => $status]);
|
||||
if ($res) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
174
app/services/user/member/MemberRightServices.php
Normal file
174
app/services/user/member/MemberRightServices.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\member;
|
||||
|
||||
use app\dao\user\member\MemberRightDao;
|
||||
use app\services\BaseServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Class MemberRightServices
|
||||
* @package app\services\user\member
|
||||
* @mixin MemberRightDao
|
||||
*/
|
||||
class MemberRightServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MemberRightDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected MemberRightDao $dao;
|
||||
|
||||
/**
|
||||
* 获取会员权益
|
||||
* @param array $where
|
||||
* @param array $field
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getSearchList(array $where = [], array $field = ['*'])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getSearchList($where, $page, $limit, $field);
|
||||
foreach ($list as &$item) {
|
||||
$item['image'] = set_file_url($item['image']);
|
||||
}
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑保存
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
if (!$data['right_type']) throw new AdminException("会员权益类型缺失");
|
||||
if (!$id) throw new AdminException("id参数缺失");
|
||||
if (!$data['title'] || !$data['show_title']) throw new AdminException("请设置权益名称");
|
||||
if (!$data['image']) throw new AdminException("请上传会员权益图标");
|
||||
switch ($data['right_type']) {
|
||||
case "integral":
|
||||
if (!$data['number']) throw new AdminException("请设置返还积分倍数");
|
||||
if ($data['number'] < 0) throw new AdminException("返还积分倍数不能为负数");
|
||||
$save['number'] = abs($data['number']);
|
||||
break;
|
||||
case "express" :
|
||||
if (!$data['number']) throw new AdminException("请设置运费折扣");
|
||||
if ($data['number'] < 0) throw new AdminException("运费折扣不能为负数");
|
||||
$save['number'] = abs($data['number']);
|
||||
break;
|
||||
case "sign" :
|
||||
if (!$data['number']) throw new AdminException("请设置签到积分倍数");
|
||||
if ($data['number'] < 0) throw new AdminException("签到积分倍数不能为负数");
|
||||
$save['number'] = abs($data['number']);
|
||||
break;
|
||||
case "offline" :
|
||||
if (!$data['number']) throw new AdminException("请设置线下付款折扣");
|
||||
if ($data['number'] < 0) throw new AdminException("线下付款不能为负数");
|
||||
$save['number'] = abs($data['number']);
|
||||
}
|
||||
$save['show_title'] = $data['show_title'];
|
||||
$save['image'] = $data['image'];
|
||||
$save['status'] = $data['status'];
|
||||
$save['sort'] = $data['sort'];
|
||||
$this->dao->update($id, $data);
|
||||
$right = $this->dao->get($id);
|
||||
if ($right) {
|
||||
$this->dao->cacheUpdate($right->toArray());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加权益内容
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function save_content(int $id, array $data)
|
||||
{
|
||||
if (!$id) throw new AdminException("id参数缺失");
|
||||
if (!$data['content']) throw new AdminException("请添加权益内容");
|
||||
$this->dao->update($id, $data);
|
||||
$right = $this->dao->get($id);
|
||||
if ($right) {
|
||||
$this->dao->cacheUpdate($right->toArray());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单条信息
|
||||
* @param array $where
|
||||
* @param string $field
|
||||
* @return array|false|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOne(array $where, string $field = '*')
|
||||
{
|
||||
if (!$where) return false;
|
||||
return $this->dao->getOne($where, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看某权益是否开启
|
||||
* @param $rightType
|
||||
* @return bool
|
||||
*/
|
||||
public function getMemberRightStatus($rightType)
|
||||
{
|
||||
if (!$rightType) return false;
|
||||
$status = $this->dao->value(['right_type' => $rightType], 'status');
|
||||
if ($status) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在缓存中查找权益等级
|
||||
* @param string $rightType
|
||||
* @return false|mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author 等风来
|
||||
* @email 136327134@qq.com
|
||||
* @date 2022/11/10
|
||||
*/
|
||||
public function getMemberRightCache(string $rightType)
|
||||
{
|
||||
$list = $this->dao->cacheList();
|
||||
if ($list === null || (is_array($list) && !$list)) {
|
||||
$list = $this->dao->getSearchList(['status' => 1]);
|
||||
$this->dao->cacheCreate($list);
|
||||
}
|
||||
|
||||
foreach ($list as $item) {
|
||||
if ($rightType == $item['right_type']) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
210
app/services/user/member/MemberShipServices.php
Normal file
210
app/services/user/member/MemberShipServices.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\services\user\member;
|
||||
|
||||
use app\dao\user\member\MemberShipDao;
|
||||
use app\services\BaseServices;
|
||||
use app\services\user\UserServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use think\annotation\Inject;
|
||||
use think\exception\ValidateException;
|
||||
|
||||
/**
|
||||
* Class MemberShipServices
|
||||
* @package app\services\user\member
|
||||
* @mixin MemberShipDao
|
||||
*/
|
||||
class MemberShipServices extends BaseServices
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MemberShipDao
|
||||
*/
|
||||
#[Inject]
|
||||
protected MemberShipDao $dao;
|
||||
|
||||
/**
|
||||
* 获取单个付费会员信息
|
||||
* @param int $id
|
||||
* @param string $field
|
||||
* @return array|\think\Model
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getMemberInfo(int $id, string $field = '*')
|
||||
{
|
||||
$member = $this->dao->getOne(['id' => $id, 'is_del' => 0], $field);
|
||||
if (!$member) {
|
||||
throw new ValidateException('该会员类型不存在或已删除');
|
||||
}
|
||||
return $member;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台获取会员类型
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function getSearchList(array $where = [])
|
||||
{
|
||||
[$page, $limit] = $this->getPageValue();
|
||||
$list = $this->dao->getSearchList($where, $page, $limit);
|
||||
$count = $this->dao->count($where);
|
||||
return compact('list', 'count');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员卡api接口
|
||||
* @return mixed
|
||||
*/
|
||||
public function getApiList(array $where)
|
||||
{
|
||||
return $this->dao->getApiList($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡类型编辑保存
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*/
|
||||
public function save(int $id, array $data)
|
||||
{
|
||||
if (!$data['title']) throw new AdminException("请填写会员名称");
|
||||
if (!$data['type']) throw new AdminException("会员类型缺失");
|
||||
if ($data['type'] == "ever") {
|
||||
$data['vip_day'] = -1;
|
||||
} else {
|
||||
if (!$data['vip_day']) throw new AdminException("请填写体验天数");
|
||||
if ($data['vip_day'] < 0) throw new AdminException("体验天数不能为负数");
|
||||
}
|
||||
if ($data['type'] == "free") {
|
||||
// $data['price'] = 0.00;
|
||||
$data['pre_price'] = 0.00;
|
||||
} else {
|
||||
if ($data['pre_price'] === '' || $data['price'] === '') throw new AdminException("请填写价格");
|
||||
if ($data['pre_price'] == 0 || $data['price'] == 0) throw new AdminException("请填写价格");
|
||||
}
|
||||
if ($data['pre_price'] < 0 || $data['price'] < 0) throw new AdminException("价格不能为负数");
|
||||
if ($data['pre_price'] > $data['price']) throw new AdminException("优惠价不能大于划线价");
|
||||
if ($data['is_label']) {
|
||||
$this->dao->update(['is_label' => 1], ['is_label' => 0]);
|
||||
}
|
||||
if ($id) {
|
||||
$data['id'] = $id;
|
||||
$this->dao->cacheUpdate($data);
|
||||
return $this->dao->update($id, $data);
|
||||
} else {
|
||||
$res = $this->dao->save($data);
|
||||
$data['id'] = $res->id;
|
||||
$this->dao->cacheUpdate($data);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取卡会员天数
|
||||
* @param array $where
|
||||
* @return mixed
|
||||
*/
|
||||
public function getVipDay(array $where)
|
||||
{
|
||||
return $this->dao->value($where, 'vip_day');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改会员类型状态
|
||||
* @param $id
|
||||
* @param $is_del
|
||||
* @return bool
|
||||
*/
|
||||
public function setStatus($id, $is_del)
|
||||
{
|
||||
$res = $this->dao->update($id, ['is_del' => $is_del]);
|
||||
if ($is_del) {
|
||||
$this->cacheDelById($id);
|
||||
} else {
|
||||
$this->cacheSaveValue($id, 'is_del', 0);
|
||||
}
|
||||
if ($res) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会员类型select
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getShipSelect()
|
||||
{
|
||||
$menus = [];
|
||||
foreach ($this->dao->getSearchList(['is_del' => 0], 0, 0, ['id', 'title']) as $menu) {
|
||||
$menus[] = ['value' => $menu['id'], 'label' => $menu['title']];
|
||||
}
|
||||
$menus[] = ['value' => 'card', 'label' => '卡密激活'];
|
||||
$menus[] = ['value' => 'admin', 'label' => '赠送'];
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取过期时间
|
||||
* @param int $uid
|
||||
* @param int $id
|
||||
* @param $userInfo
|
||||
* @param $memberInfo
|
||||
* @return false|string
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getOverdueTime(int $uid, int $id, $userInfo = [], $memberInfo = [], $is_date = false)
|
||||
{
|
||||
if (!$id) {
|
||||
throw new ValidateException('缺少会员ID');
|
||||
}
|
||||
if (!$memberInfo) {
|
||||
/** @var MemberShipServices $memberShipService */
|
||||
$memberShipService = app()->make(MemberShipServices::class);
|
||||
$memberInfo = $memberShipService->get($id);
|
||||
}
|
||||
if (!$memberInfo) {
|
||||
throw new ValidateException('会员卡类型不存在');
|
||||
}
|
||||
if ($uid && !$userInfo) {
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$userInfo = $userServices->getUserCacheInfo($uid);
|
||||
}
|
||||
$member_type = $memberInfo['type'];
|
||||
$vip_day = $memberInfo['vip_day'];
|
||||
if ($member_type == 'ever') {
|
||||
$overdue_time = 0;
|
||||
$is_ever_level = 1;
|
||||
} else {
|
||||
if (!$userInfo || $userInfo['is_money_level'] == 0) {
|
||||
$overdue_time = bcadd(bcmul($vip_day, 86400, 0), time(), 0);
|
||||
} else {
|
||||
$overdue_time = bcadd(bcmul($vip_day, 86400, 0), $userInfo['overdue_time'], 0);
|
||||
}
|
||||
$is_ever_level = 0;
|
||||
}
|
||||
if ($is_ever_level == 1) {
|
||||
$res = "永久会员";
|
||||
} else {
|
||||
$res = $is_date ? date('Y-m-d', $overdue_time) : $overdue_time;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user