阶段更新

This commit is contained in:
2023-01-12 14:47:38 +08:00
parent 088dd64b2f
commit 5b8901281c
626 changed files with 39326 additions and 12 deletions

View File

@@ -0,0 +1,80 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\User\Models\Account;
use Modules\User\Models\AccountLog;
class AccountController extends AdminController
{
protected $title = '用户账户';
public function grid(): Grid
{
$grid = new Grid(new Account());
$grid->model()->orderByDesc('user_id');
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.info.nickname', '用户昵称');
});
});
$grid->disableActions();
$grid->disableCreateButton();
$grid->model()->with(['user.info']);
$grid->column('user.username', '用户名');
$grid->column('用户昵称')->display(function () {
return $this->user->info->nickname;
});
$grid->column('balance', '余额');
$grid->column('score', '水滴');
// $grid->column('coins');
// $grid->column('other');
$grid->column('updated_at', '更新时间');
$grid->column('账户日志')->display(function () {
return '账户日志';
})->link(function () {
return route('admin.user.account.logs', $this);
}, '_self');
return $grid;
}
public function detail($id): Grid
{
$grid = new Grid(new AccountLog());
$grid->disableCreateButton();
$grid->disableActions();
if (is_numeric($id)) {
$grid->model()->where('account_id', $id);
} else {
$grid->column('用户')
->display(function () {
return $this->account->user->username."({$this->account->user->info->nickname})";
});
}
$grid->column('type', '账户类型');
$grid->column('rule.title', '账变规则');
$grid->column('amount', '账变金额');
$grid->column('balance', '当期余额');
$grid->column('remark', '备注');
$grid->column('source', '详情')->hide();
$grid->column('created_at', '账变时间');
return $grid;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Encore\Admin\Facades\Admin;
use Illuminate\Http\Request;
use Modules\User\Models\User;
class AddUserRemark extends RowAction
{
public $name = '增加备注';
public function handle(User $user, Request $request): Response
{
try {
$user->addLog(Admin::user(), $request->remark);
return $this->response()->success('添加备注成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function form(User $user)
{
$this->textarea('remark', '备注')->required();
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\User\Models\User;
use Modules\User\Models\UserInvite;
class AllotCard extends Action
{
protected $selector = '.report-posts';
public function handle(Request $request)
{
$request->validate([
'startNum' => 'required|integer|min:1|lte:endNum',
'endNum' => 'required|integer|min:1',
], [
'startNum.required' => '开始号码必须填写',
'startNum.integer' => '开始号码必须是整数',
'startNum.min' => '开始号码最小为1',
'startNum.lte' => '开始号码要小于结束号码',
'endNum.required' => '结束号码必须填写',
'endNum.integer' => '结束号码必须是整数',
'endNum.min' => '结束号码最小为1',
]);
$response = $this->response();
$startNum = $request->startNum ?: 0;
$endNum = $request->endNum ?: 0;
$user_id = $request->user_id;
// $startNum = sprintf("%'.08d", $startNum);
// $endNum = sprintf("%'.08d", $endNum++);
$isActive = UserInvite::whereBetween('id', [$startNum, $endNum])->where('status', '!=', 1)->value('code');
if ($isActive) {
$response->status = false;
return $response->error($isActive.'不可分配');
}
UserInvite::whereBetween('id', [$startNum, $endNum])->update([
'user_id' => $user_id,
'status' => UserInvite::STATUS_ALLOT,
]);
return $response->success('卡分配完毕')->refresh();
}
public function form()
{
$users = User::leftJoin('user_infos as info', 'users.id', '=', 'info.user_id')
// ->whereHas('identities', function ($q) {
// $q->where('id', 6);
// })
->select('id', DB::raw('CONCAT(username, " [", info.nickname, "]") as text'))
->pluck('text', 'id');
$this->select('user_id', '会员')
->options($users)
->required();
$this->text('startNum', '开始')->rules('required|integer|min:1');
$this->text('endNum', '结束')->rules('required|integer|min:1');
}
public function html()
{
return "<a class='report-posts btn btn-sm btn-danger'><i class='fa fa-info-circle'></i>分配激活码</a>";
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions\Certification;
use Encore\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;
use Modules\User\Models\UserCertificationConfig;
class ConfigPublish extends RowAction
{
public $name = '使用配置';
public function handle(Model $model)
{
UserCertificationConfig::where('id', '<>', $model->id)->update(['status' => 0]);
$model->status = 1;
$model->save();
return $this->response()->success('发布配置完成')->refresh();
}
public function dialog()
{
$this->confirm('确定使用配置么?');
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions\Certification;
use Encore\Admin\Actions\RowAction;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Replicate extends RowAction
{
public $name = '复制配置';
public function handle(Model $model)
{
try {
DB::transaction(function () use ($model) {
$new = $model->replicate();
$new->status = 0;
$new->save();
});
return $this->response()->success('复制菜单完成')->refresh();
} catch (\Exception $exception) {
return $this->response()->error('复制菜单出错了')->refresh();
}
}
public function dialog()
{
$this->confirm('确定复制配置么?');
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Exception;
use Illuminate\Http\Request;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\User;
class JoinIdentity extends RowAction
{
public $name = '加入身份';
public function handle(User $user, Request $request): Response
{
try {
$identity_id = $request->join_identity_id;
$remark = $request->remark;
$identity = Identity::find($identity_id);
$price = $identity->getCondition('price', '0');
$data = [
'user_id' => $user->id,
'identity_id' => $identity_id,
'year' => 1,
'type' => 1,
'stock' => $identity->stock,
'name' => '',
'card_no' => '',
'cover' => '',
'state' => Order::STATE_INIT,
'price' => $price,
];
$order = Order::create($data);
$order->pay();
//
// $user->joinIdentity($identity_id, 'System', [
// 'remark' => $remark,
// ]);
return $this->response()->success('加入身份成功')->refresh();
} catch (Exception $e) {
return $this->response()->error($e->getMessage())->refresh();
}
}
public function form(User $user)
{
$userIdentity = $user->identityFirst();
if (empty($userIdentity)) {
$identities = Identity::whereIn('order', [2, 3, 4, 5])->pluck('name', 'id');
} elseif ($userIdentity->job == Identity::JOB_YK) {
$identities = Identity::whereIn('order', [2, 3, 4, 5])->pluck('name', 'id');
} else {
$identities = Identity::where('order', '>', $userIdentity->order)->pluck('name', 'id');
}
$this->select('join_identity_id', '加入身份')
->options($identities)
->required();
$this->text('remark', '加入备注');
$this->confirm('确认加入该身份?');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\RowAction;
class LinkJoinCsVip extends RowAction
{
public $name = '开通初始会员';
/**
* @return string
*/
public function href(): string
{
return admin_url('user/'.$this->row->id.'/join');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\User\Models\Order;
class Pay extends RowAction
{
public $name = '已支付';
public function handle(Order $order): Response
{
try {
$order->pay();
return $this->response()->success('支付状态调整成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\User\Models\Order;
class Refund extends RowAction
{
public $name = '退款';
public function handle(Order $order): Response
{
try {
$order->refund();
return $this->response()->success('退款成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Modules\User\Models\Identity;
use Modules\User\Models\IdentityLog;
class RemoveIdentity extends RowAction
{
public $name = '移除身份';
public function handle(Model $user, Request $request): Response
{
try {
$identity_id = $request->remove_identity_id;
$remark = $request->remark;
$user->removeIdentity($identity_id, 'System', [
'remark' => $remark,
]);
$defaultIdentity = Identity::where('default', 1)->first();
if ($defaultIdentity) {
$user->joinIdentity($defaultIdentity->id, IdentityLog::CHANNEL_SYSTEM);
}
return $this->response()->success('移除身份成功')->refresh();
} catch (Exception $e) {
return $this->response()->error($e->getMessage())->refresh();
}
}
public function form(Model $model)
{
$this->select('remove_identity_id', '移除身份')
->options(Identity::whereIn('id', $model->identities()->get()->pluck('id'))
->pluck('name', 'id'))
->required();
$this->text('remark', '移除说明');
$this->confirm('确认移除该身份?');
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Exception;
use Illuminate\Http\Request;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\User;
class SetTag extends RowAction
{
public $name = '设置标签';
public function handle(User $user, Request $request): Response
{
try {
$tag = $request->tag;
$user->update([
'tag' => $tag
]);
return $this->response()->success('加入标签成功')->refresh();
} catch (Exception $e) {
return $this->response()->error($e->getMessage())->refresh();
}
}
public function form(User $user)
{
$this->select('tag', '标签')
->options(User::TAGS)
->required();
$this->confirm('确认加入该标签?');
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
class UpdateRelation extends RowAction
{
public $name = '变更隶属';
public function handle(Model $model, Request $request): Response
{
try {
if ($model->updateParent($request->parent_id)) {
return $this->response()->success('变更成功')->refresh();
} else {
return $this->response()->error('变更失败')->refresh();
}
} catch (Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
public function form()
{
$this->text('parent_id', '目标ID');
$this->confirm('确认变更隶属?');
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\User\Models\User;
class UserStatusInit extends RowAction
{
public $name = '正常';
public function handle(User $user): Response
{
try {
$user->update([
'status' => User::STATUS_INIT
]);
return $this->response()->success('设置成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Actions;
use Encore\Admin\Actions\Response;
use Encore\Admin\Actions\RowAction;
use Modules\User\Models\User;
class UserStatusRefund extends RowAction
{
public $name = '已退费';
public function handle(User $user): Response
{
try {
$user->update([
'status' => User::STATUS_REFUND
]);
return $this->response()->success('设置成功')->refresh();
} catch (\Exception $exception) {
return $this->response()->error($exception->getMessage())->refresh();
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Http\Controllers\Admin\Actions\Certification\ConfigPublish;
use Modules\User\Http\Controllers\Admin\Actions\Certification\Replicate;
use Modules\User\Models\UserCertificationConfig;
class CertificationConfigController extends AdminController
{
protected $title = '认证配置';
protected function grid(): Grid
{
$grid = new Grid(new UserCertificationConfig());
$grid->disableFilter();
$grid->model()->orderBy('id', 'desc');
$grid->actions(function ($action) {
$action->disableView();
$action->add(new Replicate);
if ($this->row->status == 0) {
$action->add(new ConfigPublish);
} else {
$action->disableEdit();
$action->disableDelete();
}
});
$grid->column('id', 'ID');
$grid->column('配置HASH')->display(function () {
return md5($this->created_at);
});
$grid->column('is_open', '开通网络认证')->bool();
$grid->column('is_ocr_open', '开通OCR认证')->bool();
$grid->column('type', '认证类型')
->using(UserCertificationConfig::TYPE)
->label();
$grid->column('status', '状态')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
protected function form(): Form
{
$form = new Form(new UserCertificationConfig());
$states = [
'on' => ['value' => 1, 'text' => '开启', 'color' => 'success'],
'off' => ['value' => 0, 'text' => '关闭', 'color' => 'danger'],
];
$form->switch('is_open', '开通网络认证')->states($states);
$form->switch('is_ocr_open', '开通OCR认证')->states($states);
$form->radioButton('type', '认证类型')
->options(UserCertificationConfig::TYPE)
->required();
$form->password('code', '阿里云code')->help('开启认证时必填');
$form->url('url', '阿里云接口地址')->help('开启OCR认证时必填');
$form->text('ocr_appid', 'OCRAPPID')->help('开启OCR认证时必填');
$form->password('ocr_secretkey', 'OCRSecret')->help('开启OCR认证时必填');
return $form;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\User\Models\UserCertification;
class CertificationController extends AdminController
{
protected $title = '认证记录';
protected function grid(): Grid
{
$grid = new Grid(new UserCertification());
$grid->disableCreateButton();
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '姓名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('id_card', '身份证号');
});
});
$grid->column('id', '#ID#');
$grid->column('name', '姓名');
$grid->column('id_card', '身份证号');
$grid->column('created_at', '申请时间');
return $grid;
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use EasyWeChat\Kernel\Http\StreamResponse;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Support\Facades\Storage;
use Modules\User\Models\UserChannel;
class ChannelController extends AdminController
{
use WithUploads;
protected $title = '渠道管理';
public function grid(): Grid
{
$grid = new Grid(new UserChannel());
$grid->disableFilter();
$grid->column('name', '名称');
$grid->column('code', '渠道码');
$grid->column('mini_path', '小程序地址');
$grid->column('mini_code', '小程序码')->display(function () {
return Storage::url($this->mini_code);
})->image();
$grid->column('official_code', 'h5二维码')->display(function () {
return Storage::url($this->official_code);
})->image();
$grid->column('status', '状态')->bool();
return $grid;
}
protected function form(): Form
{
$form = new Form(new UserChannel());
$form->text('name', '名称')->required();
$this->cover($form);
$form->text('code', '渠道码')->required();
$form->text('mini_path', '小程序路径')->required();
$form->switch('status', '显示')->default(1);
$form->saved(function (Form $form) {
$url = 'channel/code';
$info = $form->model();
//h5
$base64_img = $info->official_code_base64;
preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_img, $res);
$base64_img = base64_decode(str_replace($res[1], '', $base64_img));
$h5Name = 'official_code_'.$info->id.'.png';
$H5path = $url.'/'.$h5Name;
Storage::put($H5path, $base64_img);
$data['official_code'] = $H5path;
//小程序
$app = app('wechat.mini_program');
$arr['channel'] = $info->code;
$str = $info->mini_path.'?'.http_build_query($arr);
$response = $app->app_code->getQrCode($str);
if ($response instanceof StreamResponse) {
$file = $response->saveAs(storage_path('app/public/'.$url), 'mini_code_'.$info->id.'.png');
$data['mini_code'] = $url.'/'.$file;
}
$form->model()->update($data);
});
return $form;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Models\SmsGateway;
class GatewayController extends AdminController
{
protected $title = '短信网关';
public function grid(): Grid
{
$grid = new Grid(new SmsGateway());
$grid->disableFilter();
$grid->column('name', '网关名称');
$grid->column('slug', '网关标识');
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new SmsGateway());
$form->text('name', '网关名称')->required();
$form->text('slug', '网关标识')->required();
$form->keyValue('configs', '网关配置')->value([
'APP_ID' => '',
'APP_SECRET' => '',
'SIGN_NAME' => '',
]);
return $form;
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Form\NestedForm;
use Encore\Admin\Grid;
use Modules\User\Models\Identity;
class IdentitiesController extends AdminController
{
use WithUploads;
protected $title = '用户身份';
public function grid(): Grid
{
$grid = new Grid(new Identity());
$grid->model()->oldest('id')->oldest('order');
$grid->filter(function (Grid\Filter $filter) {
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('name', '身份名称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->select([
0 => '禁用',
1 => '正常',
]);
});
});
$grid->model()->oldest()->withCount('users');
$grid->column('id', '#ID#');
$grid->column('cover', '展示图片')->image('', 40);
$grid->column('name', '身份名称');
$grid->column('order', '排序');
$grid->column('status', '状态')->bool();
$grid->column('serial_open', '是否开启编号')->bool();
$grid->column('serial_places', '编号长度');
$grid->column('serial_prefix', '编号前缀');
$grid->column('years', '有效期(月)')
->display(function () {
return $this->years > 0 ? $this->years : '永久';
});
$grid->column('stock', '送水(箱)');
$grid->column('users_count', '组内用户');
$grid->column('job', '身份')->using(Identity::JOBS)->label();
// $grid->column('total', '可开通总数');
$grid->column('channel', '缴费渠道')
->using(Identity::CHANNELS)
->label([
Identity::CHANNEL_ONLINE => 'primary',
Identity::CHANNEL_OFFLINE => 'success',
]);
foreach (config('identity.conditions') as $key => $title) {
$grid->column($title)->display(function () use ($key) {
return $this->getCondition($key, '无');
});
}
foreach (config('identity.rules') as $key => $title) {
$grid->column($title)->display(function () use ($key) {
return $this->getRule($key, '无');
});
}
$states = [
'on' => ['value' => 1, 'text' => '是', 'color' => 'primary'],
'off' => ['value' => 0, 'text' => '否', 'color' => 'default'],
];
$grid->column('default', '默认身份')->switch($states);
$grid->column('can_buy', '前台开通')->switch($states);
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Identity());
$form->text('name', '身份名称')
->required()
->rules([
'unique:Modules\User\Models\Identity,name,{{id}}',
], [
'unique' => '身份名称已经存在',
]);
$this->cover($form, 'cover', '展示图片');
$form->number('order', '排序')
->required()
->default(0);
$form->textarea('description', '身份简介')
->rules(['max:255'], [
'max' => '简介内容最大不能超过:max个字符',
]);
$form->switch('default', '默认身份')
->default(0);
$form->switch('can_buy', '前台开通')
->help('是否可以在前台开通身份')
->default(0);
$form->number('stock', '库存')
->help('开通身份送多少水')
->default(0);
$form->number('years', '有效期(月)')
->help('0未长期有效')
->default(0);
$form->switch('status', '状态')
->required()
->default(1);
$form->select('serial_open', '是否开启编号')
->options([
false => '关闭',
true => '开启',
])
->required();
$form->number('serial_places', '编号长度')
->rules([
'exclude_if:serial_open,true',
'required',
], [
'required' => '编号开启必填',
]);
$form->text('serial_prefix', '编号前缀');
$form->text('protocol_url', '协议地址')->help('显示开通身份签署的协议');
$form->radioButton('channel', '缴费渠道')
->options(Identity::CHANNELS)
->default(1);
$form->radioButton('job', '身份')
->options(Identity::JOBS)
->default(0)
->when(Identity::JOB_TY, function (Form $form) {
$form->number('total', '可开通总数')->default(100);
$form->date('end_at', '结束日期');
});
$form->divider();
$form->table('conditions', '升级条件', function (NestedForm $form) {
$form->select('name', '条件')
->required()
->options(config('identity.conditions'))
->rules('required');
$form->select('compare', '规则')
->options([
'>' => '大于',
'>=' => '大于等于',
'=' => '等于',
'<' => '小于',
'<=' => '小于等于',
])
->required()
->rules('required');
$form->text('value', '值')
->required()
->rules('required');
});
//
$form->table('rules', '身份权益', function (NestedForm $form) {
$form->select('name', '权益')
->required()
->options(config('identity.rules'))
->rules('required');
$form->select('compare', '规则')
->options([
'>' => '大于',
'>=' => '大于等于',
'=' => '等于',
'<' => '小于',
'<=' => '小于等于',
])
->required()
->rules('required');
$form->text('value', '值')
->required()
->rules('required');
});
$form->table('ruleshows', '身份权益(前台展示)', function (NestedForm $form) {
$form->image('icon', '权益图片');
$form->select('name', '权益')
->options(config('identity.show_rules'))
->required()
->rules('required');
$form->text('value', '值')
->required()
->rules('required');
});
//
$form->table('rights', '可享受权益', function (NestedForm $form) {
$form->text('name', '名称')
->required()
->rules('required');
$form->image('cover', '权益图片');
$form->text('remark', '备注')
->required()
->rules('required');
$form->number('order', '排序');
});
// $form->saving(function ($form) {
//// dd(request()->all());
// });
$form->saved(function ($form) {
$model = $form->model();
if ($model->default == 1) {
Identity::where('id', '!=', $model->id)
->where('default', 1)
->update([
'default' => 0,
]);
}
});
return $form;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\User\Models\IdentityLog;
class IdentityLogController extends AdminController
{
protected $title = '身份变动记录';
public function grid(): Grid
{
$grid = new Grid(new IdentityLog());
$grid->disableActions();
$grid->disableCreateButton();
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.info.nickname', '用户昵称');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('channel', '变更方式')->select(IdentityLog::CHANNEL_MAP);
});
});
$grid->column('user.username', '用户名');
$grid->column('用户昵称')->display(function () {
return $this->user->info->nickname;
});
$grid->column('before_identity.name', '变更前身份')->display(function () {
if ($this->before == 0) {
return '无';
}
return $this->before_identity->name;
});
$grid->column('after_identity.name', '变更后身份')->display(function () {
if ($this->after == 0) {
return '无';
}
return $this->after_identity->name;
});
$grid->column('channel', '变更方式')->using(IdentityLog::CHANNEL_MAP);
$grid->column('remark', '备注');
$grid->column('created_at', '变更时间');
return $grid;
}
}

View File

@@ -0,0 +1,179 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\User\Http\Controllers\Admin\Actions\JoinIdentity;
use Modules\User\Http\Controllers\Admin\Actions\OpenPartner;
use Modules\User\Http\Controllers\Admin\Actions\RemoveIdentity;
use Modules\User\Http\Controllers\Admin\Actions\SetTag;
use Modules\User\Http\Controllers\Admin\Actions\UpdateRelation;
use Modules\User\Models\Identity;
use Modules\User\Models\User;
use Modules\User\Models\UserChannel;
use Vinkla\Hashids\Facades\Hashids;
class IndexController extends AdminController
{
protected $title = '用户管理';
/**
* Notes : 用户管理列表
*
* @Date : 2021/3/11 1:59 下午
* @Author : <Jason.C>
* @return Grid
*/
public function grid(): Grid
{
$grid = new Grid(new User());
if (config('user.create_user_by_admin')) {
$grid->quickCreate(function (Grid\Tools\QuickCreate $create) {
$create->text('username', '用户名')->required();
$create->password('password', '登录密码')->required();
$create->text('info.nickname', '用户昵称')->required();
});
} else {
$grid->disableCreateButton();
}
$grid->actions(function (Grid\Displayers\Actions $actions) {
if (! config('user.edit_user_by_admin')) {
$actions->disableEdit();
}
$actions->disableDelete();
$actions->disableView();
$actions->add(new JoinIdentity());
$actions->add(new RemoveIdentity());
$actions->add(new UpdateRelation());
});
$grid->quickSearch('username')->placeholder('快速搜索用户名');
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('username', '用户名');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('info.nickname', '用户昵称');
$filter->like('identityMiddle.serial', '会员编号(数字)');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('identities.id', '身份')->select(Identity::pluck('name', 'id'));
$filter->equal('parent.username', '推荐人');
});
});
$grid->model()->withCount('addresses')->with(['info', 'parent', 'identities', 'addresses']);
$grid->column('info.avatar', '头像')->image('', 32);
$grid->column('id', '用户ID');
$grid->column('username', '用户名');
$grid->column('info.nickname', '用户昵称');
$grid->column('tag', '标签')
->using(User::TAGS)
->label([
User::TAG_USER => 'primary',
User::TAG_WALKER => 'success',
User::TAG_ACADEMY => 'danger',
]);
// $grid->column('addresses_count', '收货地址')
// ->link(function () {
// return route('admin.mall.addresses.index', ['user_id' => $this->id]);
// }, '_self');
$grid->column('推荐人')->display(function () {
return $this->parent->username ?? '无';
});
$grid->column('identities', '用户身份')
->display(function () {
$data = [];
foreach ($this->identities as $identity) {
$data[] = $identity->name.' : '.$identity->serial_prefix.$identity->getOriginal('pivot_serial');
}
return $data;
})
->label();
// $grid->column('star', '星级')
// ->display(function () {
// $data = [];
// foreach ($this->identities as $identity) {
// $data[] = $identity->getOriginal('pivot_star').' 星';
// }
//
// return $data;
// })
// ->label();
// $grid->column('是否关注')
// ->display(function () {
// return $this->isOfficialSubscribe();
// })
// ->bool();
$grid->column('邀请码')
->display(function () {
return Hashids::connection('code')->encode($this->id);
});
$grid->column('created_at', '注册时间');
return $grid;
}
/**
* Notes : 编辑表单
*
* @Date : 2021/7/15 5:09 下午
* @Author : <Jason.C>
* @return Form
* @throws Exception
*/
public function form(): Form
{
$form = new Form(new User());
if ($form->isCreating() && ! config('user.create_user_by_admin')) {
throw new Exception('不运允许添加用户');
}
if ($form->isCreating() && ! config('user.edit_user_by_admin')) {
throw new Exception('不运允许编辑用户');
}
$form->text('username', '用户名')
->required()
->rules('unique:users,username,{{id}}');
$form->password('password', '登录密码')
->required()
->rules('min:6');
$form->text('info.nickname', '用户昵称');
return $form;
}
/**
* Notes : User 列表选择, 这里没有判断,用户是否已经有店铺了,如果判断的情况,可能导致当前用户 无法被选中
*
* @Date : 2021/5/6 4:35 下午
* @Author : <Jason.C>
*/
public function ajax(Request $request)
{
$q = $request->get('q');
return User::leftJoin('user_infos as info', 'users.id', '=', 'info.user_id')
->where('username', 'like', "%$q%")
->orWhere('info.nickname', 'like', "%$q%")
->select('id', DB::raw('CONCAT(username, " [", info.nickname, "]") as text'))
->paginate();
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Encore\Admin\Widgets\Box;
use Encore\Admin\Widgets\Form;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Modules\User\Http\Controllers\Admin\Actions\AllotCard;
use Modules\User\Models\UserInvite;
use Vinkla\Hashids\Facades\Hashids;
class InviteController extends AdminController
{
protected $title = '激活码管理';
protected function grid()
{
$grid = new Grid(new UserInvite());
$grid->disableCreateButton();
$grid->disableRowSelector();
$grid->disableActions();
$grid->disableColumnSelector();
$grid->tools(function (Grid\Tools $tools) {
$tools->append(new AllotCard());
});
$grid->header(function ($query) {
$form = new Form();
$form->action(admin_url('/users/invites/createCard'));
// $form->hidden('_token')->default(csrf_token());
$form->disableReset();
$form->text('num', '生成数量')->rules('required|integer|min:1');
$box = new Box('生成激活码', $form->render());
$box->collapsable();
$box->style('success');
$box->solid();
return $box->render();
});
$grid->model()->orderBy('id', 'desc');
$grid->column('id', '序号')->sortable();
// $grid->column('number', '编号')->sortable();
$grid->column('归属')->display(function () {
return ($this->user->username ?? '---')."<br>".($this->user->info->nickname ?? '---');
});
$grid->column('code', '激活码');
$grid->column('status', '状态')
->using(UserInvite::STATUS)
->label([
1 => 'warning',
2 => 'success',
3 => 'info',
]);
$grid->column('激活用户')->display(function () {
return ($this->activeUser->username ?? '---')."<br>".($this->activeUser->info->nickname ?? '---');
});
$grid->column('actived_at', '激活时间');
$grid->column('created_at', '创建时间');
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('code', '激活码');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.username', '归属');
});
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('status', '状态')->select(UserInvite::STATUS);
});
});
return $grid;
}
public function createCard(Request $request)
{
$request->validate([
'num' => 'required|integer|min:1',
], [
'num.required' => '数量必须填写',
'num.integer' => '数量必须是整数',
'num.min' => '数量最小为1',
]);
$num = $request->num;
$codeStart = (UserInvite::max('id') ?? 0) + 1;
$data = [];
while ($num > 0) {
$data[] = [
'number' => sprintf("%'.08d", $codeStart++),
'code' => Str::random(14),
'status' => UserInvite::STATUS_INIT,
'created_at' => now(),
'updated_at' => now(),
];
--$num;
}
UserInvite::insert($data);
admin_success('成功生成', $request->num.'个码已经生成。');
return back();
}
}

View File

@@ -0,0 +1,166 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Layout\Content;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as AdminController;
use Illuminate\Support\MessageBag;
use Modules\User\Models\User;
class JoinCsVIpController extends AdminController
{
use HasResourceActions;
/**
* Title for current resource.
*
* @var string
*/
protected $title = '开通初始会员';
/**
* Get content title.
*
* @return string
*/
protected function title(): string
{
return $this->title;
}
/**
* Create interface.
*
* @param Content $content
* @return Content
*/
public function create(Content $content, User $user): Content
{
return $content
->title($this->title())
->description($this->description['create'] ?? trans('admin.create'))
->body($this->form($user));
}
public function form($user): Form
{
$channel = config('account.sms.template.balance');
$form = new Form(new User);
$form->tools(function (Form\Tools $tools) {
// 去掉`列表`按钮
$tools->disableList();
});
$form->display('联名卡会员账户')->default($user->account->drill);
$form->display('用户昵称')->default($user->info->nickname)->readonly();
$form->display('手机号')->default($user->username)->readonly();
$form->select('rule_id', '规则')
->options(function () {
return AccountRule::query()
->whereIn('name', [
'system_drill_in',
])
->get()
->pluck('longname', 'id');
})
->required();
$form->text('mobile', '手机号')
->value(config('account.sms.mobile'))
->disable()
->required();
$form->text('amount', '数值')->required();
$form->hidden('user_id', '用户id')->value($user->id);
$form->text('remark', '备注')->help('告知用户调整原因')->required();
$form->html(view('admin.tools.sms', compact('channel')), '验证码');
$form->setAction('/admin/user/csvip');
return $form;
}
/**
* Notes: 设置积分
*
* @Author: 玄尘
* @Date : 2021/4/26 13:52
* @param \Illuminate\Http\Request $request
*/
public function setIdentity(Request $request)
{
$validator = \Validator::make($request->all(), [
'user_id' => 'required',
'rule_id' => 'required',
'amount' => 'required|integer',
'code' => 'required',
], [
'user_id.required' => '缺少操作的用户',
'rule_id.required' => '缺少规则id',
'amount.required' => '缺少增加/减少的数值',
'amount.integer' => '数值必须是整数',
'code.required' => '缺少短信验证码',
]);
if ($validator->fails()) {
return $this->backErrorMessage($validator->errors()->first());
}
$amount = $request->amount;
$channel = $request->channel ?? config('account.sms.template.default');
$user = User::find($request->user_id);
$res = \Sms::check(config('account.sms.mobile'), $request->code, $channel);
if ($res != true) {
return $this->backErrorMessage('验证码校验失败');
}
$rule = AccountRule::find($request->rule_id);
if (! $rule) {
return $this->backErrorMessage('规则未找到');
}
if (in_array($rule->name, config('account.system_set_score.in'))) {
$res = $user->account->rule($rule->id, $amount, false, [
'expired_at' => now()->addYear(),
'remark' => '后台操作增加余额',
]);
} elseif (in_array($rule->name, config('account.system_set_score.out'))) {
if ($user->account->{$rule->type} < $amount) {
return $this->backErrorMessage('账户余额不足。扣除失败');
}
$res = $user->account->rule($rule->id, -$amount, false, [
'remark' => '后台操作扣除余额',
]);
} else {
return $this->backErrorMessage('规则出错');
}
if ($res === true) {
admin_toastr('操作完成');
return redirect()->to('/admin/users?username='.$user->username);
}
return $this->backErrorMessage('操作失败'.$res);
}
public function backErrorMessage($message)
{
$error = new MessageBag([
'title' => '错误',
'message' => $message,
]);
return back()->withInput()->with(compact('error'));
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Exception;
use Modules\User\Http\Controllers\Admin\Actions\Pay;
use Modules\User\Http\Controllers\Admin\Actions\Refund;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
class OrderController extends AdminController
{
protected $title = '升级订单';
/**
* Notes: 升级订单
*
* @Author: 玄尘
* @Date : 2021/6/7 15:19
* @return Grid
*/
public function grid(): Grid
{
try {
trait_exists('Modules\Payment\Traits\WithPayments');
$grid = new Grid(new Order());
$grid->model()->latest();
$grid->disableCreateButton();
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableEdit();
$actions->disableDelete();
$actions->disableView();
if ($actions->row->canPay()) {
$actions->add(new Pay());
}
if ($actions->row->canRefund()) {
$actions->add(new Refund());
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
$filter->like('user.info.nickname', '用户昵称');
});
$filter->column(1 / 2, function (Grid\Filter $filter) {
$filter->equal('identity.id', '身份')->select(function () {
return Identity::query()->where('order', '>', 1)->pluck('name', 'id');
});
$filter->equal('state', '状态')->select(Order::STATES);
});
});
$grid->column('id', '用户ID');
$grid->column('升级用户')->display(function () {
return $this->user->username."({$this->user->info->nickname})";
});
$grid->column('name', '打款人姓名');
$grid->column('cover', '打款凭证')->gallery(['width' => 60, 'height' => 60]);
$grid->column('identity.name', '开通身份');
$grid->column('price', '应打款额')->editable();
$grid->column('state', '状态')->using(Order::STATES)->label();
$grid->column('type', '类型')->using(Order::TYPES)->label();
$grid->column('coupon', '优惠券')
->display(function () {
if ($this->useCouponLog) {
return $this->useCouponLog->couponGrant->code;
} else {
return '---';
}
});
$grid->column('created_at', '升级时间');
return $grid;
} catch (Exception $exception) {
dd('Payment 模块不存在,无法加载订单数据');
}
}
public function form(): Form
{
$form = new Form(new Order());
$form->decimal('price', '金额')->required();
return $form;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Models\Account;
use Modules\User\Models\AccountRule;
class RuleController extends AdminController
{
protected $title = '账变规则管理';
public function grid(): Grid
{
$grid = new Grid(new AccountRule());
$grid->disableTools();
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableView();
$actions->disableDelete();
});
$grid->column('id', '#ID#');
$grid->column('title', '规则名称');
$grid->column('name', '规则关键字');
$grid->column('type', '规则账户')->using(Account::TYPES);
$grid->column('variable', '固定额度');
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '更新时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new AccountRule());
$form->text('title', '规则名称')->required();
if ($form->isCreating()) {
$form->text('name', '规则关键字')->required();
} else {
$form->text('name', '规则关键字')
->readonly()
->required();
}
$form->select('type', '规则账户')
->options(Account::TYPES)
->required();
$form->number('variable', '固定额度')->default(0);
$states = [
'on' => ['value' => 1, 'text' => '是', 'color' => 'success'],
'off' => ['value' => 0, 'text' => '否', 'color' => 'danger'],
];
$form->switch('deductions', '立即扣款')->states($states);
$form->textarea('remark', '描述')->required();
return $form;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\User\Http\Controllers\Admin\Selectable;
use Closure;
use Encore\Admin\Grid\Filter;
use Encore\Admin\Grid\Selectable;
use Modules\User\Models\Identity;
class Identities extends Selectable
{
public $model = Identity::class;
public static function display(): Closure
{
return function ($value) {
if (is_array($value)) {
return implode(';', array_column($value, 'name'));
}
return optional($this->identities)->name;
};
}
public function make()
{
$this->column('id', '#ID#');
$this->column('name', '身份名称');
$this->column('status', '状态')->bool();
$this->column('created_at', '时间');
$this->filter(function (Filter $filter) {
$filter->like('name', '身份名称');
});
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Http\Controllers\Admin\Selectable\Identities;
use Modules\User\Models\Service;
class ServiceController extends AdminController
{
use WithUploads;
public $title = '客服中心';
public function grid(): Grid
{
$grid = new Grid(new Service());
$grid->disableTools();
$grid->model()->with(['identities']);
$grid->column('id', '#ID#');
$grid->column('name', '姓名');
$grid->column('mobile', '联系方式');
$grid->column('status', '状态')->bool();
$grid->column('identities', '服务身份')
->belongsToMany(Identities::class);
$grid->column('created_at', '创建时间');
$grid->column('updated_at', '更新时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new Service());
$form->text('name', '姓名')->required();
$form->mobile('mobile', '联系方式')->required();
$this->cover($form, 'cover', '客服二维码');
$form->switch('status', '显示')->default(1);
$form->belongsToMany('identities', Identities::class, '服务身份');
return $form;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use App\Admin\Traits\WithUploads;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Models\SignBanner;
use Modules\User\Models\SignChainLog;
class SignBannerController extends AdminController
{
use WithUploads;
protected $title = '签到背景图片';
public function grid(): Grid
{
$grid = new Grid(new SignBanner());
$grid->column('id', '#ID#');
$grid->column('title', '标题');
$grid->column('cover', '封面图')->image('', 100, 100);
$grid->column('status', '状态')->bool();
return $grid;
}
public function form(): Form
{
$form = new Form(new SignBanner());
$form->text('title', '标题')->required();
$this->cover($form);
$form->switch('status', '状态')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Layout\Content;
use Modules\User\Models\SignConfig;
use Encore\Admin\Form\EmbeddedForm;
class SignConfigController extends AdminController
{
protected $title = '签到配置管理';
public function index(Content $content)
{
return redirect(admin_url('users/signs/1/edit'));
}
public function form(): Form
{
SignConfig::firstOrCreate(['id' => 1]);
$form = new Form(new SignConfig());
$form->disableCreatingCheck();
$form->disableEditingCheck();
$form->tools(function (Form\Tools $tools) {
$tools->disableDelete();
$tools->disableView();
$tools->disableList();
});
$form->embeds('params', '配置', function (EmbeddedForm $form) {
$form->radio('open', '是否开启')->options([
0 => '关闭',
1 => '开启',
])->required();
$form->text('rule_name', '签到账变关键字')->default('');
$form->radio('show_type', '签到展示类型')
->options(SignConfig::SHOWTYPES)
->default(SignConfig::SHOWTYPES_DAY)
->required();
$form->radio('type', '签到类型')
->options(SignConfig::TYPES)
->required();
$form->number('single_number', '单次奖励')->default(0);
$form->number('continuous_base', '连续基础值')->default(0);
$form->number('continuous_incremental', '连续增量')->default(0);
$form->number('cycle_day', '周期天数')->default(0);
$form->number('cycle_base', '周期基础值')->default(0);
$form->number('cycle_incremental', '周期增量')->default(0);
});
$form->table('tasks', '特殊奖励', function ($form) {
$form->number('day', '天数')->default(0);
$form->number('number', '奖励')->default(0);
});
return $form;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Models\SignText;
class SignTextController extends AdminController
{
protected $title = '签到展示文字';
public function grid(): Grid
{
$grid = new Grid(new SignText());
$grid->column('id', '#ID#');
$grid->column('title', '标题');
$grid->column('description', '一级描述');
$grid->column('sub_description', '二级描述');
$grid->column('status', '状态')->bool();
return $grid;
}
public function form(): Form
{
$form = new Form(new SignText());
$form->text('title', '标题')->required();
$form->text('description', '一级描述')->required();
$form->text('sub_description', '二级描述')->required();
$form->switch('status', '状态')->default(1);
return $form;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Modules\User\Models\SmsConfig;
use Modules\User\Models\SmsGateway;
class SmsConfigController extends AdminController
{
protected $title = '短信配置';
public function grid(): Grid
{
$grid = new Grid(new SmsConfig());
$grid->disableFilter();
$grid->model()->orderByDesc('in_use');
$grid->column('debug', '调试模式')->bool();
$grid->column('debug_code', '调试验证码');
$grid->column('length', '验证码位数');
$grid->column('expires', '有效期/分钟');
$grid->column('default_gateway', '默认网关');
$grid->column('in_use', '使用中')->bool();
$grid->column('created_at', '创建时间');
return $grid;
}
public function form(): Form
{
$form = new Form(new SmsConfig());
$form->select('default_gateway', '默认网关')->options(function () {
return SmsGateway::pluck('name', 'slug');
})->required();
$form->switch('debug', '调试模式');
$form->text('debug_code', '调试验证码')->setWidth(2)->required();
$form->number('length', '验证码位数')->default(4)->required();
$form->number('expires', '有效期/分钟')->default(5)->required();
$form->keyValue('template', '渠道模板')->value([
'DEFAULT' => '',
'LOGIN' => '',
'REGISTER' => '',
])->required();
$form->switch('in_use', '使用中');
return $form;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\User\Models\Sms;
class SmsController extends AdminController
{
protected $title = '短信记录';
public function grid(): Grid
{
$grid = new Grid(new Sms());
$grid->disableCreateButton();
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->equal('mobile', '接收手机');
});
});
$grid->column('mobile', '接收手机');
$grid->column('channel', '短信渠道');
$grid->column('gateway', '发送网关');
$grid->column('content', '短信内容');
$grid->column('used', '使用')->bool();
$grid->column('created_at', '发送时间');
return $grid;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Grid;
use Modules\User\Models\UserStock;
use Modules\User\Models\UserStockLog;
class StockController extends AdminController
{
protected $title = '会员库存';
/**
* Notes : 用户管理列表
*
* @Date : 2021/3/11 1:59 下午
* @Author : <Jason.C>
* @return Grid
*/
public function grid(): Grid
{
$grid = new Grid(new UserStock());
$grid->disableCreateButton();
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->column(1 / 3, function (Grid\Filter $filter) {
$filter->like('user.username', '用户名');
});
});
$grid->model()->withCount('logs')->with(['user.info']);
$grid->column('user.username', '用户名');
$grid->column('用户昵称')
->display(function () {
return $this->user->info->nickname;
});
$grid->column('stock', '总数');
$grid->column('hold', '提货数')
->link(function () {
return admin_url('/users/stocks/'.$this->id.'/logs');
}, '_blank');
$grid->column('剩余')
->display(function () {
return $this->residue;
});
$grid->column('created_at', '注册时间');
return $grid;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Modules\User\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Modules\Gout\Models\GoutCase;
use Modules\User\Models\UserStock;
use Modules\User\Models\UserStockLog;
class StockLogController extends Controller
{
protected $title = '库存记录';
public function index(Content $content, UserStock $stock)
{
return $content
->header($stock->user->info->nickname)
->description('库存记录')
->body($this->grid($stock));
}
/**
* Notes : 用户管理列表
*
* @Date : 2021/3/11 1:59 下午
* @Author : <Jason.C>
* @return Grid
*/
public function grid($stock): Grid
{
$grid = new Grid(new UserStockLog());
$grid->disableCreateButton();
$grid->disableActions();
$grid->model()->where('user_stock_id', $stock->id)->with(['userStock']);
$grid->column('id', 'ID');
$grid->column('身份')
->display(function () {
if ($this->identity) {
return $this->identity->name;
} else {
return '---';
}
});
$grid->column('type', '类型')
->using(UserStockLog::TYPES)
->label();
$grid->column('variable', '数量');
$grid->column('created_at', '操作时间');
return $grid;
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Modules\User\Http\Controllers\Api\Account;
use App\Api\Controllers\Controller;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\User\Http\Resources\Account\UserAccountLogCollection;
class LogController extends Controller
{
/**
* Notes:水滴
*
* @Author: 玄尘
* @Date: 2022/8/18 13:57
*/
public function score(): \Illuminate\Http\JsonResponse
{
$user = Api::user();
$logs = $user->account->logs()
->where('type', 'score')
->paginate();
$data = [
'score' => $user->account->score,
'logs' => new UserAccountLogCollection($logs)
];
return $this->success($data);
}
/**
* Notes:现金账户
*
* @Author: 玄尘
* @Date: 2022/8/19 8:37
*/
public function balance(): \Illuminate\Http\JsonResponse
{
$user = Api::user();
$logs = $user->account->logs()->where('type', 'balance')->paginate();
$yesterday = $user->account->logs()
->whereDate('created_at', now()->subDay()->toDateTime())
->where('type', 'balance')
->where('amount', '>', 0)
->sum('amount') ?? 0;
$withdraw = $user->withdraws()->sum('amount') ?? 0;
$data = [
'account' => [
'balance' => floatval($user->account->balance),
'yesterday' => floatval($yesterday),
'withdraw' => floatval($withdraw),
],
'logs' => new UserAccountLogCollection($logs)
];
return $this->success($data);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Modules\User\Http\Controllers\Api\Auth;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Http\Requests\LoginRequest;
use Modules\User\Models\User;
class LoginController extends Controller
{
/**
* Notes : 用户名密码登录
*
* @Date : 2021/3/11 5:03 下午
* @Author : <Jason.C>
* @param LoginRequest $request
* @return JsonResponse
*/
public function index(LoginRequest $request): JsonResponse
{
$credentials = [
'username' => $request->username,
'password' => $request->password,
];
$token = Api::attempt($credentials);
if ($token) {
$user = User::where('username', $request->username)->first();
event(new UserLoginSuccess($user, $request, '账号密码'));
return $this->success([
'access_token' => $token,
'token_type' => 'Bearer',
]);
} else {
return $this->failed('用户名或密码错误');
}
}
/**
* Notes : 退出登录,撤销所有令牌,这个需要配合 api:^5.0 使用
*
* @Date : 2021/9/22 11:07 上午
* @Author : <Jason.C>
* @return JsonResponse
*/
public function logout(): JsonResponse
{
$user = Api::user();
if ($user) {
$user->tokens()->delete();
}
return $this->success('');
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\User\Http\Controllers\Api\Auth;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Http\Requests\RegisterRequest;
use Modules\User\Models\User;
class RegisterController extends Controller
{
/**
* Notes : 注册
*
* @Date : 2021/3/14 1:24 下午
* @Author : <Jason.C>
* @param RegisterRequest $request
* @return JsonResponse
*/
public function index(RegisterRequest $request): JsonResponse
{
$username = $request->username;
$password = $request->password;
$user = User::create([
'username' => $username,
'password' => $password,
]);
$token = Api::login($user);
event(new UserLoginSuccess($user, $request, '用户注册'));
return $this->success([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
}

View File

@@ -0,0 +1,132 @@
<?php
namespace Modules\User\Http\Controllers\Api\Auth;
use App\Api\Controllers\Controller;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Facades\Sms;
use Modules\User\Http\Requests\LoginSmsRequest;
use Modules\User\Http\Requests\SmsRequest;
use Modules\User\Models\User;
use Modules\User\Models\UserChannel;
use Vinkla\Hashids\Facades\Hashids;
class SmsController extends Controller
{
/**
* Notes : 获取登录短信验证码
*
* @Date : 2021/5/26 4:59 下午
* @Author : <Jason.C>
* @param SmsRequest $request
* @return JsonResponse
*/
public function send(SmsRequest $request): JsonResponse
{
$mobile = $request->mobileNo;
try {
Sms::sendVerificationCode($mobile);
if (Arr::get(Sms::getConfig(), 'debug')) {
$message = '短信发送成功,测试短信码'.Arr::get(Sms::getConfig(), 'debug_code');
} else {
$message = '短信发送成功';
}
return $this->success($message);
//
// $isExists = User::where('username', $mobile)->exists();
//
// return $this->success([
// 'new' => ! $isExists,
// 'message' => $message,
// ]);
} catch (Exception $exception) {
return $this->failed($exception->getException('aliyun')->getMessage());
}
}
/**
* Notes : 短信验证码登录
*
* @Date : 2021/7/20 10:15 上午
* @Author : <Jason.C>
* @param LoginSmsRequest $request
* @return JsonResponse
*/
public function login(LoginSmsRequest $request): JsonResponse
{
$mobileNo = $request->mobileNo;
$code = $request->code;
$invite_code = $request->invite ?? '';
$channel_code = $request->channel ?? '';//渠道
$name = $request->name ?? '';//姓名
$delivery_code = $request->delivery_code ?? '';//提货码
$channel = '';
if ($channel_code) {
$channel = UserChannel::query()
->where('code', $channel_code)
->first();
}
$parent = 0;
if ($invite_code) {
$invite = Hashids::connection('code')->decode($invite_code);
if (empty($invite)) {
return $this->failed('邀请码不正确');
}
$parent = $invite[0];
}
$check = Sms::checkCode($mobileNo, $code);
if ($check == false) {
return $this->failed('验证码不正确', 422);
}
$user = User::firstOrCreate([
'username' => $mobileNo,
], [
'parent_id' => $parent,
'channel_id' => $channel ? $channel->id : null,
'password' => 111111,
]);
$is_new = $user->wasRecentlyCreated;
$message = '';
if ($is_new) {
if ($user->parent && $parent && $user->parent->id != $parent) {
$message = "您已与用户{$user->parent->info->nickname}绑定隶属关系,此次邀请码无效";
}
}
if ($name) {
$user->info->update([
'nickname' => $name
]);
}
$token = Api::login($user);
event(new UserLoginSuccess($user, $request, '手机验证码'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'message' => $message,
'invite' => Hashids::connection('code')->encode($user->id),
'is_new' => $is_new,
]);
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace Modules\User\Http\Controllers\Api\Auth;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\User\Traits\WechatTrait;
class WechatController extends Controller
{
use WechatTrait;
/**
* Notes: 获取授权的跳转地址
*
* @Author: 玄尘
* @Date : 2021/6/25 13:21
* @param Request $request
* @return mixed
*/
public function getAuthUrl(Request $request)
{
$app = app('wechat.official_account');
$pages = $request->url ?? '';
$scopes = $request->scopes ?? ['snsapi_userinfo'];
$web_url = config('user.web.base');
$redirect = $web_url.$pages;
if (! is_array($scopes)) {
$scopes = [$scopes];
}
$response = $app->oauth->scopes($scopes)->redirect($redirect);
return $this->success($response);
}
/**
* Notes: 获取jssdk
*
* @Author: 玄尘
* @Date : 2021/7/1 11:08
* @param Request $request
* @return JsonResponse
*/
public function getJsSdk(Request $request)
{
$url = $request->url;
$jsApiList = $request->jsApiList ?? [];
$openTagList = $request->openTagList ?? [];
$app = app('wechat.official_account');
if ($url) {
$app->jssdk->setUrl($url);
}
if (! is_array($jsApiList)) {
$jsApiList = [$jsApiList];
}
if (! is_array($openTagList)) {
$openTagList = [$openTagList];
}
return $this->success($app->jssdk->buildConfig($jsApiList, false, false, true, $openTagList));
}
/**
* Notes: 微信分享
*
* @Author: 玄尘
* @Date : 2021/10/26 16:52
* @param Request $request
* @return JsonResponse|mixed
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function officialShare(Request $request)
{
$url = $request->url ?? '';
if (empty($url)) {
return $this->failed('地址必须传');
}
$app = app('wechat.official_account');
$apis = [
'updateAppMessageShareData',
'updateTimelineShareData',
// 'showOptionMenu',
// 'showMenuItems',
'showAllNonBaseMenuItem',
];
$app->jssdk->setUrl($url);
$cog = $app->jssdk->buildConfig($apis);
return $this->success($cog);
}
/**
* Notes: 获取小程序openid
*
* @Author: 玄尘
* @Date: 2022/9/26 14:17
* @return mixed|void
*/
public function getMiniOpenid(Request $request)
{
$validator = \Validator::make($request->all(), [
'code' => 'required',
], [
'code.required' => '缺少参数code',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
$weChat = app('wechat.mini_program');
$session = $weChat->auth->session($request->code);
if (isset($session->errcode)) {
return $this->failed($session->errmsg);
}
return $this->success($session->openid);
}
/**
* Notes: 获取公众号openid
*
* @Author: 玄尘
* @Date: 2022/9/26 14:21
*/
public function getOfficialOpenid()
{
try {
$weUser = $this->getUserFromCode();
return $this->success([
'openid' => $weUser->getId()
]);
} catch (\Exception $exception) {
return $this->failed($exception->getMessage());
}
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace Modules\User\Http\Controllers\Api\Certification;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Jason\Api\Api;
use Modules\User\Http\Requests\CertificationRequest;
use Modules\User\Http\Resources\UserCertificationResource;
use Modules\User\Models\UserCertification;
use Modules\User\Models\UserCertificationConfig;
class IndexController extends Controller
{
public function index()
{
$user = Api::user();
if (! $user->certification) {
return $this->failed('暂无认证记录');
}
return $this->success(new UserCertificationResource($user->certification));
}
/**
* Notes : 判定认证与秘钥
*
* @Date : 2021/5/17 16:52
* @Author : Mr.wang
* @return JsonResponse
*/
public function certified(): JsonResponse
{
$user = Api::user();
if (! $user) {
return $this->success(false);
}
return $this->success((bool) $user->certification);
}
/**
* Notes : 保存认证信息
*
* @Date : 2021/7/20 10:24 上午
* @Author : <Jason.C>
* @param CertificationRequest $request
* @return mixed
*/
public function store(CertificationRequest $request)
{
$user = Api::user();
if ($user->certification) {
return $this->failed('用户已存在认证信息');
}
$keys = [
'name' => $request->name,
'idcard' => $request->id_card,
'front_card' => $request->front_card ?? '',
'back_card' => $request->back_card ?? '',
];
$config = new UserCertificationConfig();
$data = $config->autoVerified($keys);
if ($data['code'] == 1) {
$verified = 1;
} else {
return $this->failed($data['message']);
}
$result = UserCertification::updateOrCreate([
'user_id' => $user->id,
], [
'name' => $request->name,
'id_card' => $request->id_card,
'front_card' => $request->front_card ?? '',
'back_card' => $request->back_card ?? '',
'verified' => $verified,
]);
if ($result) {
$user->info()->update([
'nickname' => $request->name,
]);
return $this->success('操作成功');
} else {
return $this->failed('操作失败');
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Modules\User\Http\Controllers\Api\Favorite;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\Cms\Http\Resources\CategoryCollection;
use Modules\Cms\Models\Article;
use Modules\Cms\Models\Category;
use Modules\User\Http\Resources\Favorite\FavoriteCollection;
class IndexController extends Controller
{
/**
* Notes: 我的收藏
*
* @Author: 玄尘
* @Date: 2022/10/11 11:12
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$user = Api::user();
$category_id = $request->category_id ?? 0;
$favorteArticles = $user->favorites()
->when($category_id, function ($q) use ($category_id) {
$q->whereHasMorph('favoriteable', [Article::class], function ($query) use ($category_id) {
$query->whereHas('categories', function ($q) use ($category_id) {
$q->where('cms_categories.id', $category_id);
});
});
})
->paginate();
$data = [
'categories' => new CategoryCollection(Category::query()->get()),
'favorites' => new FavoriteCollection($favorteArticles),
];
return $this->success($data);
}
}

View File

@@ -0,0 +1,449 @@
<?php
namespace Modules\User\Http\Controllers\Api\Identity;
use App\Api\Controllers\Controller;
use Carbon\Carbon;
use Encore\Admin\Form\Field\Id;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Coupon\Models\Coupon;
use Modules\Coupon\Traits\WithCoupon;
use Modules\User\Http\Resources\IdentityMiddleResource;
use Modules\User\Http\Resources\UserIdentityResource;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\UserInvite;
class IndexController extends Controller
{
use WithCoupon;
/**
* Notes: 获取身份
* type 1 体验官 2 正式身份
*
* @Author: 玄尘
* @Date: 2022/8/11 10:52
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$type = $request->type ?? '';
$user = Api::user();
$list = Identity::where('order', '>', 1)->where('can_buy', 1)->get();
$data = [
'user' => [
'username' => $user->username,
'nickname' => $user->info->nickname,
'avatar' => $user->info->avatar,
'identity' => $user->identities->count()
? new IdentityMiddleResource($user->identityMiddle()->first())
: '',
],
'identities' => UserIdentityResource::collection($list),
];
return $this->success($data);
}
/**
* Notes: 获取可开通的身份
*
* @Author: 玄尘
* @Date : 2021/6/4 9:37
* @param Identity $identity
* @return JsonResponse
*/
public function create(Identity $identity): JsonResponse
{
$user = Api::user();
$ended_at = '';
//可开通的身份ids
$ids = Identity::where('can_buy', 1)->pluck('id')->toArray();
$identity_middles = $user->identityMiddle;
//是否可以前台开通
if (in_array($identity->id, $ids)) {
//有有效期
if ($identity->years) {
//已经开通的身份ids
$identity_ids = $identity_middles->pluck('identity_id')->toArray();
//是否已经开通了此身份
if (in_array($identity->id, $identity_ids)) {
$ended_at = $identity_middles->where('identity_id', $identity->id)
->first()->ended_at ?? now()->format('Y-m-d H:i:s');
$ended_at = Carbon::parse($ended_at)->addMonths($identity->years)->format('Y/m/d');
} else {
$ended_at = now()->addMonths($identity->years)->format('Y/m/d');
}
} else {
$ended_at = '永久';
}
}
// $price = $identity->getCondition('price', '0');
// if ($identity->job == Identity::JOB_JK) {
// $coupon =
// }
$price = $identity->getCondition('price', '0');
$cost = $identity->getCondition('cost', '0');
if (! $cost) {
$cost = $price;
}
$coupon_price = 0;
$data = [
'identity' => [
'identity_id' => $identity->id,
'name' => $identity->name,
'cover' => $identity->cover_url,
'description' => $ended_at ? '有效期至'.$ended_at : $identity->description,
'coupon_price' => $coupon_price,
'cost' => $cost,
'price' => $price,
'can_buy' => (bool) $identity->can_buy,
'ended_at' => $ended_at,
'service' => config('user.experience.service'),
'protocol_url' => (string) $identity->protocol_url,//协议地址
],
];
return $this->success($data);
}
/**
* Notes: 开通会员
*
* @Author: 玄尘
* @Date : 2021/6/4 10:02
* @param Identity $identity
* @param Request $request
* @return JsonResponse
*/
public function store(Identity $identity, Request $request): JsonResponse
{
$user = Api::user();
$price = $request->price ?? 0;
if ($identity->job != Identity::JOB_TY) {
$validator = Validator::make($request->all(), [
'name' => 'required',
// 'card_no' => 'required|numeric',
'cover' => 'required',
'price' => 'required',
], [
'name.required' => '缺少姓名',
'card_no.required' => '缺少银行卡号',
'card_no.numeric' => '银行卡号只能是数字',
'cover.required' => '缺少打款凭证',
'price.required' => '缺少打款金额',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
// if ($identity->job == Identity::JOB_NK && ! $user->parent) {
// return $this->failed('没有推荐人不可开通年卡会员');
// }
} else {
$total = $identity->users()->count();
if ($total >= 100) {
return $this->failed('体验官最多可开通100人');
}
$end_at = $identity->end_at;
if ($end_at) {
$end_at = Carbon::parse($end_at)->endOfDay();
if (now()->gt($end_at)) {
return $this->failed('体验官活动已过期');
}
}
$tencentMap = app('xuanchen.tencent.map');
$res = $tencentMap->api()->ip(request()->ip())->toArray();
if (! in_array($res['ad_info']['city'], ['深圳', '深圳市'])) {
// return $this->failed('体验官活动只限于深圳用户参加');
}
}
if (! $identity->can_buy) {
return $this->failed('当前身份不可开通,请联系客服开通。');
}
$type = Order::TYPE_OPEN;
$year = $request->year ?? 1;
//是否可以开通多身份 false不可
if (config('identity.can_has_many_identity') == false) {
if ($user->identities->isNotEmpty()) {
$this_identity = $user->identities->first();
if ($this_identity->order > $identity->order) {
return $this->failed('不可降级开通');
}
if ($this_identity->id == $identity->id) {
$type = Order::TYPE_RENEW;
}
}
}
if (in_array($identity->job, [Identity::JOB_JK, Identity::JOB_NK])) {
$hasOne = Order::query()
->byUser($user)
->where('identity_id', $identity->id)
->where('state', Order::STATE_INIT)
->exists();
if ($hasOne) {
return $this->failed('您已经提交过了,请等待审核');
}
}
if (! $price) {
$price = $identity->getCondition('price', '0');
$price = $price * $year;
}
$coupon_price = 0;
$data = [
'user_id' => $user->id,
'identity_id' => $identity->id,
'year' => $year,
'type' => $type,
'stock' => $identity->stock,
'name' => $request->name,
'card_no' => $request->card_no,
'cover' => $request->cover,
'state' => Order::STATE_INIT,
'price' => $price,
];
$order = Order::create($data);
if ($order) {
return $this->success('提交成功,请等待后台审核');
} else {
return $this->failed('创建订单失败,请稍后再试');
}
}
/**
* Notes: 微信支付
*
* @Author: 玄尘
* @Date : 2021/6/7 14:42
* @param Order $order
* @param Request $request
* @return JsonResponse
* @throws Exception
*/
public function wechat(Order $order, Request $request): JsonResponse
{
$channel = $request->channel ?? 'mp';
$openid = $request->openid ?? '';
$user = Api::user();
if (! $order->canPay()) {
return $this->failed('支付失败,订单不可支付');
}
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
$extends = [
'notify_url' => route('api.payment.notify.wechat'),
];
if (! $openid) {
$openid = $user->wechat->getUserOpenid($channel);
}
$payment = $order->createWechatPayment($user, $order->price, $channel);
if (! $openid) {
return $this->failed('支付失败缺少openid');
}
if (config('payment.version', 2) == 2) {
$extends = array_merge($extends, [
'openid' => $openid,
]);
} else {
$extends = array_merge($extends, [
'payer' => [
'openid' => $openid,
],
]);
}
$notify = $payment->getPaymentParams('商品下单', $extends);
if (config('payment.version', 2) == 2) {
$notify = $notify->getContent();
} else {
$notify = $notify->toJson();
}
$data = [
'wechat' => $notify,
'identity' => [
'identity_id' => $order->identity_id,
'name' => $order->identity->name,
],
];
return $this->success($data);
}
/**
* Notes: 支付宝支付
*
* @Author: 玄尘
* @Date : 2021/6/7 14:42
* @param Order $order
* @return JsonResponse
* @throws Exception
*/
public function alipay(Order $order): JsonResponse
{
$user = Api::user();
if (! $order->canPay()) {
return $this->failed('支付失败,订单不可支付');
}
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
$payment = $order->createAlipayPayment($user, $order->price, 'app');
$notify = $payment->getPaymentParams('商品下单', [
'notify_url' => route('api.payment.notify.alipay'),
]);
$data = [
'wechat' => $notify->getContent(),
'identity' => [
'identity_id' => $order->identity_id,
'name' => $order->identity->name,
],
];
return $this->success($data);
}
/**
* Notes: 根据不同身份判定用户折扣
*
* @Author: Mr.wang
* @Date : 2021/6/10 11:00
* @return JsonResponse
*/
public function rule(): JsonResponse
{
$user = Api::user();
$defaultIdentity = Identity::orderBy('order', 'desc')->first();
$defaultDiscount = $defaultIdentity->getRule('buy_discount', 0);
if (! $user) {
return $this->success([
'message' => '开通节点 最高享'.($defaultDiscount / 10).'折优惠',
'not_vip' => true,
'discount' => $defaultDiscount / 100,
]);
}
$identity = $user->identities->first();
$discount = $identity->getRule('buy_discount', 0);
if ($discount >= 100) {
$message = '开通节点 最高享'.($defaultDiscount / 10).'折优惠';
} else {
$message = $identity->name.'尊享'.($discount / 10).'折优惠';
}
return $this->success([
'message' => $message,
'not_vip' => (bool) $identity->default,
'discount' => $discount / 100,
]);
}
/**
* Notes: 获取身份权益
*
* @Author: 玄尘
* @Date : 2021/6/8 8:39
* @param Identity $identity
* @return JsonResponse
*/
public function show(Identity $identity): JsonResponse
{
return $this->success(new UserIdentityResource($identity));
}
/**
* Notes: 激活码激活
*
* @Author: 玄尘
* @Date: 2022/9/21 10:06
* @param Order $order
* @param Request $request
* @return JsonResponse|mixed
*/
public function invite(Order $order, Request $request)
{
$code = $request->code;
$user = Api::user();
info($user->id);
if (! $order->canPay()) {
return $this->failed('支付失败,订单不可支付');
}
info($order->toJson());
if ($order->user()->isNot($user)) {
return $this->failed('支付失败,您没有权限支付');
}
$invite = UserInvite::where('code', $code)->first();
if (! $invite) {
return $this->failed('未找到激活码信息');
}
if ($invite->status != UserInvite::STATUS_ALLOT) {
return $this->failed('激活码状态不对');
}
try {
$order->pay();
$invite->use($user->id);
return $this->success('激活成功');
} catch (\Exception $exception) {
return $this->failed($exception->getMessage());
}
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace Modules\User\Http\Controllers\Api\Identity;
use App\Api\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Mall\Http\Resources\Api\Activity\ActivityBaseResource;
use Modules\Mall\Http\Resources\Api\Activity\ActivityResource;
use Modules\Mall\Models\Activity;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
class PartnerController extends Controller
{
/**
* Notes: 开通合伙人
*
* @Author: 玄尘
* @Date: 2022/8/4 15:21
* @return JsonResponse
*/
public function create(): JsonResponse
{
$user = Api::user();
$activity = Activity::find(2);
$activityInfo = $activity ? new ActivityResource($activity) : [];
$text = '开通合伙人';
$order = Order::ByUser($user)->where('identity_id', 0)->first();
$value = true;
if ($order) {
$value = false;
if ($order->state == Order::STATE_INIT) {
$text = '等待审核';
} else {
$text = '您已开通';
}
}
$data = [
'activity' => $activityInfo,
'status' => [
'value' => $value,
'text' => $text,
]
];
return $this->success($data);
}
/**
* Notes: 开通会员
*
* @Author: 玄尘
* @Date : 2021/6/4 10:02
* @param Request $request
* @return JsonResponse
*/
public function store(Request $request): JsonResponse
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'card_no' => 'required|numeric',
'cover' => 'required',
], [
'name.required' => '缺少姓名',
'card_no.required' => '缺少银行卡号',
'card_no.numeric' => '银行卡号只能是数字',
'cover.required' => '缺少打款凭证',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
$user = Api::user();
$data = [
'user_id' => $user->id,
'identity_id' => 0,
'year' => 1,
'type' => 1,
'name' => $request->name,
'card_no' => $request->card_no,
'cover' => $request->cover,
'state' => Order::STATE_INIT,
'price' => 0,
];
$order = Order::create($data);
if ($order) {
return $this->success('提交成功,请等待后台审核');
} else {
return $this->failed('创建订单失败,请稍后再试');
}
}
}

View File

@@ -0,0 +1,198 @@
<?php
namespace Modules\User\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\User\Http\Resources\UserInfoBaseResource;
use Modules\User\Http\Resources\UserInfoResource;
use Vinkla\Hashids\Facades\Hashids;
use Illuminate\Support\Facades\Config;
class IndexController extends Controller
{
/**
* Notes : 用户主页信息
*
* @Date : 2021/3/11 5:45 下午
* @Author : <Jason.C>
* @return JsonResponse
*/
public function index(): JsonResponse
{
$user = Api::user();
return $this->success(new UserInfoResource($user));
}
/**
* Notes : 用户信息
*
* @Date : 2021/6/16 2:14 下午
* @Author : Mr.wang
* @return JsonResponse
*/
public function info(): JsonResponse
{
$user = Api::user();
return $this->success(new UserInfoBaseResource($user));
}
/**
* Notes : 用户基础信息修改
*
* @Date : 2021/5/27 14:02
* @Author : Mr.wang
* @param Request $request
* @param string $key
* @return JsonResponse
*/
public function update(Request $request, string $key): JsonResponse
{
$user = Api::user();
switch ($key) {
case 'nickname':
$validator = Validator::make($request->all(), [
'value' => 'required',
], [
'value.required' => '用户昵称必须填写',
]);
break;
case 'avatar':
$validator = Validator::make($request->all(), [
'value' => ['required', 'regex:/[^\s]*\.(jpg|jpeg|gif|png)$/i'],
], [
'value.required' => '用户头像必须上传',
'value.regex' => '头像地址格式不正确',
]);
break;
default:
return $this->failed('路径不合法');
}
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$result = $user->info()->update([$key => $request->value]);
if ($result) {
return $this->success('操作成功');
} else {
return $this->failed('失败');
}
}
/**
* Notes : 用户邀请码接口
*
* @Date : 2021/5/27 14:15
* @Author : Mr.wang
* @return JsonResponse
*/
public function invite(): JsonResponse
{
$user = Api::user();
$invite = Hashids::connection('code')->encode($user->id);
$url = Config::get('user.invite_code.url').'?invite='.$invite;
$code = 'data:image/png;base64,'.base64_encode(QrCode::format('png')
->size(100)
->margin(3)
->generate($url));
return $this->success([
'code' => $code,
'invite' => $invite,
'children' => $user->children()->count(),
'user_info' => new UserInfoBaseResource($user),
]);
}
/**
* Notes: 获取小程序码
*
* @Author: 玄尘
* @Date: 2022/9/28 13:13
*/
public function getMiniCode(Request $request)
{
$user = Api::user();
$size = $request->size ?? '300';
$url = $request->url ?? 'pages/mall/index/index';
$name = "share_user_mini_{$user->id}.png";
$path = "share/".$name;
$file_path = storage_path("app/public/".$path);
$data = [
'username' => $user->username,
'nickname' => $user->info->nickname ?? '',
'avatar' => $user->info->avatar ?? '',
];
$invite = Hashids::connection('code')->encode($user->id);
$parse = parse_url($url);
$arr['invite'] = $invite;
$str = $parse['path'].'?'.http_build_query($arr);
if (! file_exists($file_path)) {
$app = app('wechat.mini_program');
$response = $app->app_code
->get($str, [
'width' => $size,
'is_hyaline' => true,
]);
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
$response->saveAs(storage_path("app/public/share"), $name);
}
}
$data = array_merge($data, [
'qrcode' => Storage::url($path),
]);
return $this->success($data);
}
/**
* Notes : 绑定邀请码
*
* @Date : 2021/7/20 10:30 上午
* @Author : wang
* @param Request $request
* @return JsonResponse
*/
public function bind(Request $request): JsonResponse
{
$invite = $request->invite ?? '';
if (empty($invite)) {
return $this->failed('邀请码不能为空');
}
$invite = Hashids::connection('code')->decode($invite);
if (empty($invite)) {
return $this->failed('邀请码不正确');
}
$user = Api::user();
if ($user->parent) {
return $this->failed('用户已有上级,不能重复绑定');
}
if ($user->updateParent($invite[0])) {
return $this->success('绑定成功');
} else {
return $this->failed('绑定失败');
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\User\Http\Controllers\Api\Invite;
use App\Api\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Mall\Http\Resources\Api\Activity\ActivityBaseResource;
use Modules\Mall\Http\Resources\Api\Activity\ActivityResource;
use Modules\Mall\Models\Activity;
use Modules\User\Http\Resources\Invite\UserInviteCollection;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
use Modules\User\Models\UserInvite;
use Modules\User\User;
class IndexController extends Controller
{
/**
* Notes: 邀请码列表
*
* @Author: 玄尘
* @Date: 2022/9/21 9:55
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request)
{
$status = $request->status ?? 1;
$lists = UserInvite::query()
->ByUser(Api::user())
->where('status', $status)
->paginate();
return $this->success(new UserInviteCollection($lists));
}
}

View File

@@ -0,0 +1,109 @@
<?php
namespace Modules\User\Http\Controllers\Api\Rank;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\OrderItem;
use Modules\User\Models\User;
use Modules\User\Traits\RankDataTrait;
class IndexController extends Controller
{
use RankDataTrait;
/**
* Notes: 总排行
*
* @Author: 玄尘
* @Date: 2022/8/17 15:10
* @param Request $request
* @return JsonResponse
*/
public function total(Request $request): JsonResponse
{
$dateBetween = [
'2022-06-01 00:00:00',
now()->toDateTimeString(),
];
$vipUsers = $this->getRankDataTrait($dateBetween);
$data = [];
$i = 1;
foreach ($vipUsers as $user) {
$data[] = [
'rank' => $i,
'avatar' => $user->info->avatar, //头像
'nickname' => $user->info->nickname,
'rate' => '-',
'number' => $user->countChild,
];
}
return $this->success([
'page_id' => 6,
'rand' => $data
]);
}
/**
* Notes: 功德榜
*
* @Author: 玄尘
* @Date: 2022/12/31 18:23
*/
public function merit()
{
$users = $this->getAllUserJz();
return $this->success($users);
}
/**
* Notes: 推荐用户总排行
*
* @Author: 玄尘
* @Date: 2022/8/17 15:11
* @return JsonResponse
*/
public function totalUser(): JsonResponse
{
$user = Api::user();
$users = User::query()
->withCount('children')
->take(10)
->latest('children_count')
->oldest('id')
->get()
->where('children_count', '>', 0)
->map(function ($info) use ($user) {
$children_count = $info->children_count;
return [
'user' => [
'user_id' => $info->id,
'username' => substr_replace($info->username, '****', -4, 4),
'nickname' => $info->info->nickname_text ?? '',
'avatar' => $info->info->avatar ?? '',
],
'total' => $children_count > 0 ? $children_count : '-',
];
})
->pad(10, [
'user' => [
'user_id' => 0,
'username' => '-',
'nickname' => '-',
'avatar' => '-',
],
'total' => '-',
]);
$users = $users->toArray();
return $this->success($users);
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Modules\User\Http\Controllers\Api\Relation;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\User\Http\Resources\RelationResource;
use Modules\User\Models\Relation;
class IndexController extends Controller
{
/**
* Notes: 我的下级
*
* @Author: 玄尘
* @Date : 2021/9/24 15:05
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request): JsonResponse
{
$layer = $request->larer ?? 1;
$user = Api::user();
$layer = bcadd($user->relation->layer, $layer);
$users = Relation::query()
->where('bloodline', 'like', "%,".$user->id.",%")
->when($layer, function ($q) use ($layer) {
$q->where('layer', $layer);
}, function ($q) {
$q->whereIn('layer', [2, 3]);
})
->paginate();
$data = [
'count' => $user->getRelationCount(),
'users' => RelationResource::collection($users),
];
return $this->success($data);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\User\Http\Controllers\Api\Service;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Jason\Api\Api;
use Modules\User\Http\Resources\UserServiceResource;
use Modules\User\Models\Identity;
class IndexController extends Controller
{
public function index(Request $request): JsonResponse
{
$identityId = $request->identity_id ?? 0;
if ($identityId) {
$identity = Identity::findOrFail($identityId);
$service = $identity->identities()->shown()->inRandomOrder()->first();
} else {
$user = Api::user();
$service = $user->identities->first()->identities()->shown()->inRandomOrder()->first();
}
if (empty($service)) {
return $this->success([]);
}
return $this->success(new UserServiceResource($service));
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace Modules\User\Http\Controllers\Api\Setting;
use App\Api\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\User\Models\UserWechat;
class IndexController extends Controller
{
/**
* Notes : 设置页面展示
*
* @Date : 2021/8/27 14:42
* @Author : Mr.wang
* @return JsonResponse
*/
public function index(): JsonResponse
{
$user = Api::user();
$wechat = UserWechat::where('user_id', $user->id)->first();
if ($wechat) {
if ($wechat->mini) {
$bool = true;
} else {
$bool = false;
}
} else {
$bool = false;
}
return $this->success([
'avatar' => $user->info->avatar ?? '',
'nickname' => $user->info->nickname ?? '',
'is_bind' => $bool,
'certification' => [
'is_true' => (bool) $user->certification,
'message' => $user->certification ? [
'name' => $user->certification->name,
'idcard' => $user->certification->id_card,
] : [],
],
]);
}
/**
* Notes : 用户基础信息修改
*
* @Date : 2021/5/27 14:02
* @Author : Mr.wang
* @param Request $request
* @param string $key
* @return JsonResponse
*/
public function update(Request $request, string $key): JsonResponse
{
$user = Api::user();
switch ($key) {
case 'nickname':
$validator = Validator::make($request->all(), [
'value' => 'required',
], [
'value.required' => '用户昵称必须填写',
]);
break;
case 'avatar':
$validator = Validator::make($request->all(), [
'value' => ['required', 'regex:/[^\s]*\.(jpg|jpeg|gif|png)$/i'],
], [
'value.required' => '用户头像必须上传',
'value.regex' => '头像地址格式不正确',
]);
break;
default:
return $this->failed('路径不合法');
}
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$result = $user->info()->update([$key => $request->value]);
if ($result) {
return $this->success('操作成功');
} else {
return $this->failed('失败');
}
}
}

View File

@@ -0,0 +1,363 @@
<?php
namespace Modules\User\Http\Controllers\Api\Sign;
use App\Api\Controllers\Controller;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Jason\Api\Api;
use Modules\Coupon\Http\Resources\User\UserBaseResource;
use Modules\User\Facades\Calendar;
use Modules\User\Facades\UserSign;
use Modules\User\Http\Resources\Sign\SignBannerResource;
use Modules\User\Http\Resources\Sign\SignTextResource;
use Modules\User\Http\Resources\UserInfoBaseResource;
use Modules\User\Models\Sign;
use Modules\User\Models\SignBanner;
use Modules\User\Models\SignConfig;
use Modules\User\Models\SignLog;
use Modules\User\Models\SignText;
use Overtrue\ChineseCalendar\Calendar as OvertrueCalendar;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Vinkla\Hashids\Facades\Hashids;
class IndexController extends Controller
{
/**
* Notes : 签到的主页,根据配置展示相应内容
*
* @Date : 2021/5/28 4:41 下午
* @Author : <Jason.C>
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$type = SignConfig::getParams('show_type');
$user = Api::user();
switch ($type) {
case 'week':
##todo 根据自然周进行展示,等待完善
break;
case 'month':
//获取年
$year = $request->year ?? now()->year;
//获取月份
$month = $request->month ?? now()->month;
$yearMonth = sprintf("%d-%s", $year, $month);
$data = $this->month($yearMonth, $user);
break;
default:
$days = $request->days ?? 7;
$data = $this->sevenDay($days, $user);
break;
}
return $this->success($data);
}
/**
* Notes : 7天签到图
*
* @Date : 2022/1/7 15:07
* @Author : Mr.wang
* @param $days
* @param $user
* @return array
*/
private function sevenDay($days, $user)
{
$continue_days = $user->sign->continue_days;
$modDay = bcmod($continue_days, $days);
$cycle = bcdiv($continue_days, $days, 0);
$data = [
'can_sign' => ! UserSign::canSign($user, now()),
'next_task' => '',
];
$task = UserSign::getNextTaskCrystal($continue_days);
if ($task) {
$data['next_task'] = [
'day' => $task['day'],
'diff' => $task['day'] - $continue_days,
'crystal' => $task['number'] ?? 0,
];
}
for ($i = 1; $i <= $days; $i++) {
$day = $cycle * $days + $i;
$text = '第'.$day.'天';
if ($i == $modDay) {
$text = '今天';
}
$data['lists'][$i] = [
'sign' => ($i <= $modDay),
'crystal' => UserSign::getSignCrystal($day),
'text' => $text,
];
}
if ($user->sign) {
return $data;
} else {
return [];
}
}
/**
* Notes : 一月签到图
*
* @Date : 2022/1/7 15:11
* @Author : Mr.wang
* @param $yearMonth
* @param $user
* @return array[]
*/
private function month($yearMonth, $user)
{
$base = [
'month' => $yearMonth,
'continue' => $user->sign->continue_days,
'total' => $user->sign->counts,
'isSign' => $user->isSign(),
];
$calendar = Calendar::show($yearMonth)['calendar'];
$calendar = $calendar->map(function ($info) use ($user) {
$canSign = UserSign::canSign($user, Carbon::parse($info['today']));
return array_merge($info, [
'isSign' => $user->isSign($info['today']),
'canSign' => $canSign,
'canReSign' => UserSign::canReSign($user, Carbon::parse($info['today']))
]);
});
// //获取月份第一天所在的星期
// $firstDayOfWeek = Carbon::parse("$yearMonth-01")->dayOfWeek;
// //补全
// $day = 0;
// $calendar = [];
// for ($i = 0; $i < 6; $i++) {
// for ($j = 0; $j < 7; $j++) {
// if ($firstDayOfWeek != 0 and $i == 0) {
// //根据月初第一天所在的星期,计算出之前几天的日子
// $day = Carbon::parse("$yearMonth-01")->subDays($firstDayOfWeek - $j)->day;
// $date = Carbon::parse("$yearMonth-01")->subDays($firstDayOfWeek - $j);
// $hidden = $date->lt(Carbon::parse("$yearMonth-01")->startOfMonth());
// } else {
// $day++;
// $date = Carbon::parse("$yearMonth-01")->addDays($day - 1);
// $hidden = $date->gt(Carbon::parse("$yearMonth-01")->endOfMonth());
// }
// $calen = [
// 'date' => $date->format("j"),
// 'isPast' => $date->isPast(),
// 'isHidden' => $hidden,
// 'isSign' => $user->isSign($date->format('Y-m-d')),
// ];
// $calendar[$i][] = $calen;
// }
// }
return [
'base' => $base,
'calendar' => $calendar->splitIn(5),
];
}
/**
* Notes : 签到
*
* @Date : 2021/5/28 3:14 下午
* @Author : <Jason.C>
* @return JsonResponse
*/
public function sign(): JsonResponse
{
$user = Api::user();
try {
[$res, $message] = UserSign::signIn($user);
if ($res) {
// $logs = $user->account->logs()
// ->where('rule_id', 10)
// ->whereDate('created_at', now())
// ->get();
return $this->success($message);
} else {
return $this->failed($message);
}
} catch (Exception $exception) {
return $this->failed($exception->getMessage());
}
}
/**
* Notes : 预留补签功能
*
* @Date : 2021/5/28 3:14 下午
* @Author : <Jason.C>
* @param Request $request
* @return JsonResponse
*/
public function replenish(Request $request): JsonResponse
{
$user = Api::user();
$date = $request->date;
$date = Carbon::parse($date);
try {
[$res, $message] = UserSign::replenish($user, $date);
if ($res) {
return $this->success($message);
} else {
return $this->failed('补签失败');
}
} catch (Exception $exception) {
return $this->failed($exception->getMessage());
}
}
/**
* Notes: 月日历
*
* @Author: 玄尘
* @Date: 2022/8/3 11:44
* @return JsonResponse
*/
public function date()
{
return $this->success(Calendar::show('2022-07'));
}
/**
* Notes: 签到封面
*
* @Author: 玄尘
* @Date: 2022/8/9 8:15
* @return JsonResponse
*/
public function backgrounds(): JsonResponse
{
$user = Api::user();
$signTexts = SignText::shown()->get();
$signBanner = SignBanner::query()->shown()->inRandomOrder()->first();
$calendar = new OvertrueCalendar();
$lunarMonth = $calendar->toChinaMonth(now()->month);
$lunarDay = $calendar->toChinaDay(now()->day);
$invite = Hashids::connection('code')->encode($user->id);
$url = Config::get('user.invite_code.url').'?invite='.$invite;
$code = 'data:image/png;base64,'.base64_encode(QrCode::format('png')
->size(100)
->margin(3)
->generate($url));
//锶源昆仑
return $this->success([
'texts' => SignTextResource::collection($signTexts),
'banner' => new SignBannerResource($signBanner),
'time' => [
'yearMonth' => now()->format('Y-m'),
'time' => now()->format('H:i'),
'day' => now()->format('d'),
'lunar' => '农历'.$lunarMonth.$lunarDay,
],
'user' => [
'username' => $user->username,
'nickname' => $user->info->nickname ?? '',
'avatar' => $user->info->avatar ?? '',
'code' => $code,
],
'sign' => $user->getSignData()
]);
}
/**
* Notes: 签到排行
*
* @Author: 玄尘
* @Date: 2022/8/17 13:43
* @param Request $request
* @return JsonResponse
*/
public function rank(Request $request): JsonResponse
{
$user = Api::user();
$ranks = Sign::query()
->latest('counts')
->take(10)
->get()
->map(function ($info) use ($user) {
return [
'user' => [
'user_id' => $info->user_id,
'username' => $info->user->username,
'nickname' => $info->user->info->nickname ?? '',
'avatar' => $info->user->info->avatar ?? '',
],
'is_my' => $info->user_id == $user->id,
'total' => $info->counts,
];
})
->pad(10, [
'user' => [
'user_id' => 0,
'username' => '---',
'nickname' => '---',
'avatar' => '---',
],
'is_my' => false,
'total' => 0,
]);
$ranks = $ranks->toArray();
$i = 1;
$top = $other = [];
$myRank = 0;
foreach ($ranks as &$rank) {
$rank['rank'] = $i;
if ($rank['user']['user_id'] == $user->id) {
$myRank = $i;
}
if ($i < 4) {
$top[] = $rank;
} else {
$other[] = $rank;
}
$i++;
}
if (! $myRank) {
$myRank = Sign::query()->where('counts', '>', $user->sign->counts)->count();
}
$data = [
'user' => [
'username' => $user->username,
'nickname' => $user->info->nickname,
'avatar' => $user->info->avatar,
'total' => $user->sign->counts,
'rank' => $myRank ?: $myRank + 1,
],
'top' => $top,
'other' => $other,
];
return $this->success($data);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Modules\User\Http\Controllers\Api\Socialite;
use Illuminate\Http\Request;
abstract class Controller extends \App\Api\Controllers\Controller
{
abstract public function app(Request $request);
abstract public function query(Request $request);
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Modules\User\Http\Controllers\Api\Socialite;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Models\User;
class UniCloudController extends Controller
{
public function app(Request $request)
{
$validator = Validator::make($request->all(), [
'access_token' => 'required',
'openid' => 'required',
], [
'access_token.required' => 'access_token必须填写',
'openid.required' => 'openid必须填写',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$data = [
'access_token' => $request->access_token,
'openid' => $request->openid,
];
$secret = config('user.socialite.unicloud.self_secret', '');
$domain = config('user.socialite.unicloud.domain', '');
$url = config('user.socialite.unicloud.cloud_function_url.one_key', '');
if (! $secret || ! $domain || ! $url) {
return $this->failed('过程参数存在错误');
}
ksort($data);
$signString = urldecode(http_build_query($data));
$sign = hash_hmac('sha256', $signString, $secret);
$params = $signString.'&sign='.$sign;
$url = $domain.$url.'?'.$params;
$res = json_decode(file_get_contents($url));
if ($res->success) {
$user = User::firstOrCreate([
'username' => $res->phoneNumber,
], [
'password' => 111111,
]);
$token = Api::login($user);
event(new UserLoginSuccess($user, $request, '本机一键登录'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'is_new' => $user->wasRecentlyCreated,
]);
} else {
return $this->failed('一键登录失败');
}
}
public function query(Request $request)
{
$validator = Validator::make($request->all(), [
'mobile' => 'required',
], [
'mobile.required' => '请传入手机号',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$user = User::firstOrCreate([
'username' => $request->mobile,
], [
'password' => 111111,
]);
$token = Api::login($user);
event(new UserLoginSuccess($user, $request, '本机一键登录'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'is_new' => $user->wasRecentlyCreated,
]);
}
}

View File

@@ -0,0 +1,489 @@
<?php
namespace Modules\User\Http\Controllers\Api\Socialite;
use App\Models\AreaCode;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Facades\Sms;
use Modules\User\Http\Requests\WechatMiniRequest;
use Modules\User\Models\User;
use Modules\User\Models\UserSubscribe;
use Modules\User\Models\UserWechat;
use Modules\User\Traits\WechatTrait;
use Vinkla\Hashids\Facades\Hashids;
class WeChatController extends Controller
{
use WechatTrait;
protected array $config = [];
/**
* Notes : APP 登录
*
* @Date : 2021/6/10 3:40 下午
* @Author : Mr.wang
* @param Request $request
* @return JsonResponse
*/
public function app(Request $request): JsonResponse
{
$validator = Validator::make($request->all(), [
'union_id' => 'required',
'mobileNo' => 'required|phone:CN,mobile',
'code' => 'required',
], [
'union_id.required' => 'unionId必须填写',
'mobileNo.required' => '手机号码必须填写',
'mobileNo.phone' => '手机号码格式不正确',
'code.required' => '验证码必须填写',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first(), 422);
}
$unionId = $request->union_id;
$wechat = UserWechat::where('unionid', $unionId)->first();
if (empty($wechat)) {
$mobileNo = $request->mobileNo;
$code = $request->code;
$check = Sms::checkCode($mobileNo, $code);
if ($check == false) {
return $this->failed('验证码不正确', 422);
}
$user = User::firstOrCreate([
'username' => $mobileNo,
], [
'password' => 111111,
]);
$wechat = $user->wechat()->firstOrcreate([
'unionid' => $unionId,
'nickname' => $request->nickname ?? '',
'avatar' => $request->avatar ?? '',
'sex' => $request->gender ?? 0,
'country' => $request->country ?? '',
'province' => $request->province ?? '',
'city' => $request->city ?? '',
]);
$wechat->app()->firstOrcreate([
'openid' => $request->open_id ?? '',
]);
$user->info()->update([
'nickname' => $request->nickname ?? $user->info->nickname,
'avatar' => $request->avatar ?? '',
]);
$token = Api::login($user);
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'is_new' => $user->wasRecentlyCreated,
]);
} else {
$token = Api::login($wechat->user);
event(new UserLoginSuccess(Api::user(), $request, '微信授权'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'is_new' => false,
]);
}
}
/**
* Notes : 小程序手机号登录
*
* @Date : 2021/7/29 17:21
* @Author : Mr.wang
* @param WechatMiniRequest $request
* @return JsonResponse
* @throws InvalidConfigException
*/
public function mini(WechatMiniRequest $request): JsonResponse
{
$code = $request->code;
$weChat = app('wechat.mini_program');
$session = $weChat->auth->session($code);
if ($session->errcode) {
return $this->failed($session->errmsg);
}
try {
$decryptedData = $weChat->encryptor->decryptData(
$session->session_key,
$request->iv,
$request->encryptedData
);
$mobile = $decryptedData['purePhoneNumber'];
$user = User::where('username', $mobile)->first();
if (! $user) {
$user = User::create([
'username' => $mobile,
'password' => 111111,
]);
$user->info()->create([
'nickname' => $request->nickname ?? '',
'avatar' => $request->avatar ?? '',
]);
}
$token = Api::login($user);
event(new UserLoginSuccess(Api::user(), $request, '微信授权'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
'is_new' => $user->wasRecentlyCreated,
]);
} catch (\Exception $exception) {
return $this->failed($exception->getMessage());
}
}
/**
* Notes : 公众号登录
*
* @Date : 2021/5/26 3:14 下午
* @Author : < Jason.C >
*/
public function official()
{
}
public function query(Request $request): JsonResponse
{
$unionId = $request->union_id ?? '';
if (empty($unionId)) {
return $this->failed('', 404);
}
$wechat = UserWechat::where('unionid', $unionId)->first();
if (empty($wechat)) {
return $this->success([
'union_id' => $unionId,
]);
} else {
$token = Api::login($wechat->user);
event(new UserLoginSuccess(Api::user(), $request, '微信授权'));
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
]);
}
}
/**
* Notes: 入库微信信息
*
* @Author: 玄尘
* @Date: 2022/8/2 11:16
*/
public function addWechatUser(): JsonResponse
{
try {
$user = Api::user();
if (! $user) {
throw new \Exception('操作失败请登录。');
}
$wechatUser = $user->wechat;
$weUser = $this->getUserFromCode();
$openid = $weUser->getId();
$baseUser = $this->getWechatUser($openid);
$unionid = '';
$raw = $weUser->getRaw();
if (isset($raw['unionid'])) {
$unionid = $raw['unionid'];
}
if (! $openid) {
if ($raw && $raw['errmsg']) {
throw new \Exception($raw['errmsg']);
}
throw new \Exception('code解密失败');
}
if (! $user->info->avatar) {
//更新头像
$user->info->update([
'avatar' => $weUser->getAvatar(),
]);
}
if (! $wechatUser) {
$wechatUser = $user->wechat()
->firstOrCreate([
'unionid' => $unionid,
'nickname' => $weUser->getNickname(),
'avatar' => $weUser->getAvatar(),
]);
} elseif (empty($wechatUser['unionid']) && ! empty($unionid)) {
$wechatUser->update([
'unionid' => $unionid,
]);
}
if (! $wechatUser->official) {
$wechatUser->official()->firstOrCreate([
'openid' => $weUser->getId(),
'subscribe' => $baseUser->subscribe
]);
} else {
$wechatUser->official()->update([
'subscribe' => $baseUser->subscribe
]);
}
//设置关注状态
if ($unionid) {
$this->setUserSubscribe($unionid, $openid, $baseUser->subscribe);
}
return $this->success([
'openid' => $openid,
'subscribe' => $baseUser->subscribe,
]);
} catch (\Exception $exception) {
return $this->failed($exception->getMessage());
}
}
/**
* Notes: 小程序入库
*
* @Author: 玄尘
* @Date: 2022/9/23 14:46
* @param Request $request
* @return JsonResponse|mixed
*/
public function miniAddWechatUser(Request $request)
{
$user = Api::user();
$validator = \Validator::make($request->all(), [
'code' => 'required',
'iv' => 'required',
'encryptedData' => 'required',
], [
'code.required' => '缺少参数code',
'iv.required' => '缺少参数iv',
'encryptedData.mobile' => '缺少参数encryptedData',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
try {
$code = $request->code;
$unionid = '';
$weChat = app('wechat.mini_program');
$session = $weChat->auth->session($code);
if (isset($session->unionid)) {
$unionid = $session->unionid;
}
if (isset($session->errcode)) {
return $this->failed($session->errmsg);
}
$openid = $session->openid;
$wechatUser = $user->wechat;
$decryptedData = $weChat->encryptor->decryptData(
$session->session_key,
$request->iv,
$request->encryptedData
);
if (! $wechatUser) {
$wechatUser = $user->wechat()
->firstOrCreate([
'unionid' => $unionid,
'nickname' => $decryptedData['nickName'] ?? '',
'avatar' => $decryptedData['avatarUrl'] ?? '',
]);
} elseif (empty($wechatUser['unionid']) && ! empty($unionid)) {
$wechatUser->update([
'unionid' => $unionid,
]);
}
if (! $wechatUser->mini) {
$wechatUser->mini()->firstOrCreate([
'openid' => $openid,
]);
}
$userSubscribe = UserSubscribe::query()
->where('unionid', $unionid)
->where('subscribe', 1)
->first();
if ($userSubscribe && ! $wechatUser->official) {
if (! $wechatUser->official) {
$wechatUser->official()
->firstOrCreate([
'openid' => $userSubscribe->openid,
'subscribe' => $userSubscribe->subscribe
]);
} else {
$wechatUser->official()->update([
'subscribe' => $userSubscribe->subscribe
]);
}
}
return $this->success([
'openid' => $openid,
'subscribe' => $userSubscribe ? 1 : 0,
]);
} catch (\Exception $e) {
return $this->failed($e->getMessage());
}
}
/**
* Notes: 小程序登录加注册
*
* @Author: 玄尘
* @Date: 2023/1/12 8:53
* @param Request $request
* @return JsonResponse|mixed
*/
public function miniLoginAndReg(Request $request)
{
$validator = \Validator::make($request->all(), [
'code' => 'required',
'iv' => 'required',
'encryptedData' => 'required',
], [
'code.required' => '缺少参数code',
'iv.required' => '缺少参数iv',
'encryptedData.mobile' => '缺少参数encryptedData',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
try {
$code = $request->code;
$invite_code = $request->invite ?? '';//推荐码
$weChat = app('wechat.mini_program');
$session = $weChat->auth->session($code);
if (isset($session->errcode)) {
return $this->failed($session->errmsg);
}
$decryptedData = $weChat->encryptor->decryptData(
$session->session_key,
$request->iv,
$request->encryptedData
);
$user = User::query()->where('username', $decryptedData['phoneNumber'])->first();
if (! $user) {
$parent = 0;
if ($invite_code) {
$invite = Hashids::connection('code')->decode($invite_code);
if (empty($invite)) {
return $this->failed('邀请码不正确');
}
$parent = $invite[0];
}
$user = User::query()
->firstOrCreate([
'username' => $decryptedData['phoneNumber'],
], [
'parent_id' => $parent,
'password' => 111111,
]);
}
$token = Api::login($user);
return $this->success([
'token_type' => 'Bearer',
'access_token' => $token,
]);
} catch (\Exception $e) {
return $this->failed($e->getMessage());
}
}
/**
* Notes: description
*
* @Author: 玄尘
* @Date: 2023/1/12 10:48
*/
public function updateUserData(Request $request)
{
$user = Api::user();
$delivery_code = $request->delivery_code ?? '';//提货码
$name = $request->name ?? '';//提货码
$validator = \Validator::make($request->all(), [
'delivery_code' => 'required',
'name' => 'required',
], [
'delivery_code.required' => '缺少提货码',
'name.required' => '缺少姓名',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
if ($name) {
$user->info->update([
'nickname' => $name
]);
}
if ($delivery_code) {
if (! $user->info->delivery_code) {
$areaCode = AreaCode::query()->where('code', $delivery_code)->first();
if ($areaCode->user_id) {
return $this->failed('当前提货码已被别人使用');
}
$user->info->update([
'delivery_code' => $delivery_code
]);
$areaCode->update([
'user_id' => $user->id
]);
} else {
if ($user->info->delivery_code && $user->info->delivery_code != $delivery_code) {
return $this->failed('您已经绑定过提货码,不能重复绑定');
}
}
}
return $this->success('更新成功');
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace Modules\User\Http\Controllers\Api\Stock;
use App\Api\Controllers\Controller;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\Mall\Facades\Item;
use Modules\Mall\Facades\Order as OrderFacade;
use Modules\Mall\Http\Resources\Api\Address\AddressResource;
use Modules\Mall\Http\Resources\Api\Goods\GoodsBaseResource;
use Modules\Mall\Http\Resources\Api\Order\OrderCollection;
use Modules\Mall\Models\Address;
use Modules\Mall\Models\Goods;
use Modules\Mall\Models\GoodsSku;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\Region;
use Modules\User\Http\Resources\stock\UserStockLogCollection;
use Modules\User\Http\Resources\UserIdentityBaseResource;
use Modules\User\Models\Identity;
use Modules\User\Models\UserStockLog;
class IndexController extends Controller
{
/**
* Notes : 订单列表
*
* @Date : 2021/5/13 5:17 下午
* @Author : <Jason.C>
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$state = $request->state ?? '';
$list = Order::byUser(Api::user())
->TypeSample()
->when($state, function ($query) use ($state) {
switch ($state) {
case 'init':
$query->paid()->unPay();
break;
case 'delivered':
$query->delivered();
break;
}
}, function ($query) {
$query->common();
})
->paginate(8);
return $this->success(new OrderCollection($list));
}
/**
* Notes: 提货前置
*
* @Author: 玄尘
* @Date: 2022/8/1 11:32
* @return JsonResponse
*/
public function create(): JsonResponse
{
$user = Api::user();
$addresses = Address::where('user_id', $user->id)->orderBy('is_default', 'desc')->get();
$address = Address::where('user_id', $user->id)->orderBy('is_default', 'desc')->first();
$data = [
'addresses' => AddressResource::collection($addresses),
'address' => $address ? new AddressResource($address) : '',
'stockData' => $user->getStockData(),
'dientity' => new UserIdentityBaseResource($user->identityFirst())
];
return $this->success($data);
}
/**
* Notes: 提货
*
* @Author: 玄尘
* @Date: 2022/8/1 11:33
* @param Request $request
* @return JsonResponse|mixed
* @throws \Exception
*/
public function store(Request $request)
{
$user = Api::user();
$validator = Validator::make($request->all(), [
'address_id' => 'required|integer',
'qty' => 'required|integer',
], [
'qty.required' => '缺少提货数量',
'qty.integer' => '数量必须是数字',
'address_id.required' => '缺少收货地址',
'address_id.integer' => '收货地址必须是数字',
]);
if ($validator->fails()) {
return $this->failed($validator->errors()->first());
}
$remark = $request->remark ?? '';
$address_id = $request->address_id;
$qty = $request->qty;
$address = Address::find($address_id);
// $userIdentity = $user->identityFirst();
// if ($userIdentity->job == Identity::JOB_TY) {
// $shenzhen = Region::query()->where('name', '深圳市')->first();
// if ($address->city_id != $shenzhen->id) {
// return $this->failed('体验官收货地址只能选择深圳');
// }
// }
$goods_sku = GoodsSku::query()
->whereHas('goods', function ($q) {
$q->where('channel', Goods::CHANNEL_FREE)->where('status', Goods::STATUS_UP);
})
->first();
if (! $goods_sku) {
return $this->failed('缺少商品');
}
$stockData = $user->getStockData();
if ($qty > $stockData['residue']) {
return $this->failed('用户库存不足');
}
$detail = collect();
$item = new Item($goods_sku, $address, $qty);
$detail->push($item);
$orders = (new OrderFacade)->user($user)
->remark($remark)
->type(Order::TYPE_SAMPLE)
->items($detail)
->address($address)
->create();
//提货自动完成
foreach ($orders as $order) {
if ($order->type == Order::TYPE_SAMPLE) {
$order->pay();
}
}
return $this->success('提货成功');
}
/**
* Notes: 账变记录
*
* @Author: 玄尘
* @Date: 2022/8/3 10:43
*/
public function logs()
{
$user = Api::user();
$logs = UserStockLog::query()
->ByUser($user)
->oldest()
->paginate();
return $this->success(new UserStockLogCollection($logs));
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Modules\User\Rules\IdCardRule;
class CertificationRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|min:2|max:5',
'id_card' => ['required', new IdCardRule(), 'unique:user_certifications'],
// 'front_card' => 'required',
// 'back_card' => 'required',
];
}
public function messages(): array
{
return [
'name.required' => '认证用户姓名必须填写',
'name.min' => '认证用户姓名至少:min个字符',
'name.max' => '认证用户姓名最多:max个字符',
'id_card.required' => '身份证号必须填写',
'id_card.unique' => '身份证号已存在',
'front_card.required' => '身份证正面图片必须上传',
'back_card.required' => '身份证背面图片必须上传',
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LoginRequest extends FormRequest
{
/**
* Notes : 字段验证规则
*
* @Date : 2021/3/11 4:59 下午
* @Author : <Jason.C>
* @return string[]
*/
public function rules(): array
{
return [
'username' => 'required',
'password' => 'required|min:6',
];
}
/**
* Notes : 验证错误提示消息
*
* @Date : 2021/3/11 4:59 下午
* @Author : <Jason.C>
* @return string[]
*/
public function messages(): array
{
return [
'username.required' => '用户名必须填写',
'password.required' => '密码必须填写',
'password.min' => '密码最少为:min个字符',
];
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LoginSmsRequest extends FormRequest
{
public function rules(): array
{
return [
'mobileNo' => 'required|phone:CN,mobile',
'code' => 'required',
];
}
public function messages(): array
{
return [
'mobileNo.required' => '手机号码必须填写',
'mobileNo.phone' => '手机号码格式不正确',
'code.required' => '验证码必须填写',
];
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterRequest extends FormRequest
{
/**
* Notes : 字段验证规则
*
* @Date : 2021/3/11 4:59 下午
* @Author : <Jason.C>
* @return string[]
*/
public function rules(): array
{
return [
'username' => 'required|unique:users',
'password' => 'required|min:6',
];
}
/**
* Notes : 验证错误提示消息
*
* @Date : 2021/3/11 4:59 下午
* @Author : <Jason.C>
* @return string[]
*/
public function messages(): array
{
return [
'username.required' => '用户名必须填写',
'username.unique' => '用户名已经被使用',
'password.required' => '密码必须填写',
'password.min' => '密码最少为:min个字符',
];
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SmsRequest extends FormRequest
{
public function rules(): array
{
return [
'mobileNo' => 'required|phone:CN,mobile',
];
}
public function messages(): array
{
return [
'mobileNo.required' => '手机号码必须填写',
'mobileNo.phone' => '手机号码格式不正确',
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ThawOneRequest extends FormRequest
{
public function rules(): array
{
return [
'thaw_id' => 'required',
'all_ids' => 'required',
];
}
public function messages(): array
{
return [
'thaw_id.required' => '请传入要领取的ID',
'all_ids.required' => '传入当前总的ID',
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateUserInfoRequest extends FormRequest
{
public function rules(): array
{
return [
'nickname' => 'required',
'avatar' => ['regex:/[^\s]*\.(jpg|jpeg|gif|png)$/i'],
];
}
public function messages(): array
{
return [
'nickname.required' => '用户昵称必须填写',
'avatar.regex' => '头像地址格式不正确',
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class WechatMiniRequest extends FormRequest
{
public function rules(): array
{
return [
'code' => 'required',
'iv' => 'required',
'encryptedData' => 'required',
];
}
public function messages(): array
{
return [
'code.required' => '缺失CODE',
'iv.required' => '缺失向量',
'encryptedData.required' => '缺失内容',
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Http\Resources\Account;
use App\Api\Resources\BaseCollection;
class UserAccountLogCollection extends BaseCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection->map(function ($log) {
return new UserAccountLogResource($log);
}),
'page' => $this->page(),
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Modules\User\Http\Resources\Account;
use Illuminate\Http\Resources\Json\JsonResource;
class UserAccountLogResource extends JsonResource
{
public function toArray($request): array
{
return [
'user_account_log_id' => $this->id,
'frozen' => [
'value' => $this->frozen,
'text' => $this->frozen ? '待发放' : '已发放',
],
'rule' => [
'rule_id' => $this->rule->id,
'name' => $this->rule->name,
'title' => $this->rule->title,
'remark' => $this->rule->remark,
],
'remark' => $this->source['remark'] ?? $this->rule->remark,
'amount' => $this->amount > 0 ? '+'.floatval($this->amount) : floatval($this->amount),
'created_at' => $this->created_at->format('Y-m-d H:i:s'),
];
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\User\Http\Resources\Account;
use Illuminate\Http\Resources\Json\JsonResource;
class UserAccountResource extends JsonResource
{
public function toArray($request): array
{
return [
'balance' => floatval($this->balance),//现金
'score' => [
'surplus' => floatval($this->score),//水滴余量
'use' => 0,//水滴使用
'plan' => 300,//水滴赠送
],
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Http\Resources\Favorite;
use App\Api\Resources\BaseCollection;
class FavoriteCollection extends BaseCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection->map(function ($info) {
return new FavoriteResource($info);
}),
'page' => $this->page(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Modules\User\Http\Resources\Favorite;
use Illuminate\Http\Resources\Json\JsonResource;
use Modules\Cms\Http\Resources\ArticleBaseResource;
class FavoriteResource extends JsonResource
{
public function toArray($request): array
{
return [
'favorite_id' => $this->id,
'favoriteable' => new ArticleBaseResource($this->favoriteable)
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\User\Http\Resources;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class IdentityMiddleResource extends JsonResource
{
public function toArray($request): array
{
if ($this->identity->order == 1) {
$ended_at = '---';
} else {
$ended_at = $this->identity->years ? Carbon::parse($this->ended_at)->format('Y-m-d') : '永久';
}
return [
'name' => $this->identity->name,
'serial' => $this->identity->serial_prefix.$this->serial,
'started_at' => $this->started_at ?? '',
'ended_at' => $ended_at,
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Http\Resources\Invite;
use App\Api\Resources\BaseCollection;
class UserInviteCollection extends BaseCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection->map(function ($info) {
return new UserInviteResource($info);
}),
'page' => $this->page(),
];
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Modules\User\Http\Resources\Invite;
use Illuminate\Http\Resources\Json\JsonResource;
use Modules\Coupon\Http\Resources\User\UserBaseResource;
class UserInviteResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'number' => $this->number,
'code' => $this->code,
'user' => $this->user ? new UserBaseResource($this->user) : '',
'activeUser' => $this->activeUser ? new UserBaseResource($this->activeUser) : '',
'actived_at' => $this->actived_at ? $this->actived_at->format('Y-m-d') : '',
];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RelationResource extends JsonResource
{
public function toArray($request): array
{
return [
'user_id' => $this->user->id,
// 'username' => substr_replace($this->user->username, '****', 3, 4),
'username' => $this->user->username,
'nickname' => $this->user->info->nickname ?? '',
'avatar' => $this->user->info->avatar ?? '',
'sex' => $this->user->case ? $this->user->case->sex_text : '--',
'identity' => new UserIdentityBaseResource($this->user->identities->first()),
'created_at' => (string) $this->user->created_at,
];
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\User\Http\Resources\Sign;
use Illuminate\Http\Resources\Json\JsonResource;
class SignBannerResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'cover' => $this->cover_url,
];
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Modules\User\Http\Resources\Sign;
use Illuminate\Http\Resources\Json\JsonResource;
class SignTextResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'h1' => $this->description,
'h2' => $this->sub_description,
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Storage;
class UserCertificationResource extends JsonResource
{
public function toArray($request): array
{
return [
'certification_id' => $this->id,
'name' => $this->name,
'verified' => (bool) $this->verified,
'id_card' => $this->id_card,
'front_card' => $this->when($this->front_card, function () {
return Storage::url($this->front_card);
}),
'back_card' => $this->when($this->back_card, function () {
return Storage::url($this->back_card);
}),
'created_at' => (string) $this->created_at,
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserIdentityBaseResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'cover' => $this->cover_url,
'order' => $this->order,
'is_experience' => (bool) $this->isExperience(),
];
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Jason\Api\Api;
use Modules\User\Models\Identity;
use Modules\User\Models\Order;
class UserIdentityResource extends JsonResource
{
public function toArray($request): array
{
$user = Api::user();
$open = $renew = false;
$text = '立即开通';
$price = $this->getCondition('price', '0');
$cost = $this->getCondition('cost', '0');
$identityName = $this->name;
if ($user) {
$identity = $user->identityFirst();
if ($identity) {
//当前身份 可以续费
if ($identity->id == $this->id) {
$renew = (bool) $identity->years;
$text = '续费';
} elseif ($identity->order > $this->order) {
$text = '不可降级';
} else {
$identityOrder = Order::ByUser($user)
->where('identity_id', $this->id)
->where('state', Order::STATE_INIT)
->first();
if ($identityOrder) {
$text = '等待审核';
} else {
$open = true;
}
}
} else {
$open = true;
}
}
return [
'identity_id' => $this->id,
'name' => $identityName,
'stock' => $this->stock,
'years' => $this->years,
'times' => $this->when($user && $this->id == $user->identityFirst()->id, function () use ($user) {
return new IdentityMiddleResource($user->identityMiddle()->first());
}, [
'name' => '---',
'serial' => '---',
'started_at' => '---',
'ended_at' => '---',
]),
'cover' => $this->cover_url,
'order' => $this->order,
'description' => $this->description ?? "",
'cost' => floatval($cost),//开通金额
'price' => floatval($price),//开通金额
'is_experience' => (bool) $this->isExperience(),
'can' => [
'buy' => (bool) $this->can_buy,
'open' => $this->can_buy ? $open : false,//开通
'renew' => $this->can_buy ? $renew : false,//续费
],
'buttonText' => $text,
'rights' => $this->rights,
'rules' => $this->getRules(),
'not_rules' => $this->getNotRules(),
'is_open' => $user && $this->id == $user->identityFirst()->id
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Storage;
class UserIdentityRightsResource extends JsonResource
{
public function toArray($request): array
{
$rights = $this->rights;
$data = [];
if ($rights){
for ($i = 1; $i <= count($rights); $i++) {
$data[$i] = [
'name' => $rights['new_'.$i]['name'] ?? '',
'cover' => ! empty($rights['new_'.$i]['cover']) ? Storage::url($rights['new_'.$i]['cover']) : '',
'order' => $rights['new_'.$i]['order'] ?? '',
'remark' => $rights['new_'.$i]['remark'] ?? '',
];
}
}
return [
'identity_id' => $this->id,
'name' => $this->name,
'cover' => $this->cover_url,
'order' => $this->order,
'rights' => $data,
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserInfoBaseResource extends JsonResource
{
public function toArray($request): array
{
return [
'user_id' => $this->id,
'username' => $this->username,
'nickname' => $this->info->nickname ?? '',
'avatar' => $this->info->avatar ?? '',
// 'sign' => $this->getSignData(),
'identity' => new UserIdentityBaseResource($this->identities->first()),
'status' => $this->getStateData(),
'canPick' => $this->canPick(),
'nowStatus' => $this->getNowStatus(),
'tag' => $this->tag
];
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Jason\Api\Api;
use Modules\Mall\Models\Order;
use Modules\Mall\Models\Refund as RefundModel;
use Modules\User\Http\Resources\Account\UserAccountResource;
use Modules\User\Models\Identity;
use Vinkla\Hashids\Facades\Hashids;
class UserInfoResource extends JsonResource
{
public function toArray($request): array
{
$identity = $this->identityFirst();
if ($identity->id > 2) {
$order = true;
} else {
$order = false;
}
return [
'user_id' => $this->id,
'username' => $this->username,
'nickname' => $this->info->nickname ?? '',
'avatar' => $this->info->avatar ?? '',
'account' => new UserAccountResource($this->account),
'identity' => new UserIdentityBaseResource($identity),
'service' => new UserServiceResource($identity->identities()->first()),
'water_mobile' => app('Conf_mall')['water_mobile'] ?? '',
'invite' => Hashids::connection('code')->encode($this->id),
'case' => $this->getStockData(),
'created_at' => (string) $this->created_at,
'status' => $this->getStateData(),
'nowStatus' => $this->getNowStatus(),
'canPick' => $this->canPick(),
'count' => [
'relation' => $this->getRelationCount(),//下级
'orders' => $this->getOrderCount(),
'refunds' => RefundModel::byUser(Api::user())->count(),//退款单数量
],
'identityShow' => $this->when(true, function () use ($identity) {
return [
'right' => new UserIdentityRightsResource($identity),
'times' => new IdentityMiddleResource($this->identityMiddle()->first()),
'is_top' => $identity->id == 4,
];
}),
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserServiceResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'code' => $this->cover_url,
'mobile' => $this->mobile,
];
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\User\Http\Resources;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Modules\User\Facades\UserSign;
class UserSignResource extends JsonResource
{
public function toArray($request): array
{
return [
'continue_days' => $this->continue_days,
'counts' => $this->counts,
'last_sign_at' => (string) $this->last_sign_at,
'today_signed' => !UserSign::canSign($this->user, Carbon::today()),
];
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\User\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserWechatResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'unionid' => $this->unionid,
'nickname' => $this->nickname,
'avatar' => $this->avatar,
'mini' => $this->mini,
'official' => $this->official,
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Modules\User\Http\Resources\stock;
use App\Api\Resources\BaseCollection;
class UserStockLogCollection extends BaseCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection->map(function ($log) {
return new UserStockLogResource($log);
}),
'page' => $this->page(),
];
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\User\Http\Resources\stock;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class UserStockLogResource extends JsonResource
{
public function toArray($request): array
{
return [
'user_stock_log_id' => $this->id,
'variable' => $this->variable,
'type' => $this->type_text,
'created_at' => $this->created_at->format('Y-m-d H:i:s'),
];
}
}