2777 lines
92 KiB
PHP
Executable File
2777 lines
92 KiB
PHP
Executable File
<?php
|
||
// +----------------------------------------------------------------------
|
||
// | ShopXO 国内领先企业级B2C免费开源电商系统
|
||
// +----------------------------------------------------------------------
|
||
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
|
||
// +----------------------------------------------------------------------
|
||
// | Licensed ( https://opensource.org/licenses/mit-license.php )
|
||
// +----------------------------------------------------------------------
|
||
// | Author: Devil
|
||
// +----------------------------------------------------------------------
|
||
namespace app\service;
|
||
|
||
use think\facade\Db;
|
||
use app\service\SystemService;
|
||
use app\service\RegionService;
|
||
use app\service\SafetyService;
|
||
use app\service\ResourcesService;
|
||
use app\service\SystemBaseService;
|
||
|
||
/**
|
||
* 用户服务层
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-01T21:51:08+0800
|
||
*/
|
||
class UserService
|
||
{
|
||
// user登录session key
|
||
public static $user_login_key = 'user_login_info';
|
||
public static $user_token_key = 'user_token_data';
|
||
|
||
/**
|
||
* 获取用户登录信息
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2021-12-06
|
||
* @desc description
|
||
* @param [boolean] $is_cache [是否缓存读取]
|
||
*/
|
||
public static function LoginUserInfo($is_cache = true)
|
||
{
|
||
// 静态数据避免重复读取
|
||
static $user_login_info = null;
|
||
if($user_login_info === null)
|
||
{
|
||
// 参数
|
||
$params = input();
|
||
|
||
// 用户数据处理
|
||
if(APPLICATION == 'web')
|
||
{
|
||
// web用户session
|
||
$user_login_info = MyCookie(self::$user_login_key);
|
||
|
||
// 用户信息为空,指定了token则设置登录信息
|
||
if(empty($user_login_info))
|
||
{
|
||
$token = empty($params['token']) ? MyCookie(self::$user_token_key) : $params['token'];
|
||
if(!empty($token))
|
||
{
|
||
$user_login_info = self::UserTokenData($token);
|
||
if(!empty($user_login_info) && isset($user_login_info['id']))
|
||
{
|
||
self::UserLoginRecord($user_login_info['id']);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if(!empty($params['token']))
|
||
{
|
||
$user_login_info = self::UserTokenData($params['token']);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 是否缓存读取
|
||
if(!empty($user_login_info) && !$is_cache)
|
||
{
|
||
// 根据用户id从数据库获取信息并处理
|
||
$user_login_info = self::UserHandle(self::UserInfo('id', $user_login_info['id']));
|
||
if(!empty($user_login_info))
|
||
{
|
||
// 重新更新用户缓存
|
||
self::UserLoginRecord($user_login_info['id']);
|
||
if(!empty($user_login_info['token']))
|
||
{
|
||
MyCache(SystemService::CacheKey('shopxo.cache_user_info').$user_login_info['token'], $user_login_info);
|
||
}
|
||
}
|
||
}
|
||
|
||
return $user_login_info;
|
||
}
|
||
|
||
/**
|
||
* 获取用户token用户数据
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @datetime 2019-08-18T19:01:59+0800
|
||
* @desc description
|
||
* @param [string] $token [用户token]
|
||
*/
|
||
public static function UserTokenData($token)
|
||
{
|
||
$user = MyCache(SystemService::CacheKey('shopxo.cache_user_info').$token);
|
||
if(!empty($user) && isset($user['id']))
|
||
{
|
||
return $user;
|
||
}
|
||
|
||
// 数据库校验
|
||
return self::AppUserInfoHandle(null, 'token', $token);
|
||
}
|
||
|
||
/**
|
||
* 用户状态校验
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2019-02-27
|
||
* @desc description
|
||
* @param [string] $field [条件字段]
|
||
* @param [string] $value [条件值]
|
||
*/
|
||
public static function UserStatusCheck($field, $value)
|
||
{
|
||
// 查询用户状态是否正常
|
||
$user = self::UserInfo($field, $value);
|
||
if(empty($user))
|
||
{
|
||
return DataReturn('用户不存在或已删除', -110);
|
||
}
|
||
if(!in_array($user['status'], [0,1]))
|
||
{
|
||
$common_user_status_list = MyConst('common_user_status_list');
|
||
if(isset($common_user_status_list[$user['status']]))
|
||
{
|
||
return DataReturn($common_user_status_list[$user['status']]['tips'], -110);
|
||
} else {
|
||
return DataReturn('用户状态有误', -110);
|
||
}
|
||
}
|
||
return DataReturn('正常', 0);
|
||
}
|
||
|
||
/**
|
||
* 用户列表
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-06T21:31:53+0800
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function UserList($params = [])
|
||
{
|
||
$where = empty($params['where']) ? [] : $params['where'];
|
||
$field = empty($params['field']) ? '*' : $params['field'];
|
||
$order_by = empty($params['order_by']) ? 'id desc' : trim($params['order_by']);
|
||
$m = isset($params['m']) ? intval($params['m']) : 0;
|
||
$n = isset($params['n']) ? intval($params['n']) : 10;
|
||
|
||
// 获取用户列表
|
||
$data = Db::name('User')->where($where)->order($order_by)->field($field)->limit($m, $n)->select()->toArray();
|
||
return DataReturn(MyLang('common.handle_success'), 0, self::UserListHandle($data, $params));
|
||
}
|
||
|
||
/**
|
||
* 列表数据处理
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2022-08-01
|
||
* @desc description
|
||
* @param [array] $data [数据列表]
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function UserListHandle($data, $params = [])
|
||
{
|
||
if(!empty($data))
|
||
{
|
||
// 用户列表钩子-前面
|
||
$hook_name = 'plugins_service_user_list_handle_begin';
|
||
MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'params' => &$params,
|
||
'data' => &$data,
|
||
]);
|
||
|
||
// 字段列表
|
||
$keys = ArrayKeys($data);
|
||
|
||
// 邀请用户列表
|
||
if(in_array('referrer', $keys))
|
||
{
|
||
$referrer_list = self::GetUserViewInfo(array_column($data, 'referrer'));
|
||
}
|
||
|
||
// 开始处理数据
|
||
$common_gender_list = MyConst('common_gender_list');
|
||
$common_user_status_list = MyConst('common_user_status_list');
|
||
foreach($data as &$v)
|
||
{
|
||
// 生日
|
||
if(array_key_exists('birthday', $v))
|
||
{
|
||
$v['birthday_text'] = empty($v['birthday']) ? '' : date('Y-m-d', $v['birthday']);
|
||
}
|
||
|
||
// 头像
|
||
if(array_key_exists('avatar', $v))
|
||
{
|
||
if(!empty($v['avatar']))
|
||
{
|
||
$v['avatar'] = ResourcesService::AttachmentPathViewHandle($v['avatar']);
|
||
} else {
|
||
$v['avatar'] = SystemBaseService::AttachmentHost().'/static/index/'.strtolower(MyC('common_default_theme', 'default', true)).'/images/default-user-avatar.jpg';
|
||
}
|
||
}
|
||
|
||
// 邀请用户信息
|
||
if(array_key_exists('referrer', $v))
|
||
{
|
||
$v['referrer_info'] = (!empty($referrer_list) && is_array($referrer_list) && array_key_exists($v['referrer'], $referrer_list)) ? $referrer_list[$v['referrer']] : [];
|
||
}
|
||
|
||
// 时间
|
||
if(array_key_exists('add_time', $v))
|
||
{
|
||
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
|
||
}
|
||
if(array_key_exists('upd_time', $v))
|
||
{
|
||
$v['upd_time'] = date('Y-m-d H:i:s', $v['upd_time']);
|
||
}
|
||
|
||
// 性别
|
||
if(array_key_exists('gender', $v))
|
||
{
|
||
$v['gender_text'] = isset($common_gender_list[$v['gender']]) ? $common_gender_list[$v['gender']]['name'] : '未知';
|
||
}
|
||
|
||
// 状态
|
||
if(array_key_exists('status', $v))
|
||
{
|
||
$v['status_text'] = $common_user_status_list[$v['status']]['name'];
|
||
}
|
||
}
|
||
|
||
// 用户列表钩子-后面
|
||
$hook_name = 'plugins_service_user_list_handle_end';
|
||
MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'params' => &$params,
|
||
'data' => &$data,
|
||
]);
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* 用户总数
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-10T22:16:29+0800
|
||
* @param [array] $where [条件]
|
||
*/
|
||
public static function UserTotal($where)
|
||
{
|
||
return (int) Db::name('User')->where($where)->count();
|
||
}
|
||
|
||
/**
|
||
* 用户信息保存
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-10T22:16:29+0800
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function UserSave($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'admin',
|
||
'error_msg' => '管理员信息有误',
|
||
],
|
||
[
|
||
'checked_type' => 'length',
|
||
'key_name' => 'username',
|
||
'checked_data' => '30',
|
||
'is_checked' => 1,
|
||
'error_msg' => '用户名格式最多 30 个字符之间',
|
||
],
|
||
[
|
||
'checked_type' => 'unique',
|
||
'key_name' => 'username',
|
||
'checked_data' => 'User',
|
||
'checked_key' => 'id',
|
||
'is_checked' => 1,
|
||
'error_msg' => '用户已存在[{$var}]',
|
||
],
|
||
[
|
||
'checked_type' => 'length',
|
||
'key_name' => 'nickname',
|
||
'checked_data' => '30',
|
||
'is_checked' => 1,
|
||
'error_msg' => '用户昵称格式最多 30 个字符之间',
|
||
],
|
||
[
|
||
'checked_type' => 'fun',
|
||
'key_name' => 'mobile',
|
||
'checked_data' => 'CheckMobile',
|
||
'is_checked' => 1,
|
||
'error_msg' => '手机号码格式错误',
|
||
],
|
||
[
|
||
'checked_type' => 'fun',
|
||
'key_name' => 'email',
|
||
'checked_data' => 'CheckEmail',
|
||
'is_checked' => 1,
|
||
'error_msg' => '邮箱格式错误',
|
||
],
|
||
[
|
||
'checked_type' => 'in',
|
||
'key_name' => 'gender',
|
||
'checked_data' => array_column(MyConst('common_gender_list'), 'id'),
|
||
'error_msg' => '性别值范围不正确',
|
||
],
|
||
[
|
||
'checked_type' => 'in',
|
||
'key_name' => 'status',
|
||
'checked_data' => array_column(MyConst('common_user_status_list'), 'id'),
|
||
'error_msg' => '状态值范围不正确',
|
||
],
|
||
[
|
||
'checked_type' => 'length',
|
||
'key_name' => 'address',
|
||
'checked_data' => '80',
|
||
'is_checked' => 1,
|
||
'error_msg' => '地址格式最多 80 个字符之间',
|
||
],
|
||
[
|
||
'checked_type' => 'fun',
|
||
'key_name' => 'pwd',
|
||
'checked_data' => 'CheckLoginPwd',
|
||
'is_checked' => 1,
|
||
'error_msg' => '密码格式 6~18 个字符之间',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 更新数据
|
||
$data = [
|
||
'system_type' => empty($params['system_type_name']) ? 'default' : $params['system_type_name'],
|
||
'username' => isset($params['username']) ? $params['username'] : '',
|
||
'nickname' => isset($params['nickname']) ? $params['nickname'] : '',
|
||
'mobile' => isset($params['mobile']) ? $params['mobile'] : '',
|
||
'email' => isset($params['email']) ? $params['email'] : '',
|
||
'address' => isset($params['address']) ? $params['address'] : '',
|
||
'gender' => intval($params['gender']),
|
||
'integral' => intval($params['integral']),
|
||
'locking_integral' => intval($params['locking_integral']),
|
||
'status' => intval($params['status']),
|
||
'alipay_openid' => isset($params['alipay_openid']) ? $params['alipay_openid'] : '',
|
||
'baidu_openid' => isset($params['baidu_openid']) ? $params['baidu_openid'] : '',
|
||
'toutiao_openid' => isset($params['toutiao_openid']) ? $params['toutiao_openid'] : '',
|
||
'toutiao_unionid' => isset($params['toutiao_unionid']) ? $params['toutiao_unionid'] : '',
|
||
'qq_openid' => isset($params['qq_openid']) ? $params['qq_openid'] : '',
|
||
'qq_unionid' => isset($params['qq_unionid']) ? $params['qq_unionid'] : '',
|
||
'weixin_openid' => isset($params['weixin_openid']) ? $params['weixin_openid'] : '',
|
||
'weixin_unionid' => isset($params['weixin_unionid']) ? $params['weixin_unionid'] : '',
|
||
'weixin_web_openid' => isset($params['weixin_web_openid']) ? $params['weixin_web_openid'] : '',
|
||
'kuaishou_openid' => isset($params['kuaishou_openid']) ? $params['kuaishou_openid'] : '',
|
||
'birthday' => empty($params['birthday']) ? 0 : strtotime($params['birthday']),
|
||
'referrer' => empty($params['referrer']) ? 0 : intval($params['referrer']),
|
||
];
|
||
|
||
// 用户保存处理钩子
|
||
$hook_name = 'plugins_service_user_save_handle';
|
||
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'params' => &$params,
|
||
'data' => &$data,
|
||
'user_id' => isset($params['id']) ? intval($params['id']) : 0,
|
||
]));
|
||
if(isset($ret['code']) && $ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
|
||
// 密码
|
||
if(!empty($params['pwd']))
|
||
{
|
||
$data['salt'] = GetNumberCode(6);
|
||
$data['pwd'] = LoginPwdEncryption(trim($params['pwd']), $data['salt']);
|
||
}
|
||
|
||
// 更新/添加
|
||
if(!empty($params['id']))
|
||
{
|
||
// 获取用户信息
|
||
$user = Db::name('User')->where(['id'=>intval($params['id'])])->field('id,integral')->find();
|
||
if(empty($user))
|
||
{
|
||
return DataReturn('用户信息不存在', -10);
|
||
}
|
||
$ret = self::UserUpdateHandle($data, $params['id']);
|
||
if($ret['code'] == 0)
|
||
{
|
||
$user_id = $params['id'];
|
||
}
|
||
} else {
|
||
$data['add_time'] = time();
|
||
$ret = self::UserInsert($data);
|
||
if($ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
$user_id = $ret['data']['user_id'];
|
||
}
|
||
|
||
// 添加用户后处理钩子
|
||
$hook_name = 'plugins_service_user_save_success_handle';
|
||
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'params' => &$params,
|
||
'data' => &$data,
|
||
'user_id' => &$user_id,
|
||
]));
|
||
if(isset($ret['code']) && $ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
|
||
// 状态
|
||
if(isset($user_id))
|
||
{
|
||
if(($data['integral'] > 0 && empty($user)) || (isset($user['integral']) && $user['integral'] != $data['integral']))
|
||
{
|
||
$integral_type = 1;
|
||
$old_integral = 0;
|
||
$opt_integral = 0;
|
||
if(!empty($params['id']))
|
||
{
|
||
$old_integral = $user['integral'];
|
||
$integral_type = ($user['integral'] > $data['integral']) ? 0 : 1;
|
||
$opt_integral = ($integral_type == 1) ? $data['integral']-$user['integral'] : $user['integral']-$data['integral'];
|
||
}
|
||
IntegralService::UserIntegralLogAdd($user_id, $old_integral, $opt_integral, '管理员操作', $integral_type, $params['admin']['id']);
|
||
}
|
||
return DataReturn(MyLang('common.operate_success'), 0);
|
||
}
|
||
return DataReturn(MyLang('common.operate_fail'), -100);
|
||
}
|
||
|
||
/**
|
||
* 用户信息更新
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2022-02-13
|
||
* @desc description
|
||
* @param [array] $data [用户更新信息]
|
||
* @param [int] $user_id [用户id]
|
||
*/
|
||
public static function UserUpdateHandle($data, $user_id)
|
||
{
|
||
$data['upd_time'] = time();
|
||
if(Db::name('User')->where(['id'=>intval($user_id)])->update($data))
|
||
{
|
||
// 更新成功后钩子
|
||
$hook_name = 'plugins_service_user_update_success';
|
||
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'user_id' => $user_id,
|
||
'data' => $data,
|
||
]));
|
||
if(isset($ret['code']) && $ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
return DataReturn(MyLang('common.update_success'), 0);
|
||
}
|
||
return DataReturn(MyLang('common.update_fail'), -100);
|
||
}
|
||
|
||
/**
|
||
* 用户删除
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-10T22:16:29+0800
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function UserDelete($params = [])
|
||
{
|
||
// 参数是否有误
|
||
if(empty($params['ids']))
|
||
{
|
||
return DataReturn('商品id有误', -1);
|
||
}
|
||
// 是否数组
|
||
if(!is_array($params['ids']))
|
||
{
|
||
$params['ids'] = explode(',', $params['ids']);
|
||
}
|
||
|
||
// 删除操作
|
||
if(Db::name('User')->where(['id'=>$params['ids']])->delete())
|
||
{
|
||
return DataReturn(MyLang('common.delete_success'), 0);
|
||
}
|
||
return DataReturn(MyLang('common.delete_fail'), -100);
|
||
}
|
||
|
||
/**
|
||
* 用户登录记录
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2017-03-09T11:37:43+0800
|
||
* @param [int] $user_id [用户id]
|
||
* @return [boolean] [记录成功true, 失败false]
|
||
*/
|
||
public static function UserLoginRecord($user_id = 0)
|
||
{
|
||
if(!empty($user_id))
|
||
{
|
||
$user = self::UserInfo('id', $user_id);
|
||
if(!empty($user))
|
||
{
|
||
// 用户数据处理
|
||
$user = self::UserHandle($user);
|
||
|
||
// 用户登录成功信息纪录钩子
|
||
$hook_name = 'plugins_service_user_login_success_record';
|
||
MyEventTrigger($hook_name, [
|
||
'hook_name' => $hook_name,
|
||
'is_backend' => true,
|
||
'user' => &$user,
|
||
'user_id' => $user_id
|
||
]);
|
||
|
||
// web端设置session
|
||
if(APPLICATION == 'web')
|
||
{
|
||
// 存储session
|
||