新增用户资料修改和头像上传api+其他细节优化

This commit is contained in:
gongfuxiang 2022-11-18 22:30:41 +08:00
parent 8e948dc277
commit 826f07b188
28 changed files with 270 additions and 114 deletions

View File

@ -91,9 +91,6 @@ class User extends Base
{
return $this->error('用户信息不存在', MyUrl('admin/user/index'));
}
// 生日
$data['birthday_text'] = empty($data['birthday']) ? '' : date('Y-m-d', $data['birthday']);
}
// 模板数据

View File

@ -200,11 +200,10 @@ class User
[
'label' => '生日',
'view_type' => 'field',
'view_key' => 'birthday_text',
'view_key' => 'birthday',
'is_sort' => 1,
'search_config' => [
'form_type' => 'date',
'form_name' => 'birthday',
'is_point' => 1,
],
],

View File

@ -1,6 +1,6 @@
<!-- 性别 开始 -->
<div class="am-form-group">
<label>性别<span class="am-form-group-label-tips-must">必选</span></label>
<label>性别</label>
<div>
{{foreach :MyConst('common_gender_list') as $v}}
<label class="am-radio-inline am-margin-right-sm">

View File

@ -164,7 +164,7 @@
<div class="am-u-sm-6 am-padding-horizontal-0">
<div class="am-form-group">
<label>生日</label>
<input type="text" name="birthday" class="am-radius Wdate" placeholder="生日" pattern="{{:MyConst('common_regex_date')}}" data-validation-message="生日格式有误" {{if !empty($data)}} value="{{$data.birthday_text}}" {{/if}} onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" />
<input type="text" name="birthday" class="am-radius Wdate" placeholder="生日" pattern="{{:MyConst('common_regex_date')}}" data-validation-message="生日格式有误" value="{{if !empty($data['birthday'])}}{{$data.birthday}}{{/if}}" onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" />
</div>
</div>
<div class="am-u-sm-6 am-padding-horizontal-0">
@ -209,7 +209,7 @@
{{/if}}
<!-- 插件扩展数据 end -->
<div class="am-form-group am-form-group-refreshing am-margin-top-lg am-padding-left-0">
<div class="am-form-group am-form-group-refreshing am-margin-top-lg am-padding-horizontal-0">
<input type="hidden" name="id" {{if !empty($data)}} value="{{$data.id}}"{{/if}} />
<button type="submit" class="am-btn am-btn-primary am-radius btn-loading-example am-btn-sm am-btn-block" data-am-loading="{loadingText:'处理中...'}">保存</button>
</div>

View File

@ -24,7 +24,7 @@ use app\service\AnswerService;
class Answer extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\BannerService;
class Banner extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\GoodsCartService;
class Cart extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -33,7 +33,7 @@ use app\service\GoodsCartService;
class Index extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\MessageService;
class Message extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\AppHomeNavService;
class Navigation extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -28,7 +28,7 @@ use app\service\ResourcesService;
class Order extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -23,7 +23,7 @@ use app\service\PayRequestLogService;
class OrderNotify extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -0,0 +1,91 @@
<?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\api\controller;
use app\service\ApiService;
use app\service\UserService;
/**
* 用户资料
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-02T22:48:35+0800
*/
class Personal extends Common
{
/**
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-03T12:39:08+0800
*/
public function __construct()
{
// 调用父类前置方法
parent::__construct();
// 是否登录
$this->IsLogin();
}
/**
* 个人资料
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-11-18
* @desc description
*/
public function Index()
{
$data = [
// 用户数据
'data' => UserService::UserHandle(UserService::UserInfo('id', $this->user['id'])),
// 性别
'gender_list' => MyConst('common_gender_list'),
];
return ApiService::ApiDataReturn(DataReturn('success', 0, $data));
}
/**
* 保存
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-11-18
* @desc description
*/
public function Save()
{
$params = $this->data_post;
$params['user'] = $this->user;
return ApiService::ApiDataReturn(UserService::PersonalSave($params));
}
/**
* 用户头像上传
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-03
* @desc description
*/
public function UserAvatarUpload()
{
$params = $this->data_post;
$params['user'] = $this->user;
$params['img_field'] = 'file';
return ApiService::ApiDataReturn(UserService::UserAvatarUpload($params));
}
}
?>

View File

@ -24,7 +24,7 @@ use app\service\RegionService;
class Region extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\SearchService;
class Search extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -34,7 +34,7 @@ use app\service\GoodsCartService;
class User extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -26,7 +26,7 @@ use app\service\ResourcesService;
class UserAddress extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\GoodsBrowseService;
class UserGoodsBrowse extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\GoodsFavorService;
class UserGoodsFavor extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -24,7 +24,7 @@ use app\service\IntegralService;
class UserIntegral extends Common
{
/**
* [__construct 构造方法]
* 构造方法
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1

View File

@ -72,7 +72,7 @@ class Personal extends Common
// 模板数据
$assign = [
// 用户数据
'data' => $this->user,
'data' => UserService::UserHandle(UserService::UserInfo('id', $this->user['id'])),
// 性别
'common_gender_list' => MyConst('common_gender_list'),
// 浏览器名称
@ -95,5 +95,21 @@ class Personal extends Common
$params['user'] = $this->user;
return ApiService::ApiDataReturn(UserService::PersonalSave($params));
}
/**
* 用户头像上传
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-03
* @desc description
*/
public function UserAvatarUpload()
{
$params = $this->data_post;
$params['user'] = $this->user;
$params['img_field'] = 'file';
return ApiService::ApiDataReturn(UserService::UserAvatarUpload($params));
}
}
?>

View File

@ -464,24 +464,5 @@ class User extends Common
]);
return MyView();
}
/**
* 用户头像上传
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-03
* @desc description
*/
public function UserAvatarUpload()
{
// 登录校验
$this->IsLogin();
$params = $this->data_post;
$params['user'] = $this->user;
$params['img_field'] = 'file';
return ApiService::ApiDataReturn(UserService::UserAvatarUpload($params));
}
}
?>

View File

@ -38,7 +38,7 @@
{{if empty($user[$k])}}
<span class="items-value-empty">未填写</span>
{{elseif $k eq 'avatar' /}}
<img src="{{$user[$k]}}" width="50" height="50" />
<img src="{{$user[$k]}}" width="50" height="50" class="am-radius" />
{{else /}}
{{$user[$k]}}
{{/if}}

View File

@ -23,21 +23,53 @@
<div class="user-content">
<div class="user-content-body">
<!-- form start -->
<form class="am-form form-validation" action="{{:MyUrl('index/personal/save')}}" method="POST" request-type="ajax-url" request-value="{{:MyUrl('index/personal/index')}}">
<form class="am-form form-validation am-form-full-screen" action="{{:MyUrl('index/personal/save')}}" method="POST" request-type="ajax-url" request-value="{{:MyUrl('index/personal/index')}}">
<legend>
<span class="am-text-default">个人资料</span>
<a href="{{:MyUrl('index/personal/index')}}" class="am-fr am-text-xs am-margin-top-sm am-icon-mail-reply"> 返回</a>
</legend>
<div class="am-cf">
<div class="am-u-sm-6 am-padding-horizontal-0">
<div class="am-form-group">
<label>昵称</label>
<input type="text" name="nickname" placeholder="昵称" minlength="2" maxlength="16" data-validation-message="昵称 2~16 个字符之间" class="am-radius" {{if !empty($data)}} value="{{$data.nickname}}"{{/if}} required />
<label>昵称<span class="am-form-group-label-tips-must">必填</span></label>
<input type="text" name="nickname" placeholder="昵称" minlength="2" maxlength="16" data-validation-message="昵称2~16个字符之间" class="am-radius" value="{{if !empty($data['nickname'])}}{{$data.nickname}}{{/if}}"required />
</div>
{{include file="lib/gender" /}}
</div>
<div class="am-u-sm-6 am-padding-horizontal-0">
<div class="am-form-group">
<label>生日</label>
<input type="text" name="birthday" class="am-form-field am-radius Wdate" placeholder="生日" data-validation-message="生日格式有误" {{if !empty($data)}} value="{{$data.birthday_text}}"{{/if}} onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" autocomplete="off" />
<input type="text" name="birthday" class="am-form-field am-radius Wdate" placeholder="生日" data-validation-message="生日格式有误" value="{{if !empty($data['birthday'])}}{{$data.birthday}}{{/if}}" onclick="WdatePicker({firstDayOfWeek:1,dateFmt:'yyyy-MM-dd'})" autocomplete="off" />
</div>
<div class="am-form-group am-form-group-refreshing">
</div>
</div>
<div class="am-cf">
<div class="am-u-sm-3 am-padding-horizontal-0">
<div class="am-form-group">
<label>所在省</label>
<input type="text" placeholder="所在省" name="province" data-validation-message="所在省最多30个字符" class="am-radius" value="{{if !empty($data['province'])}}{{$data.province}}{{/if}}" />
</div>
</div>
<div class="am-u-sm-3 am-padding-horizontal-0">
<div class="am-form-group">
<label>所在市</label>
<input type="text" placeholder="所在市" name="city" data-validation-message="所在市最多30个字符" class="am-radius" value="{{if !empty($data['city'])}}{{$data.city}}{{/if}}" />
</div>
</div>
<div class="am-u-sm-3 am-padding-horizontal-0">
<div class="am-form-group">
<label>所在区/县</label>
<input type="text" placeholder="所在区/县" name="county" data-validation-message="所在区/县最多30个字符" class="am-radius" value="{{if !empty($data['county'])}}{{$data.county}}{{/if}}" />
</div>
</div>
<div class="am-u-sm-3 am-padding-horizontal-0">
<div class="am-form-group">
<label>详细地址</label>
<input type="text" placeholder="详细地址" name="address" data-validation-message="详细地址2~30个字符" class="am-radius" value="{{if !empty($data['address'])}}{{$data.address}}{{/if}}" />
</div>
</div>
</div>
{{include file="lib/gender" /}}
<div class="am-form-group am-form-group-refreshing am-margin-top-lg am-padding-horizontal-0">
<button type="submit" class="am-btn am-btn-primary am-radius btn-loading-example am-btn-sm am-btn-block" data-am-loading="{loadingText:'处理中...'}">保存</button>
</div>
</form>

View File

@ -39,7 +39,7 @@
<span data-am-modal-close class="am-close">&times;</span>
</div>
<div class="am-popup-bd">
<form class="am-form form-validation-user-avatar view-save" action="{{:MyUrl('index/user/useravatarupload')}}" method="POST" request-type="ajax-reload" enctype="multipart/form-data">
<form class="am-form form-validation-user-avatar view-save" action="{{:MyUrl('index/personal/useravatarupload')}}" method="POST" request-type="ajax-reload" enctype="multipart/form-data">
<div class="cropper-images-view">
<div class="img-container am-fl user-avatar-img-container">
<img src="{{$attachment_host}}/static/{{$module_name}}/{{$default_theme}}/images/default-user-avatar.jpg" alt="Picture" />

View File

@ -549,11 +549,11 @@ class ConstService
'name' => '性别',
'type' => 'string',
],
'birthday_text'=> [
'birthday' => [
'name' => '生日',
'type' => 'string',
],
'status_text'=> [
'status_text' => [
'name' => '状态',
'type' => 'string',
],

View File

@ -750,10 +750,13 @@ class NavigationService
'nickname' => [
'name' => '昵称'
],
'address_info' => [
'name' => '地址'
],
'gender_text' => [
'name' => '性别'
],
'birthday_text' => [
'birthday' => [
'name' => '生日'
],
'mobile_security' => [

View File

@ -207,7 +207,7 @@ class UserService
// 生日
if(array_key_exists('birthday', $v))
{
$v['birthday_text'] = empty($v['birthday']) ? '' : date('Y-m-d', $v['birthday']);
$v['birthday'] = empty($v['birthday']) ? '' : date('Y-m-d', $v['birthday']);
}
// 头像
@ -371,7 +371,7 @@ class UserService
'province' => empty($params['province']) ? '' : $params['province'],
'city' => empty($params['city']) ? '' : $params['city'],
'county' => empty($params['county']) ? '' : $params['county'],
'address' => isset($params['address']) ? $params['address'] : '',
'address' => empty($params['address']) ? '' : $params['address'],
'gender' => intval($params['gender']),
'integral' => intval($params['integral']),
'locking_integral' => intval($params['locking_integral']),
@ -599,19 +599,25 @@ class UserService
}
if(isset($user['birthday']))
{
$user['birthday_text'] = empty($user['birthday']) ? '' : date('Y-m-d', $user['birthday']);
$user['birthday'] = empty($user['birthday']) ? '' : date('Y-m-d', $user['birthday']);
}
// 邮箱/手机
if(isset($user['mobile']))
{
$user['mobile_security']= empty($user['mobile']) ? '' : mb_substr($user['mobile'], 0, 3, 'utf-8').'***'.mb_substr($user['mobile'], -3, null, 'utf-8');
$user['mobile_security'] = empty($user['mobile']) ? '' : mb_substr($user['mobile'], 0, 3, 'utf-8').'***'.mb_substr($user['mobile'], -3, null, 'utf-8');
}
if(isset($user['email']))
{
$user['email_security'] = empty($user['email']) ? '' : mb_substr($user['email'], 0, 3, 'utf-8').'***'.mb_substr($user['email'], -3, null, 'utf-8');
}
// 地址信息
if(isset($user['province']) && isset($user['city']) && isset($user['county']) && isset($user['address']))
{
$user['address_info'] = $user['province'].$user['city'].$user['county'].$user['address'];
}
// 显示名称,根据规则优先展示
$user['user_name_view'] = isset($user['username']) ? $user['username'] : '';
if(empty($user['user_name_view']) && isset($user['nickname']))
@ -658,31 +664,6 @@ class UserService
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'img_width',
'error_msg' => '图片宽度不能为空',
],
[
'checked_type' => 'empty',
'key_name' => 'img_height',
'error_msg' => '图片高度不能为空',
],
[
'checked_type' => 'isset',
'key_name' => 'img_x',
'error_msg' => '图片裁剪x坐标有误',
],
[
'checked_type' => 'isset',
'key_name' => 'img_y',
'error_msg' => '图片裁剪y坐标有误',
],
[
'checked_type' => 'empty',
'key_name' => 'img_field',
'error_msg' => '图片name字段值不能为空',
],
[
'checked_type' => 'empty',
'key_name' => 'user',
@ -695,6 +676,14 @@ class UserService
return DataReturn($ret, -1);
}
// 缓存key、是否操作频繁
$cache_key = 'cache_user_avatar_upload_frequency_'.$params['user']['id'];
$cache_value = MyCache($cache_key);
if(!empty($cache_value) && $cache_value['time']+3600 > time() && $cache_value['count'] >= 5)
{
return DataReturn('操作频繁,请稍后再试!', -1);
}
// 开始处理图片存储
// 定义图片目录
$root_path = ROOT.'public'.DS;
@ -711,7 +700,14 @@ class UserService
return DataReturn($error, -2);
}
$original = $images_obj->GetCompressCut($_FILES[$params['img_field']], $root_path.$img_path.'original'.$date, 800, 800, $params['img_x'], $params['img_y'], $params['img_width'], $params['img_height']);
// 是否指定裁剪信息
$original_dir = $root_path.$img_path.'original'.$date;
if(!empty($params['img_width']) && !empty($params['img_height']) && isset($params['img_x']) && isset($params['img_y']))
{
$original = $images_obj->GetCompressCut($_FILES[$params['img_field']], $original_dir, 800, 800, $params['img_x'], $params['img_y'], $params['img_width'], $params['img_height']);
} else {
$original = $images_obj->GetOriginal($_FILES[$params['img_field']], $original_dir);
}
if(!empty($original))
{
$compr = $images_obj->GetBinaryCompress($root_path.$img_path.'original'.$date.$original, $root_path.$img_path.'compr'.$date, 200, 200);
@ -719,17 +715,33 @@ class UserService
}
if(empty($compr) || empty($small))
{
return DataReturn('图片有误,请换一张', -3);
return DataReturn('图片有误,请换一张!', -3);
}
$avatar = DS.$img_path.'compr'.$date.$compr;
// 缓存记录
if(empty($cache_value))
{
$cache_value = ['count'=>1, 'time'=>time()];
} else {
$cache_value['count']++;
}
MyCache($cache_key, $cache_value, 3600);
// app则直接返回图片地址
if(APPLICATION == 'app')
{
return DataReturn(MyLang('common.upload_success'), 0, ResourcesService::AttachmentPathViewHandle($avatar));
}
// 更新用户头像
$data = [
'avatar' => DS.$img_path.'compr'.$date.$compr,
'avatar' => $avatar,
'upd_time' => time(),
];
if(Db::name('User')->where(['id'=>$params['user']['id']])->update($data))
{
// 设置session
// web端用户登录纪录处理
self::UserLoginRecord($params['user']['id']);
return DataReturn(MyLang('common.upload_success'), 0);
}
@ -968,7 +980,7 @@ class UserService
$body_html = [];
// 用户登录后钩子
$user = self::UserInfo('id', $user_id, 'id,number_code,system_type,username,nickname,mobile,email,gender,avatar,province,city,birthday');
$user = self::UserInfo('id', $user_id, 'id,number_code,system_type,username,nickname,mobile,email,gender,avatar,province,city,county,birthday');
// 会员码生成处理
if(empty($user['number_code']))
@ -1762,7 +1774,7 @@ class UserService
'checked_type' => 'length',
'checked_data' => '2,16',
'key_name' => 'nickname',
'error_msg' => '昵称 2~16 个字符之间',
'error_msg' => '昵称2~16个字符之间',
],
[
'checked_type' => 'isset',
@ -1792,16 +1804,32 @@ class UserService
'birthday' => empty($params['birthday']) ? '' : strtotime($params['birthday']),
'nickname' => $params['nickname'],
'gender' => intval($params['gender']),
'province' => empty($params['province']) ? '' : $params['province'],
'city' => empty($params['city']) ? '' : $params['city'],
'county' => empty($params['county']) ? '' : $params['county'],
'address' => empty($params['address']) ? '' : $params['address'],
'upd_time' => time(),
];
// 是否存在头像
if(!empty($params['avatar']))
{
$data['avatar'] = ResourcesService::AttachmentPathHandle($params['avatar']);
}
// 更新用户信息
if(Db::name('User')->where(['id'=>$params['user']['id']])->update($data))
{
// 更新用户session数据
// // web端用户登录纪录处理
if(APPLICATION == 'web')
{
self::UserLoginRecord($params['user']['id']);
return DataReturn(MyLang('common.edit_success'), 0);
}
return DataReturn(MyLang('common.edit_fail'), -100);
// 成功并返回用户信息
$user = self::UserHandle(self::UserInfo('id', $params['user']['id']));
return DataReturn(MyLang('common.change_success'), 0, $user);
}
return DataReturn(MyLang('common.change_fail'), -100);
}
/**
@ -1824,6 +1852,7 @@ class UserService
'gender' => empty($params['gender']) ? 0 : intval($params['gender']),
'province' => empty($params['province']) ? '' : $params['province'],
'city' => empty($params['city']) ? '' : $params['city'],
'county' => empty($params['county']) ? '' : $params['county'],
'mobile' => empty($params['mobile']) ? '' : $params['mobile'],
'referrer' => isset($params['referrer']) ? $params['referrer'] : 0,
];
@ -2250,7 +2279,7 @@ class UserService
$body_html = [];
// 注册成功后钩子
$user = self::UserInfo('id', $user_id, 'id,number_code,system_type,username,nickname,mobile,email,gender,avatar,province,city,birthday');
$user = self::UserInfo('id', $user_id, 'id,number_code,system_type,username,nickname,mobile,email,gender,avatar,province,city,county,birthday');
$hook_name = 'plugins_service_user_register_end';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
@ -2337,6 +2366,10 @@ class UserService
'key' => 'city',
'type' => 'string'
],
'county' => [
'key' => 'county',
'type' => 'string'
],
'gender' => [
'key' => 'gender',
'type' => 'int',
@ -2462,6 +2495,10 @@ class UserService
{
$data['city'] = $params['city'];
}
if(empty($mobile_user['county']) && !empty($params['county']))
{
$data['county'] = $params['county'];
}
if(empty($mobile_user) && isset($params['gender']))
{
$data['gender'] = intval($params['gender']);
@ -2704,7 +2741,7 @@ class UserService
}
if(!empty($user_ids))
{
$data = Db::name('User')->where(['id'=>$user_ids])->column('id,number_code,system_type,username,nickname,mobile,email,avatar,province,city', 'id');
$data = Db::name('User')->where(['id'=>$user_ids])->column('id,number_code,system_type,username,nickname,mobile,email,avatar,province,city,county', 'id');
}
// 数据处理