初始化

This commit is contained in:
2026-03-02 13:44:38 +08:00
commit 05b785083c
677 changed files with 58662 additions and 0 deletions

View File

@@ -0,0 +1,304 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminDepartment;
use addons\webman\model\AdminUser;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\badge\Badge;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\support\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Validation\Rule;
/**
* 系统用户管理
*/
class AdminController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.user_model');
}
/**
* 系统用户
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('admin.system_user'));
$grid->model()
->when(plugin()->webman->config('admin_auth_id') != Admin::id(), function (Builder $builder) {
$builder->whereKeyNot(plugin()->webman->config('admin_auth_id'));
});
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->userInfo();
$grid->column('username', admin_trans('admin.fields.username'))->display(function ($val, $data) {
if ($data['id'] == plugin()->webman->config('admin_auth_id')) {
return Html::create()
->content($val)
->content(
Badge::create()->count(admin_trans('admin.super_admin'))->numberStyle(['backgroundColor' => '#1890ff', 'marginLeft' => '5px'])
);
} else {
return $val;
}
})->copy();
$grid->column('phone', admin_trans('admin.fields.phone'));
$grid->column('email', admin_trans('admin.fields.mail'));
$grid->column('status', admin_trans('admin.fields.status'))->switch();
$grid->column('type', admin_trans('admin.fields.type'))
->display(function ($value, AdminUser $data) {
$tag = '';
switch ($value) {
case AdminDepartment::TYPE_DEPARTMENT:
$tag = Tag::create(admin_trans('department.type.' . AdminDepartment::TYPE_DEPARTMENT))->color('#108ee9');
break;
case AdminDepartment::TYPE_CHANNEL:
$tag = Tag::create(admin_trans('department.type.' . AdminDepartment::TYPE_CHANNEL))->color('#f50');
break;
}
if ($data->is_super == 1) {
$tag = Tag::create(admin_trans('admin.fields.is_super'))->color('#3b5999');
}
return Html::create()->content([
$tag,
]);
})->sortable();
$grid->column('created_at', admin_trans('admin.fields.create_at'));
$grid->quickSearch();
$grid->hideDelete();
$grid->setForm()->modal($this->form());
$grid->filter(function (Filter $filter) {
$filter->like()->text('username')->placeholder(admin_trans('admin.fields.username'));
$filter->like()->text('phone')->placeholder(admin_trans('admin.fields.phone'));
$filter->eq()->select('status')
->placeholder(admin_trans('admin.fields.status'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
1 => admin_trans('admin.normal'),
0 => admin_trans('admin.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$department_model = plugin()->webman->config('database.department_model');
$departmentList = (new $department_model)::where('type', AdminDepartment::TYPE_DEPARTMENT)
->orWhereHas('channel', function ($query) {
$query->whereNull('deleted_at');
})
->get();
$departmentTree = [
['id' => 'department', 'name' => admin_trans('admin.department_tree'), 'pid' => 0],
['id' => 'channel', 'name' => admin_trans('admin.channel_tree'), 'pid' => 0],
];
/** @var AdminDepartment $value */
foreach ($departmentList as $value) {
if ($value->type == AdminDepartment::TYPE_DEPARTMENT) {
$departmentTree[] = ['id' => $value->id, 'name' => $value->name, 'pid' => $value->pid == 0 ? 'department' : $value->pid];
}
if ($value->type == AdminDepartment::TYPE_CHANNEL) {
$departmentTree[] = ['id' => $value->id, 'name' => $value->name, 'pid' => $value->pid == 0 ? 'channel' : $value->pid];
}
}
$grid->sidebar('department_id', $departmentTree)
->tree()
->hideAdd()
->hideDel()
->searchPlaceholder(admin_trans('admin.search_department'));
$grid->actions(function (Actions $actions, $data) {
if ($data['id'] == plugin()->webman->config('admin_auth_id')) {
$actions->hideDel();
}
$actions->dropdown()
->prepend(admin_trans('admin.reset_password'), 'fas fa-key')
->modal($this->resetPassword($data['id']));
});
$grid->deling(function ($ids) {
if (is_array($ids) && in_array(plugin()->webman->config('admin_auth_id'), $ids)) {
return message_error(admin_trans('admin.super_admin_delete'));
}
});
$grid->updateing(function ($ids, $data) {
if (in_array(plugin()->webman->config('admin_auth_id'), $ids)) {
if (isset($data['status']) && $data['status'] == 0) {
return message_error(admin_trans('admin.super_admin_disabled'));
}
}
});
});
}
/**
* 系统用户
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('admin.system_user'));
$form->text('username', admin_trans('admin.fields.username'))
->ruleChsDash()
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'))->ignore($form->input('id')) => admin_trans('admin.username_exist'),
])
->required()
->disabled($form->isEdit());
$form->text('nickname', admin_trans('admin.fields.nickname'))
->ruleChsAlphaNum()
->required();
$form->image('avatar', admin_trans('admin.fields.avatar'))
->required();
if (!$form->isEdit()) {
$form->password('password', admin_trans('admin.fields.password'))
->default(123456)
->help(admin_trans('admin.pass_help'))
->required();
}
$form->text('phone', admin_trans('admin.fields.phone'))
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'))->ignore($form->input('id')) => admin_trans('admin.phone_exist'),
])
->ruleMobile();
$form->text('email', admin_trans('admin.fields.mail'))->ruleEmail();
if ($form->input('id') != plugin()->webman->config('admin_auth_id')) {
$form->radio('type', admin_trans('admin.fields.type'))
->default(AdminDepartment::TYPE_DEPARTMENT)
->disabled($form->isEdit())
->options([
AdminDepartment::TYPE_DEPARTMENT => admin_trans('department.type.' . AdminDepartment::TYPE_DEPARTMENT),
AdminDepartment::TYPE_CHANNEL => admin_trans('department.type.' . AdminDepartment::TYPE_CHANNEL)
])
->when('==', AdminDepartment::TYPE_DEPARTMENT, function (Form $form) {
$roleModel = plugin()->webman->config('database.role_model');
$role = $roleModel::where('type', AdminDepartment::TYPE_DEPARTMENT)->pluck('name', 'id')->toArray();
$form->checkbox('roles', admin_trans('admin.access_rights'))
->options($role);
$department = plugin()->webman->config('database.department_model');
$options = $department::where('status', 1)->where('type', AdminDepartment::TYPE_DEPARTMENT)->get()->toArray();
$form->treeSelect('department_id', admin_trans('admin.department'))
->required()
->options($options);
})->when('==', AdminDepartment::TYPE_CHANNEL, function (Form $form) {
$roleModel = plugin()->webman->config('database.role_model');
$role = $roleModel::where('type', AdminDepartment::TYPE_CHANNEL)->pluck('name', 'id')->toArray();
$form->checkbox('roles', admin_trans('admin.access_rights'))
->options($role);
$department = plugin()->webman->config('database.department_model');
$options = $department::where('status', 1)->where('type', AdminDepartment::TYPE_CHANNEL)->whereHas('channel', function ($query) {
$query->whereNull('deleted_at');
})
->get()->toArray();
$form->treeSelect('department_id', admin_trans('admin.channel'))
->required()
->options($options);
});
$department = plugin()->webman->config('database.post_model');
$options = $department::where('status', 1)->pluck('name', 'id')->toArray();
$form->select('post', admin_trans('admin.post'))
->options($options)
->multiple();
}
});
}
/**
* 修改密码
* @auth true
* @group all
* @return Form
*/
public function updatePassword(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->password('old_password', admin_trans('admin.old_password'))->required();
$form->password('password', admin_trans('admin.new_password'))
->rule([
'confirmed' => admin_trans('admin.password_confim_validate'),
'min:6' => admin_trans('admin.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('admin.confim_password'))
->required();
$form->saving(function (Form $form) {
if (!password_verify($form->input('old_password'), Admin::user()->password)) {
return message_error(admin_trans('admin.old_password_error'));
}
});
});
}
/**
* 个人信息
* @auth true
* @group all
* @return Form
*/
public function editInfo(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->text('username', admin_trans('admin.fields.username'))
->ruleChsDash()->disabled();
$form->text('nickname', admin_trans('admin.fields.nickname'))
->ruleChsAlphaNum();
$form->image('avatar', admin_trans('admin.fields.avatar'));
$form->text('phone', admin_trans('admin.fields.phone'))
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'))->ignore($form->input('id')) => admin_trans('admin.phone_exist'),
])
->ruleMobile();
$form->text('email', admin_trans('admin.fields.mail'))->ruleEmail();
});
}
/**
* 重置密码
* @auth true
* @group all
* @param $id
* @return Form
*/
public function resetPassword($id): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->password('password', admin_trans('admin.new_password'))
->rule([
'confirmed' => admin_trans('admin.password_confim_validate'),
'min:6' => admin_trans('admin.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('admin.confim_password'))
->required();
});
}
}

View File

@@ -0,0 +1,274 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\form\MyEditor;
use addons\webman\model\AppVersion;
use addons\webman\model\Channel;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\form\Watch;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\support\Request;
use RarArchive;
use Respect\Validation\Exceptions\Exception;
use ZipArchive;
/**
* 版本管理
*/
class AppVersionController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.app_version_model');
}
/**
* 版本
* @auth true
* @return Card
*/
public function index(): Card
{
return Card::create(Tabs::create()
->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID), $this->androidList())
->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS), $this->iosList())
->type('card')
->destroyInactiveTabPane()
);
}
/**
* 安装版本
* @return Grid
*/
public function androidList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->model()->where('system_key', AppVersion::SYSTEM_KEY_ANDROID)->orderBy('id', 'desc');
$this->getList($grid, AppVersion::SYSTEM_KEY_ANDROID);
});
}
/**
* 苹果版本
* @return Grid
*/
public function iosList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->model()->where('system_key', AppVersion::SYSTEM_KEY_IOS)->orderBy('id', 'desc');
$this->getList($grid, AppVersion::SYSTEM_KEY_IOS);
});
}
/**
* 版本列表
* @param $grid
* @param $systemKey
*/
public function getList($grid, $systemKey)
{
$grid->title(admin_trans('app_version.title'));
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->bordered(true);
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('system_key', admin_trans('app_version.fields.system_key'))->align('center');
$grid->column('app_version', admin_trans('app_version.fields.app_version'));
$grid->column('app_version_key', admin_trans('app_version.fields.app_version_key'))->align('center');
$grid->column('apk_url', admin_trans('app_version.fields.apk_url'))->align('center');
$grid->column('force_update', admin_trans('app_version.fields.force_update'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('hot_update', admin_trans('app_version.fields.hot_update'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('regular_update', admin_trans('app_version.fields.regular_update'))->align('center');
$grid->column('notes', admin_trans('app_version.fields.notes'))->align('center');
$grid->column('status', admin_trans('app_version.fields.status'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('created_at', admin_trans('app_version.fields.created_at'))->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->filter(function (Filter $filter) {
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('channel.fields.name'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->eq()->select('status')
->placeholder(admin_trans('app_version.fields.status'))
->options([
1 => admin_trans('post.normal'),
0 => admin_trans('post.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->setForm()->drawer($this->form($systemKey));
$grid->quickSearch();
}
/**
* 添加修改版本
* @auth true
*/
public function form($systemKey): Form
{
ini_set('memory_limit', '512M');
Form::extend('myEditor', MyEditor::class);
return Form::create(new $this->model, function (Form $form) use ($systemKey) {
$form->title(admin_trans('app_version.title'));
$form->radio('system_key', admin_trans('app_version.fields.system_key'))
->button()
->default($systemKey)
->options([
AppVersion::SYSTEM_KEY_ANDROID => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID),
AppVersion::SYSTEM_KEY_IOS => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS),
])->required();
$form->dateTime('regular_update', admin_trans('app_version.fields.regular_update'))->required();
$form->select('department_id', admin_trans('slider.fields.department_id'))
->options($this->getChannelOptions())->required();
$form->text('app_version', admin_trans('app_version.fields.app_version'))->rule([
'regex:/^\d+\.\d+\.\d+$/' => admin_trans('app_version.app_version_regex')
])->maxlength(50)->required();
$form->text('app_version_key', admin_trans('app_version.fields.app_version_key'))->disabled(true)->maxlength(50)->required();
$form->watch([
'app_version' => function ($value, Watch $watch) {
$versionNumbers = explode('.', $value);
$newVersion = implode('', $versionNumbers);
$watch['app_version_key'] = $newVersion;
},
]);
$form->row(function (Form $form) {
$form->switch('status', admin_trans('app_version.fields.status'))->span(8)->required();
$form->switch('force_update', admin_trans('app_version.fields.force_update'))->span(8)->required();
$form->switch('hot_update', admin_trans('app_version.fields.hot_update'))
->default(0)
->when('==', 1, function (Form $form) {
$form->file('apk_url', admin_trans('app_version.hot_apk_url'))
->directory('app_version')
->type('file')
->ext(['zip'])
->chunkSize(1)
->chunk()
->limit(1)
->fileSize('200MB')->hideFinder()->required();
})->when('==', 0, function (Form $form) {
$form->text('apk_url', admin_trans('app_version.fields.apk_url'))->ruleUrl()->maxlength(200)->required();
})
->span(8)
->required();
}, null);
$form->textarea('notes', admin_trans('app_version.fields.notes'))->maxlength(125)->bindAttr('rows', 3);
$form->myEditor('update_content', admin_trans('app_version.fields.update_content'));
$form->hidden('user_id')->value(!empty(Admin::user()) ? Admin::user()->id : 0);
$form->hidden('user_name')->value(!empty(Admin::user()) ? Admin::user()->username : '');
$form->hidden('hot_update_url');
$form->layout('vertical');
$form->saving(function (Form $form) {
$apkUrl = $form->input('apk_url');
$hotUpdate = $form->input('hot_update');
$hotUpdateUrl = $form->input('hot_update_url');
$appVersionKey = $form->input('app_version_key');
if (!$apkUrl) {
return message_error(admin_trans('app_version.missing_package_address'));
}
if (!$appVersionKey) {
return message_error(admin_trans('app_version.app_version_key_not_found'));
}
if (AppVersion::query()->where('department_id', $form->input('department_id'))->where('app_version_key', $appVersionKey)->exists()) {
return message_error(admin_trans('app_version.app_version_key_exists'));
}
if ($hotUpdate == 1) {
$apkUrl = str_replace(env('APP_DOMAIN'), '', $apkUrl);
if (!file_exists(public_path() . $apkUrl)) {
return message_error(admin_trans('app_version.upload_update_package'));
}
if (empty($hotUpdateUrl)) {
$extension = pathinfo($apkUrl, PATHINFO_EXTENSION);
$fileName = pathinfo($apkUrl, PATHINFO_FILENAME);
if (!$extension || !$fileName) {
return message_error(admin_trans('app_version.hot_apk_url_error'));
}
// 解压压缩包
$hotUrl = $this->decompression($appVersionKey, $extension, $apkUrl);
$form->input('hot_update_url', $hotUrl);
}
}
});
});
}
/**
* 筛选部门/渠道
* @return array
*/
public function getChannelOptions(): array
{
$channelList = Channel::query()->orderBy('created_at', 'desc')->get();
$data = [];
/** @var Channel $channel */
foreach ($channelList as $channel) {
$data[$channel->department_id] = $channel->name;
}
return $data;
}
/**
* @param $appVersionKey
* @param string $type
* @param string $file
* @return string|void
* @throws \Exception
*/
public function decompression($appVersionKey, string $type = '', string $file = '')
{
try {
$file = public_path() . $file;
$savePath = '/storage/app_version/' . $appVersionKey;
$newPath = public_path() . $savePath;
if (!file_exists($newPath)) {
//检查是否有该文件夹,如果没有就创建,并给予最高权限
mkdir($newPath, 0755, true);
}
switch ($type) {
case 'zip':
$zip = new ZipArchive;
if ($zip->open($file) === TRUE) {
$zip->extractTo($newPath);
$zip->close();
return env('APP_DOMAIN') . $savePath;
} else {
throw new \Exception(admin_trans('app_version.decompression_failed'));
}
case 'rar':
$file = RarArchive::open($file);
if ($file !== FALSE) {
$entries = $file->getEntries();
foreach ($entries as $entry) {
$entry->extract($newPath);
}
$file->close();
return env('APP_DOMAIN') . $savePath;
} else {
throw new \Exception(admin_trans('app_version.decompression_failed'));
}
}
} catch (Exception $e) {
throw new \Exception($e->getMessage());
}
}
}

View File

@@ -0,0 +1,153 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\DownloadFile;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\field\upload\Upload;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\component\grid\ToolTip;
use Illuminate\Database\Eloquent\Builder;
/**
* 附件管理
*/
class AttachmentController
{
protected $attachmentModel;
protected $attachmentCateModel;
public function __construct()
{
$this->attachmentModel = plugin()->webman->config('database.attachment_model');
$this->attachmentCateModel = plugin()->webman->config('database.attachment_cate_model');
}
/**
* 附件
* @auth true
* @param string $type image图片 file文件
* @param int $size 文件大小
* @param array $ext 文件后缀
* @param string $customStyle
* @param string $selectionField
* @return Grid
*/
public function index($type = '', $size = 0, $ext = [],$customStyle='card',$selectionField=''): Grid
{
$grid = Grid::create(new $this->attachmentModel);
if($selectionField){
$grid->selectionField($selectionField);
}
$grid->title(admin_trans('attachment.title'));
$grid->model()->when($type, function (Builder $q, $value) {
$q->where('type', $value);
})->when($ext, function (Builder $q, $value) {
$q->whereIn('ext', $value);
})->when($size, function (Builder $q, $value) {
$q->where('size', '<=', $value);
});
$grid->hideTrashed();
$grid->autoHeight();
$grid->sidebar('cate_id', new $this->attachmentCateModel)
->model(function (Builder $builder) {
$builder->where(function (Builder $q) {
$q->orWhere('admin_id', Admin::id())->orWhere('permission_type', 0);
});
})
->setForm($this->cate())
->tree();
$grid->custom(function ($data) {
return Html::create([
Image::create()
->src($data['url'])
->style(['object-fit' => 'contain'])
->width(80)
->height(80)->whenShow($data['type'] == 'image'),
DownloadFile::create()
->onlyImage()
->style(['object-fit' => 'contain'])
->width(80)
->height(80)
->url($data['url'])->whenShow($data['type'] == 'file'),
ToolTip::create()->title($data['real_name'])
->placement('bottom')
->content(
Html::create($data['real_name'])
->style(['white-space' => 'nowrap', 'text-overflow' => 'ellipsis', 'overflow' => 'hidden', 'width' => '100%'])
),
])->style(['display' => 'flex', 'align-items' => 'center', 'flex-direction' => 'column', 'text-align' => 'center']);
}, 'ACard',$customStyle)->grid(10, 6)
->when($customStyle=='card',function ($list){
$list->class('ant-card')->style(['padding'=>'0 10px']);
});
$grid->pagination()->pageSize(24);
$grid->actions(function (Actions $actions, $data) {
$actions->icon();
$actions->prepend(
Button::create()
->icon('<cloud-download-outlined />')
->size('small')
->shape('circle')
->redirect($data['url'])
);
});
$grid->quickSearch('real_name');
$grid->vModel('selectedSidebar');
$grid->tools(
Upload::create()
->multiple()
->action('ex-admin/addons-webman-controller-AttachmentController/upload')
->bindAttr('params', ['cate_id' => $grid->bindAttr('selectedSidebar')])
->style(['marginLeft' => '8px'])
->eventCustom('success', 'GridRefresh')
,false);
return $grid;
}
/**
* 上传
* @return mixed
*/
public function upload()
{
$class = plugin()->webman->config('form.uploader');
$simpleUploader = new $class;
return $simpleUploader->upload();
}
/**
* 附件分类
* @auth true
*/
public function cate()
{
return Form::create(new $this->attachmentCateModel(),function (Form $form){
$options = $this->attachmentCateModel::where('admin_id', Admin::id())->get()->toArray();
array_unshift($options, ['id' => 0, 'name' => admin_trans('attachment.cate.parent'), 'pid' => -1]);
$form->treeSelect('pid', admin_trans('attachment.cate.fields.pid'))
->default(0)
->required()
->options($options);
$form->text('name', admin_trans('attachment.cate.fields.name'))->required();
$form->radio('permission_type', admin_trans('attachment.cate.fields.permission_type'))
->options([
0 => admin_trans('attachment.cate.public'),
1 => admin_trans('attachment.cate.private'),
])
->default(0);
$form->number('sort', admin_trans('attachment.cate.fields.sort'))->default($this->attachmentCateModel::max('sort') + 1);
$form->input('admin_id', Admin::id());
});
}
}

View File

@@ -0,0 +1,202 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminDepartment;
use addons\webman\model\AdminUser;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\badge\Badge;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\support\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Validation\Rule;
/**
* 渠道用户管理
* @group channel
*/
class ChannelAdminController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.user_model');
}
/**
* 渠道用户
* @group channel
* @auth true
*/
public function index(): Grid
{
/** @var AdminUser $superAdmin */
$superAdmin = AdminUser::where('department_id', Admin::user()->department_id)->where('is_super', 1)->first();
return Grid::create(new $this->model, function (Grid $grid) use($superAdmin){
$grid->title(admin_trans('admin.system_user'));
$grid->model()
->when(plugin()->webman->config('admin_auth_id') != Admin::id(), function (Builder $builder) {
$builder->whereKeyNot(plugin()->webman->config('admin_auth_id'));
})->where('department_id', Admin::user()->department_id);
$grid->bordered(true);
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->userInfo();
$grid->column('username', admin_trans('admin.fields.username'))->display(function ($val, $data) {
if ($data['id'] == plugin()->webman->config('admin_auth_id')) {
return Html::create()
->content($val)
->content(
Badge::create()->count(admin_trans('admin.super_admin'))->numberStyle(['backgroundColor' => '#1890ff', 'marginLeft' => '5px'])
);
} else {
return $val;
}
})->copy();
$grid->column('phone', admin_trans('admin.fields.phone'));
$grid->column('email', admin_trans('admin.fields.mail'));
$grid->column('status', admin_trans('admin.fields.status'))->switch();
$grid->column('type', admin_trans('admin.fields.type'))
->display(function ($value, AdminUser $data) {
if ($data->is_super == 1) {
$tag = Tag::create(admin_trans('admin.fields.is_super'))->color('#3b5999');
} else {
$tag = Tag::create(admin_trans('department.type.' . AdminDepartment::TYPE_CHANNEL))->color('#f50');
}
return Html::create()->content([
$tag,
]);
})->sortable();
$grid->column('created_at', admin_trans('admin.fields.create_at'));
$grid->quickSearch();
$grid->hideDelete();
$grid->setForm()->modal($this->form());
$grid->filter(function (Filter $filter) {
$filter->like()->text('username')->placeholder(admin_trans('admin.fields.username'));
$filter->like()->text('phone')->placeholder(admin_trans('admin.fields.phone'));
$filter->eq()->select('status')
->placeholder(admin_trans('admin.fields.status'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
1 => admin_trans('admin.normal'),
0 => admin_trans('admin.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.date_start'), admin_trans('public_msg.date_end')]);
});
$grid->actions(function (Actions $actions, $data) use($superAdmin){
if ($data['id'] == $superAdmin->id) {
$actions->hideDel();
}
if ($data['id'] != $superAdmin->id) {
$actions->dropdown()
->prepend(admin_trans('admin.reset_password'), 'fas fa-key')
->modal($this->resetPassword($data['id']));
} else {
$actions->dropdown();
}
});
$grid->deling(function ($ids) use($superAdmin){
if (is_array($ids) && in_array($superAdmin->id, $ids)) {
return message_error(admin_trans('admin.super_admin_delete'));
}
});
$grid->updateing(function ($ids, $data) use($superAdmin){
if (in_array($superAdmin->id, $ids)) {
if (isset($data['status']) && $data['status'] == 0) {
return message_error(admin_trans('admin.super_admin_disabled'));
}
}
});
});
}
/**
* 重置密码
* @auth true
* @group channel
* @param $id
* @return Form
*/
public function resetPassword($id): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->password('password', admin_trans('admin.new_password'))
->rule([
'confirmed' => admin_trans('admin.password_confim_validate'),
'min:6' => admin_trans('admin.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('admin.confim_password'))
->required();
});
}
/**
* 系统用户
* @group channel
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('admin.system_user'));
$form->text('username', admin_trans('admin.fields.username'))
->ruleChsDash()
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'))->ignore($form->input('id')) => admin_trans('admin.username_exist'),
])
->required()
->disabled($form->isEdit());
$form->text('nickname', admin_trans('admin.fields.nickname'))
->ruleChsAlphaNum()
->required();
$form->image('avatar', admin_trans('admin.fields.avatar'))
->required();
if (!$form->isEdit()) {
$form->password('password', admin_trans('admin.fields.password'))
->default(123456)
->help(admin_trans('admin.pass_help'))
->required();
}
$form->text('phone', admin_trans('admin.fields.phone'))
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'))->ignore($form->input('id')) => admin_trans('admin.phone_exist'),
])
->ruleMobile();
$form->text('email', admin_trans('admin.fields.mail'))->ruleEmail();
$form->hidden('department_id')->default(Admin::user()->department_id);
if (!$form->isEdit() || $form->driver()->get('is_super') != 1) {
$roleModel = plugin()->webman->config('database.role_model');
$role = $roleModel::where('type', AdminDepartment::TYPE_CHANNEL)->pluck('name', 'id')->toArray();
$form->checkbox('roles', admin_trans('admin.access_rights'))
->options($role);
$post = plugin()->webman->config('database.post_model');
$options = $post::where('status', 1)->pluck('name', 'id')->toArray();
$form->select('post', admin_trans('admin.post'))
->options($options)
->multiple();
}
});
}
}

View File

@@ -0,0 +1,380 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\AdminDepartment;
use addons\webman\model\AdminRole;
use addons\webman\model\AdminRoleUsers;
use addons\webman\model\AdminUser;
use addons\webman\model\Channel;
use ExAdmin\ui\component\common\Copy;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Arr;
use ExAdmin\ui\support\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use support\Db;
/**
* 渠道管理
*/
class ChannelController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.channel_model');
}
/**
* 渠道
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('channel.title'));
$grid->model()->with(['department'])->orderBy('created_at', 'desc');
$grid->autoHeight();
$grid->bordered(true);
$grid->column('department_id', admin_trans('channel.fields.id'))->align('center')->fixed(true);
$grid->column('name', admin_trans('channel.fields.name'))->align('center')->fixed(true);
$grid->column('department.leader', admin_trans('channel.fields.leader'))->align('center')->copy()->fixed(true);
$grid->column('department.phone', admin_trans('channel.fields.phone'))->align('center')->copy();
$grid->column('player_num', admin_trans('channel.fields.player_num'))->display(function ($val, Channel $data) {
return $data->player->count();
})->align('center');
$grid->column('created_at', admin_trans('channel.fields.create_at'))->align('center');
$grid->column('status', admin_trans('channel.fields.status'))->switch();
$grid->column('lang', admin_trans('channel.fields.lang'))->display(function ($val) {
return Html::create()->content([
admin_config('ui.lang.list')[$val] ?? ''
]);
})->align('center');
$grid->column('currency', admin_trans('channel.fields.currency'))->align('center');
$grid->column('pay_type', admin_trans('channel.fields.pay_type'))->display(function ($val) {
return Html::create()->content([
admin_trans('channel.pay_type.'.$val)
]);
})->align('center')->align('center');
$grid->column('game_id', admin_trans('channel.fields.game_id'))->display(function ($val) {
return Html::create()->content([
admin_trans('channel.game.'.$val)
]);
})->align('center')->align('center');
$grid->column('channel_function', admin_trans('channel.fields.channel_function'))->display(function ($value, Channel $channel) {
$channelFunction = [];
if ($channel->web_login_status == 1) {
$channelFunction[] = 'web_login_status';
}
if ($channel->recharge_status == 1) {
$channelFunction[] = 'recharge_status';
}
if ($channel->withdraw_status == 1) {
$channelFunction[] = 'withdraw_status';
}
if ($channel->wallet_action_status == 1) {
$channelFunction[] = 'wallet_action_status';
}
if ($channel->promotion_status == 1) {
$channelFunction[] = 'promotion_status';
}
$html = Html::create();
foreach ($channelFunction as $option) {
$html->content(
Tag::create(admin_trans('channel.fields.' . $option))
->color('success')
);
}
return $html;
})->align('center');
$grid->column('player_total_amount', admin_trans('channel.fields.player_total_amount'))->display(function ($val, Channel $data) {
return $data->wallet()->sum('money');
})->align('center');
$grid->column('domain', admin_trans('channel.fields.domain'))->display(function ($value) {
return ToolTip::create(Str::of($value)->limit(30, ' (...)'))->title($value);
})->width('150px')->align('center')->ellipsis(true)->copy();
$grid->column('telegram_url', admin_trans('channel.fields.whats_app'))->display(function ($value) {
return ToolTip::create(Str::of($value)->limit(30, ' (...)'))->title($value);
})->width('150px')->align('center')->ellipsis(true)->copy();
$grid->column('package_url', admin_trans('channel.fields.package_url'))->display(function ($value) {
return ToolTip::create(Str::of($value)->limit(30, ' (...)'))->title($value);
})->width('150px')->align('center')->ellipsis(true)->copy();
$grid->hideDelete();
$grid->setForm()->drawer($this->form());
$grid->filter(function (Filter $filter) {
$filter->eq()->text('id')->placeholder(admin_trans('channel.fields.id'));
$filter->like()->text('name')->placeholder(admin_trans('channel.fields.name'));
$filter->like()->text('phone')->placeholder(admin_trans('channel.fields.phone'));
$filter->like()->text('leader')->placeholder(admin_trans('channel.fields.leader'));
$filter->eq()->select('status')
->placeholder(admin_trans('channel.fields.status'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
1 => admin_trans('channel.normal'),
0 => admin_trans('channel.disable')
]);
});
$grid->quickSearch(function (Builder $builder, $quickSearch) {
$builder->whereHas('department', function ($query) use ($quickSearch) {
$query->where([
['leader', 'like', '%' . $quickSearch . '%', 'or'],
['phone', 'like', '%' . $quickSearch . '%', 'or'],
]);
})->orWhere('id', $quickSearch)
->orWhere('name', $quickSearch)
->orWhere('domain', $quickSearch);
});
$grid->deleted(function ($ids) {
DB::beginTransaction();
try {
$departmentIds = Arr::pluck(Channel::select('department_id')->whereIn('id', $ids)->withTrashed()->get()->toArray(), 'department_id');
AdminDepartment::whereIn('id', $departmentIds)->delete();
AdminUser::whereIn('department_id', $departmentIds)->delete();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
}
});
});
}
/**
* 渠道
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('channel.title'));
$form->row(function (Form $form) {
$form->text('name', admin_trans('channel.fields.name'))
->ruleChsDash()
->rule([
(string)Rule::unique(plugin()->webman->config('database.channel_model'))->ignore($form->input('id')) => admin_trans('channel.name_exist'),
])
->required();
$form->text('domain', admin_trans('channel.fields.domain'))
->ruleUrl()
->rule([
(string)Rule::unique(plugin()->webman->config('database.channel_model'))->ignore($form->input('id')) => admin_trans('channel.channel_exist'),
])
->required()->style(['margin-left' => '10px']);
});
$form->row(function (Form $form) {
$form->text('department.phone', admin_trans('channel.fields.phone'))->ruleNumber();
$form->text('department.leader', admin_trans('channel.fields.leader'))->style(['margin-left' => '10px']);
});
$form->text('telegram_url', admin_trans('channel.fields.whats_app'))
->ruleUrl()
->rule([
(string)Rule::unique(plugin()->webman->config('database.channel_model'))->ignore($form->input('id')) => admin_trans('channel.telegram_url_exist'),
])
->required();
$form->text('package_url', admin_trans('channel.fields.package_url'))
->ruleUrl()
->rule([
(string)Rule::unique(plugin()->webman->config('database.channel_model'))->ignore($form->input('id')) => admin_trans('channel.package_url_exist'),
])
->required();
$form->radio('currency', admin_trans('channel.fields.currency'))
->button()
->options(plugin()->webman->config('currency'))
->required();
$form->radio('lang', admin_trans('channel.fields.lang'))
->button()
->options(admin_config('ui.lang.list'))
->required();
$form->radio('game_id', admin_trans('channel.fields.game_id'))
->button()
->options(plugin()->webman->config('game'))
->required();
$form->row(function (Form $form) {
if (!$form->isEdit()) {
$form->text('user.username', admin_trans('channel.fields.username'))
->ruleChsDash()
->rule([
(string)Rule::unique(plugin()->webman->config('database.user_model'), 'username')->ignore($form->input('id')) => admin_trans('admin.username_exist'),
])
->required()
->addonAfter(Copy::create($form->input('user.username')))
->disabled($form->isEdit());
$form->password('user.password', admin_trans('channel.fields.password'))
->default(123456)
->help(admin_trans('admin.pass_help'))
->required();
} else {
$form->text('user.username', admin_trans('channel.fields.username'))
->ruleChsDash()
->addonAfter(Copy::create($form->input('user.username')))
->disabled($form->isEdit());
}
});
$channelFunction = [];
if ($form->isEdit()) {
$id = $form->driver()->get('id');
/** @var Channel $channel */
$channel = Channel::find($id);
if ($channel->recharge_status == 1) {
$channelFunction[] = 'recharge_status';
}
if ($channel->withdraw_status == 1) {
$channelFunction[] = 'withdraw_status';
}
if ($channel->web_login_status == 1) {
$channelFunction[] = 'web_login_status';
}
if ($channel->wallet_action_status == 1) {
$channelFunction[] = 'wallet_action_status';
}
if ($channel->promotion_status == 1) {
$channelFunction[] = 'promotion_status';
}
}
$form->row(function (Form $form) use ($channelFunction) {
$form->checkbox('channel_function', admin_trans('channel.fields.channel_function'))
->value($channelFunction)
->options([
'web_login_status' => admin_trans('channel.fields.web_login_status'),
'recharge_status' => admin_trans('channel.fields.recharge_status'),
'withdraw_status' => admin_trans('channel.fields.withdraw_status'),
'wallet_action_status' => admin_trans('channel.fields.wallet_action_status'),
'promotion_status' => admin_trans('channel.fields.promotion_status'),
]);
});
$form->layout('vertical');
$form->saving(function (Form $form) {
$channelFunction = $form->input('channel_function');
if (!empty($channelFunction)) {
$artificial = collect(['recharge_status', 'withdraw_status']);
$intersectArtificial = $artificial->intersect($channelFunction)->toArray();
if (!empty($intersectArtificial) && !empty($intersectQTalk)) {
return message_error(admin_trans('channel.channel_function_help'));
}
}
if (!$form->isEdit()) {
DB::beginTransaction();
try {
$adminDepartment = new AdminDepartment();
$adminDepartment->name = $form->input('name');
$adminDepartment->leader = $form->input('department.leader');
$adminDepartment->phone = $form->input('department.phone');
$adminDepartment->type = AdminDepartment::TYPE_CHANNEL;
$adminDepartment->save();
$adminUser = new AdminUser();
$adminUser->username = $form->input('user.username');
$adminUser->password = $form->input('user.password');
$adminUser->nickname = $form->input('name');
$adminUser->department_id = $adminDepartment->id;
$adminUser->type = AdminDepartment::TYPE_CHANNEL;
$adminUser->is_super = 1;
$adminUser->save();
$adminRole = new AdminRoleUsers();
$adminRole->role_id = AdminRole::ROLE_CHANNEL;
$adminRole->user_id = $adminUser->id;
$adminRole->save();
$channel = new Channel();
$channel->name = $form->input('name');
$channel->domain = $form->input('domain');
$channel->telegram_url = $form->input('telegram_url');
$channel->package_url = $form->input('package_url');
$channel->lang = $form->input('lang');
$channel->game_id = $form->input('game_id');
$channel->currency = $form->input('currency');
$channel->pay_type = $form->input('pay_type') ?? 4;
$channel->department_id = $adminDepartment->id;
$channel->user_id = $adminUser->id;
$channel->site_id = gen_uuid(); // 站点标识
$channel->recharge_status = in_array('recharge_status', $channelFunction);
$channel->withdraw_status = in_array('withdraw_status', $channelFunction);
$channel->web_login_status = in_array('web_login_status', $channelFunction);
$channel->wallet_action_status = in_array('wallet_action_status', $channelFunction);
$channel->promotion_status = in_array('promotion_status', $channelFunction);
$channel->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
$adminDepartment->path = $adminDepartment->id;
$adminDepartment->save();
return message_success(admin_trans('channel.save_success'));
} else {
$orgData = $form->driver()->get();
/** @var Channel $channel */
$channel = Channel::find($orgData['id']);
if (empty($channel)) {
return message_error(admin_trans('channel.not_fount'));
}
DB::beginTransaction();
try {
$channel->name = $form->input('name');
$channel->domain = $form->input('domain');
$channel->telegram_url = $form->input('telegram_url');
$channel->package_url = $form->input('package_url');
$channel->lang = $form->input('lang');
$channel->game_id = $form->input('game_id');
$channel->currency = $form->input('currency');
$channel->pay_type = $form->input('pay_type') ?? 4;
$channel->recharge_status = in_array('recharge_status', $channelFunction);
$channel->withdraw_status = in_array('withdraw_status', $channelFunction);
$channel->web_login_status = in_array('web_login_status', $channelFunction);
$channel->wallet_action_status = in_array('wallet_action_status', $channelFunction);
$channel->status = $form->input('status');
$channel->promotion_status = in_array('promotion_status', $channelFunction);
$channel->save();
/** @var AdminDepartment $adminDepartment */
$adminDepartment = AdminDepartment::find($channel->department_id);
$adminDepartment->name = $form->input('name');
$adminDepartment->leader = $form->input('department.leader');
$adminDepartment->phone = $form->input('department.phone');
$adminDepartment->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('channel.save_error'));
}
return message_success(admin_trans('channel.save_success'));
}
});
});
}
/**
* 筛选部门/渠道
* @return mixed
*/
public function getDepartmentOptions()
{
$request = Request::input();
$channel = Channel::orderBy('created_at', 'desc');
if (!empty($request['search'])) {
$channel->where('name', 'like', '%' . $request['search'] . '%');
}
$channelList = $channel->get();
$data = [];
/** @var Channel $channel */
foreach ($channelList as $channel) {
$data[] = [
'value' => $channel->department_id,
'label' => $channel->name,
];
}
return Response::success($data);
}
}

View File

@@ -0,0 +1,420 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\Game;
use addons\webman\model\GamePlatform;
use addons\webman\model\Player;
use addons\webman\model\Prize;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Notification;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Request;
use support\Db;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Actions;
use addons\webman\model\GameType;
use Tinywan\Jwt\JwtToken;
/**
* 渠道游戏平台
* @group channel
*/
class ChannelGameController
{
protected $game;
protected $prize;
public function __construct()
{
$this->game = plugin()->webman->config('database.game_model');
$this->prize = plugin()->webman->config('database.prize_model');
}
/**
* 游戏列表
* @group channel
* @auth true
* @return Grid
*/
public function index(): Grid
{
return Grid::create(new $this->game(), function (Grid $grid) {
$grid->title(admin_trans('game.title'));
if (plugin()->webman->config('admin_auth_id') != Admin::id()){
$gameId = Channel::query()->where('department_id', Admin::user()['department_id'])->value('game_id');
$grid->model()->where('id', $gameId);
}
$grid->model()->orderBy('status', 'desc')->orderBy('id', 'asc');
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('game.fields.id'))->align('center');
$grid->column('logo', 'LOGO')->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->style(['border-radius' => '50%', 'objectFit' => 'cover'])
->src($data['logo']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('name', admin_trans('game.fields.name'))->align('center');
$grid->column('game_image', admin_trans('game.fields.game_image'))->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->style(['border-radius' => '50%', 'objectFit' => 'cover'])
->src($data['game_image']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('description', admin_trans('game.fields.description'))->align('center');
$grid->column('status', admin_trans('game_platform.fields.status'))->switch()->align('center');
$grid->column('updated_at', admin_trans('game.fields.updated_at'))->align('center');
$grid->expandFilter();
$grid->actions(function (Actions $actions, $data) {
$actions->hideDel();
$actions->prepend(
Button::create(admin_trans('game.enter_game'))->ajax([$this, 'enterGame'],
['id' => $data['id']])
);
$actions->prepend(
Button::create(admin_trans('game.view_prize'))->modal([$this, 'getPrizeList'],
['id' => $data['id']])->width('100%')
);
})->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->hideAdd();
$grid->hideTrashed();
});
}
/**
* 进入游戏
* @param $id
* @group channel
* @auth true
* @return Notification
*/
public function enterGame($id): Notification
{
$game = Game::query()->where('id', $id)->first();
if (empty($game->test_url)) {
$player = Player::query()->where('test', 1)->find($id);
$channel = Channel::query()->whereJsonContains('game_id', $id)->first();
if (empty($channel) || empty($player)) {
return notification_error(admin_trans('admin.success'),admin_trans('game_platform.action_error'))->redirect('');
}
$token = JwtToken::generateToken([
'id' => $player->uuid,
'account' => $player->account,
'game_id' => $id,
'app_id' => $channel->externalApp->app_id,
'channel' => openssl_encrypt($channel->externalApp->app_secret, 'DES-ECB', config('app.channel_des_key')),
'access_exp' => 864000000,
'refresh_exp' => 864000000,
]);
$url = $game->game_url . $id . '?access_token=' . $token['access_token'];
} else {
$url = $game->test_url;
}
return notification_success(admin_trans('admin.success'),
admin_trans('game_platform.action_success'))->redirect($url);
}
/**
* 游戏详情
* @auth true
* @group channel
* @return Form
*/
public function form(): Form
{
return Form::create(new $this->game(), function (Form $form) {
$form->title(admin_trans('prize.title'));
$form->text('name', admin_trans('game.fields.name'))->required()->maxlength(50);
$form->image('logo', admin_trans('game.fields.logo'))
->required();
$form->image('game_image', admin_trans('game.fields.game_image'))
->required();
$form->textarea('description', admin_trans('game.fields.description'))->maxlength(500)->bindAttr('rows', 10);
$form->layout('vertical');
});
}
/**
* 查看奖品
* @param $id
* @group channel
* @return Grid
* @auth true
*/
public function getPrizeList($id): Grid
{
$num = Game::query()->where('id', $id)->value('prize_num');
$prizeNum = Prize::query()->where('game_id', $id)
->where('department_id', Admin::user()->department_id)
->where('status', 1)
->count();
if ($prizeNum < $num) {
for ($j = $num - $prizeNum; $j >= 1; $j--) {
Prize::query()->create([
'game_id' => $id,
'department_id' => Admin::user()->department_id,
'name' => '奖品名称',
'probability' => 0,
'type' => 1,
'total_stock' => 0,
'daily_stock' => 0,
'total_remaining' => 0,
'daily_remaining' => 0,
'admin_id' => Admin::id(),
'admin_name' => Admin::user()->username,
]);
}
}
return Grid::create(new $this->prize(), function (Grid $grid) use($id) {
$grid->title(admin_trans('prize.title'));
$grid->model()->where('game_id', $id)->where('department_id', Admin::user()->department_id)->orderBy('probability');
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('prize.fields.id'))->align('center')->width('5%');
$grid->column('name', admin_trans('prize.fields.name'))->align('center')->width('10%');
$grid->column('type', admin_trans('prize.fields.type'))->display(function ($val) {
return admin_trans('prize.prize_type.' . $val);
})->align('center')->width('10%');
$grid->column('pic', admin_trans('prize.fields.pic'))->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->src($data['pic']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('probability', admin_trans('prize.fields.probability'))->align('center')->width('10%');
$grid->column('total_stock', admin_trans('prize.fields.total_stock'))->align('center')->width('8%');
$grid->column('daily_stock', admin_trans('prize.fields.daily_stock'))->align('center')->width('8%');
$grid->column('total_remaining', admin_trans('prize.fields.total_remaining'))->align('center')->width('8%');
$grid->column('daily_remaining', admin_trans('prize.fields.daily_remaining'))->align('center')->width('8%');
$grid->column('description', admin_trans('prize.fields.description'))->align('center')->width('20%');
$grid->column('admin_name', admin_trans('prize.fields.admin_name'))->align('center')->width('8%');
$grid->column('updated_at', admin_trans('prize.fields.updated_at'))->align('center')->width('8%');
$grid->expandFilter();
$grid->setForm()->drawer($this->editPrize($id));
$grid->actions(function (Actions $actions, $data) {
$actions->hideDel();
$actions->prepend(
Button::create(admin_trans('prize.replenish_daily_stock'))->ajax([$this, 'replenishDailyStock'],
['id' => $data['id']])
);
})->align('center');
$grid->hideDelete();
$grid->hideAdd();
$grid->hideSelection();
$grid->hideTrashed();
});
}
/**
* 补充每日库存
* @param $id
* @group channel
* @auth true
* @return Msg
*/
public function replenishDailyStock($id): Msg
{
/** @var Prize $prize */
$prize = Prize::query()->where('id', $id)->first();
if ($prize->daily_remaining < $prize->daily_stock) {
$diff = $prize->daily_stock - $prize->daily_remaining;
$prize->daily_remaining = $prize->daily_stock;
$prize->total_remaining = $prize->total_remaining + $diff;
$prize->total_stock = $prize->total_stock + $diff;
}
$prize->save();
return message_success(admin_trans('prize.action_success'));
}
/**
* 奖品详情
* @auth true
* @group channel
* @param $gameId
* @return Form
*/
public function editPrize($gameId): Form
{
return Form::create(new $this->prize(), function (Form $form) use ($gameId) {
$form->title(admin_trans('prize.title'));
$form->text('name', admin_trans('prize.fields.name'))->required()->maxlength(50);
$form->select('type', admin_trans('prize.fields.type'))->options([
Prize::PRIZE_TYPE_PHYSICAL => admin_trans('prize.prize_type.' . Prize::PRIZE_TYPE_PHYSICAL),
Prize::PRIZE_TYPE_VIRTUAL => admin_trans('prize.prize_type.' . Prize::PRIZE_TYPE_VIRTUAL),
Prize::PRIZE_TYPE_LOSE => admin_trans('prize.prize_type.' . Prize::PRIZE_TYPE_LOSE),
])->required();
$form->image('pic', admin_trans('prize.fields.pic'));
$form->hidden('game_id')->default($gameId);
$form->number('probability', admin_trans('prize.fields.probability'))->min(1)->max(999)->required();
$form->number('total_stock', admin_trans('prize.fields.total_stock'))->min(1)->max(100000)->required();
$form->number('daily_stock', admin_trans('prize.fields.daily_stock'))->min(1)->max(100000)
->help(admin_trans('prize.daily_stock_help'))->required();
$form->textarea('description', admin_trans('prize.fields.description'))->maxlength(500)->bindAttr('rows', 10);
$form->layout('vertical');
$form->saving(function (Form $form) {
try {
if (!$form->isEdit()) {
$prize = new Prize();
$prize->game_id = $form->input('game_id');
} else {
$prizeId = $form->driver()->get('id');
$prize = Prize::query()->find($prizeId);
}
$prize->type = $form->input('type');
$prize->name = $form->input('name');
$prize->pic = $form->input('pic');
$prize->probability = $form->input('probability');
$prize->total_remaining = $form->input('total_stock');
$prize->daily_remaining = $form->input('daily_stock');
$prize->total_stock = $form->input('total_stock');
$prize->daily_stock = $form->input('daily_stock');
if ($prize->daily_stock > $prize->total_stock) {
return message_error(admin_trans('prize.daily_stock_help'));
}
$prize->description = $form->input('description');
$prize->admin_id = Admin::id();
$prize->admin_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : trans('system_automatic', [], 'message');
$prize->department_id = !empty(Admin::user()) ? Admin::user()->toArray()['department_id'] : trans('system_automatic', [], 'message');
$prize->save();
} catch (\Exception $e) {
return message_error(admin_trans('form.save_fail'));
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* 筛选游戏平台
* @return mixed
*/
public function getGamePlatformOptions()
{
$request = Request::input();
$gamePlatform = GamePlatform::query()->orderBy('created_at', 'desc');
if (!empty($request['search'])) {
$gamePlatform->where('name', 'like', '%' . $request['search'] . '%');
}
$channelList = $gamePlatform->get();
$data = [];
/** @var GamePlatform $gamePlatform */
foreach ($channelList as $gamePlatform) {
$data[] = [
'value' => $gamePlatform->id,
'label' => $gamePlatform->name,
];
}
return Response::success($data);
}
/**
* 游戏类型列表
* @auth true
*/
public function serviceList(): Grid
{
return Grid::create(new GameType(), function (Grid $grid) {
$grid->title(admin_trans('game_type.title'));
$grid->autoHeight();
$grid->bordered(true);
$grid->column('game_type', admin_trans('game_type.fields.game_type'))->display(function ($val) {
return $val ? admin_trans('game_type.game_type.' . $val) : admin_trans('game_type.nu_set');
})->align('center');
$grid->column('ratio', admin_trans('game_type.fields.ratio'))->display(function ($value) {
return $value . '%';
})->editable(
(new Editable)->number('ratio')
->min(1)
->max(100)
->addonAfter('%')
)->align('center')->ellipsis(true);
$grid->column('updated_at', admin_trans('game_type.fields.updated_at'))->align('center')->display(function ($val) {
return $val ? date('Y-m-d H:i:s', strtotime($val)) : '';
})->ellipsis(true);
$grid->actions(function (Action $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->hideDelete();
$grid->hideSelection();
$grid->hideAdd();
});
}
/**
* 游戏类型
* @auth true
*/
public function serviceForm(): Form
{
return Form::create(new GamePlatform, function (Form $form) {
$form->title(admin_trans('game_platform.game_platform'));
$form->text('name', admin_trans('game_platform.fields.name'));
$form->text('title', admin_trans('game_platform.fields.title'));
$form->number('service_ratio', admin_trans('game_platform.fields.service_ratio'))->addonAfter('%');
$form->layout('vertical');
$form->saving(function (Form $form) {
if (!$form->isEdit()) {
return message_error(admin_trans('game_platform.save_error'));
DB::beginTransaction();
try {
$gamePlatform = new GamePlatform();
$gamePlatform->name = $form->input('name');
$gamePlatform->title = $form->input('title');
$gamePlatform->service_ratio = $form->input('service_ratio');
$gamePlatform->status = 1;
$gamePlatform->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('game_platform.save_success'));
} else {
$gamePlatform = GamePlatform::find($form->input('id'));
if (empty($gamePlatform)) {
return message_error(admin_trans('game_platform.not_fount'));
}
DB::beginTransaction();
try {
$gamePlatform->name = $form->input('name');
$gamePlatform->title = $form->input('title');
$gamePlatform->service_ratio = $form->input('service_ratio');
$gamePlatform->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('game_platform.save_success'));
}
});
});
}
}

View File

@@ -0,0 +1,292 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Player;
use addons\webman\model\PlayerLoginRecord;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\echart\BarChart;
use ExAdmin\ui\component\echart\LineChart;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\layout\Divider;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use Illuminate\Support\Carbon;
use support\Db;
use support\Response;
/**
* 数据中心
* @group channel
*/
class ChannelIndexController
{
/**
* 数据中心
* @group channel
* @auth true
*/
public function index(): Layout
{
$rechargeData = $this->rechargeData();
$withdrawData = $this->withdrawData();
$playerData = $this->playerData();
$loginData = $this->loginData();
$layout = Layout::create();
$layout->row(function (Row $row) use ($rechargeData, $withdrawData, $playerData, $loginData) {
$row->gutter([10, 10]);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-globe')->style(['fontSize' => '45px', 'color' => 'rgb(0,154,97)', 'marginRight' => '20px']), 4),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.department_id'))
->value(Admin::user()->department->id ?? '')->style(['fontSize' => '45px', 'text-align' => 'center']), 6),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.department_name'))
->value(Admin::user()->department->name ?? '')->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-user')->style(['fontSize' => '45px', 'color' => '#409eff', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.today_add_player'))
->value($playerData['today'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.player_all'))
->value($playerData['all'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-ChannelPlayerController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-user')->style(['fontSize' => '45px', 'color' => '#e91e63', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.today_active_player'))
->value($loginData['today'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8)
->redirect('ex-admin/addons-webman-controller-PlayerController/index',['active_player' => 1]),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.mouth_active_player'))
->value($loginData['month'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8)
->redirect('ex-admin/addons-webman-controller-PlayerController/index',['active_player' => 2])
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-money-bill')->style(['fontSize' => '45px', 'color' => '#409eff', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.recharge_all'))
->value(floatval($rechargeData['all']))->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-ChannelRechargeRecordController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 6);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-money-bill-alt')->style(['fontSize' => '45px', 'color' => '#ff9800', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.withdraw_all'))
->value(floatval($withdrawData['all']))->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-ChannelWithdrawRecordController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 6);
$row->column(Card::create($this->rechargeChart())->hoverable(), 12);
$row->column(Card::create($this->withdrawChart())->hoverable(), 12);
$row->column(Card::create($this->playerChart())->hoverable(), 12);
});
return $layout;
}
/**
* 获取活跃玩家数据
* @return array
*/
public function loginData(): array
{
return [
'month' => PlayerLoginRecord::whereYear('created_at', date('Y'))->whereMonth('created_at', date('m'))->distinct('player_id')->count(),
'today' => PlayerLoginRecord::whereDate('created_at', date('Y-m-d'))->distinct('player_id')->count(),
];
}
/**
* 获取玩家数据
* @return array
*/
public function playerData(): array
{
return [
'all' => Player::count('*'),
'today' => Player::whereDate('created_at', date('Y-m-d'))->count(),
];
}
/**
* 获取充值数据
* @return array
*/
public function rechargeData(): array
{
return [
'all' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ARTIFICIAL])->sum('coins'),
'regular' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('type', PlayerRechargeRecord::TYPE_REGULAR)->sum('coins'),
'artificial' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('type', PlayerRechargeRecord::TYPE_ARTIFICIAL)->sum('coins'),
];
}
/**
* 获取提现数据
* @return array
*/
public function withdrawData(): array
{
return [
'all' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->sum('coins'),
'self' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->where('type', PlayerWithdrawRecord::TYPE_SELF)->sum('coins'),
'artificial' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->where('type', PlayerWithdrawRecord::TYPE_ARTIFICIAL)->sum('coins'),
];
}
/**
* 充值趋势图
* @return LineChart
*/
public function rechargeChart(): LineChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = PlayerRechargeRecord::whereDate('created_at', '>=', $range)
->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)
->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ARTIFICIAL])
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('SUM(`coins`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return LineChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.recharge_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.recharge_amount'), $yAxis);
}
/**
* 提现趋势图
* @return LineChart
*/
public function withdrawChart(): LineChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = PlayerWithdrawRecord::whereDate('created_at', '>=', $range)
->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('SUM(`coins`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return LineChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.withdraw_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.withdraw_amount'), $yAxis);
}
/**
* 上传
* @return Response|void
*/
public function myEditorUpload()
{
$file = request()->file('file');
if ($file && $file->isValid()) {
$size = $file->getSize();
if ($file->getSize() >= 1024 * 1024) {
return jsonFailResponse(trans('image_upload_size_fail', ['{size}' => '1M'], 'message'));
}
$extension = $file->getUploadExtension();
if (!in_array($extension, ['png', 'jpg', 'jpeg'])) {
return jsonFailResponse(trans('image_upload_size_fail', ['{size}' => '1M'], 'message'));
}
$uploadName = $file->getUploadName();
$basePath = public_path() . '/storage/' . date('Ymd') . DIRECTORY_SEPARATOR;
$baseUrl = env('APP_URL', 'http://127.0.0.1:8787') . '/storage/' . date('Ymd') . '/';
$uniqueId = hash_file('md5', $file->getPathname());
$saveFilename = $uniqueId . '.' . $file->getUploadExtension();
$savePath = $basePath . $saveFilename;
$file->move($savePath);
return jsonSuccessResponse('success', [
'origin_name' => $uploadName,
'save_name' => $saveFilename,
'save_path' => $savePath,
'url' => $baseUrl . $saveFilename,
'unique_id' => $uniqueId,
'size' => $size,
'mime_type' => $file->getUploadMimeType(),
'extension' => $extension,
]);
}
}
/**
* 新增玩家
* @return BarChart
*/
public function playerChart(): BarChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = Player::whereDate('created_at', '>=', $range)
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('COUNT(`id`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return BarChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.player_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.player_amount'), $yAxis);
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\DrawRecord;
use addons\webman\model\Game;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Request;
/**
* 游戏游玩记录
*/
class ChannelPlayGameRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.draw_records_model');
}
/**
* 玩家游戏记录
* @group channel
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('play_game_record.title'));
$grid->model()->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->bordered(true);
$grid->hideAction();
$grid->hideDelete();
$grid->hideDeleteSelection();
$grid->hideSelection();
$grid->column('id', admin_trans('play_game_record.fields.id'))->fixed(true)->align('center');
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, DrawRecord $data) {
$image = !empty($data->player->avatar) ? Avatar::create()->src(is_numeric($data->player->avatar) ? config('def_avatar.' . $data->player->avatar) : $data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val),
]);
})->fixed(true)->align('center');
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('game_type', admin_trans('game.fields.game_type'))->display(function ($val) {
return $val ? admin_trans('game.game_type.' . $val) : admin_trans('game.nu_set');
})->align('center');
$grid->column('prize_name', admin_trans('prize.fields.name'))->align('center');
$grid->column('prize_type', admin_trans('prize.fields.type'))->display(function ($val) {
return $val ? admin_trans('prize.prize_type.' . $val) : admin_trans('prize.nu_set');
})->align('center');
$grid->column('created_at', admin_trans('play_game_record.fields.create_at'))->align('center');
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('game_type')
->placeholder(admin_trans('play_game_record.fields.game_type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
Game::GAME_TYPE_EGG => admin_trans('game.game_type.' . Game::GAME_TYPE_EGG),
Game::GAME_TYPE_TURNTABLE => admin_trans('game.game_type.' . Game::GAME_TYPE_TURNTABLE),
Game::GAME_TYPE_BLINDBOX => admin_trans('game.game_type.' . Game::GAME_TYPE_BLINDBOX),
Game::GAME_TYPE_TICKET => admin_trans('game.game_type.' . Game::GAME_TYPE_TICKET),
Game::GAME_TYPE_LOTTERY => admin_trans('game.game_type.' . Game::GAME_TYPE_LOTTERY),
Game::GAME_TYPE_DICE => admin_trans('game.game_type.' . Game::GAME_TYPE_DICE),
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->quickSearch();
});
}
}

View File

@@ -0,0 +1,1310 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\PhoneSmsLog;
use addons\webman\model\Player;
use addons\webman\model\PlayerBank;
use addons\webman\model\PlayerChipRecord;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerExtend;
use addons\webman\model\PlayerMoneyEditLog;
use addons\webman\model\PlayerPlatformCash;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerRegisterRecord;
use addons\webman\model\PlayerTag;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
use Exception;
use Illuminate\Validation\Rule;
use support\Cache;
use support\Db;
use addons\webman\model\PlayerPromoter;
use Illuminate\Support\Str;
/**
* 渠道玩家
* @group channel
*/
class ChannelPlayerController
{
protected $model;
protected $playerTag;
private $withdraw;
private $recharge;
private $promoter;
private $playerChipRecord;
protected $playerActivityPhaseRecord;
protected $playerLotteryRecord;
protected $playerDeliveryRecord;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_model');
$this->playerTag = plugin()->webman->config('database.player_tag_model');
$this->withdraw = plugin()->webman->config('database.player_withdraw_record_model');
$this->recharge = plugin()->webman->config('database.player_recharge_record_model');
$this->promoter = plugin()->webman->config('database.player_promoter_model');
$this->playerChipRecord = plugin()->webman->config('database.player_chip_record_model');
$this->playerActivityPhaseRecord = plugin()->webman->config('database.player_activity_phase_record_model');
$this->playerLotteryRecord = plugin()->webman->config('database.player_lottery_record_model');
$this->playerDeliveryRecord = plugin()->webman->config('database.player_delivery_record_model');
}
/**
* 渠道玩家
* @auth true
* @group channel
* @return Grid
*/
public function index(): Grid
{
/** @var Channel $channel */
$channel = Channel::where('department_id', Admin::user()->department_id)->first();
return Grid::create(new $this->model(), function (Grid $grid) use ($channel) {
$grid->title(admin_trans('player.title'));
$requestFilter = Request::input('ex_admin_filter', []);
if (isset($requestFilter['search_type']) && !empty($requestFilter['search_type'])) {
$grid->model()->where('is_coin', $requestFilter['search_type']);
}
if (isset($requestFilter['created_at_start']) && !empty($requestFilter['created_at_start'])) {
$grid->model()->where('player.created_at', '>=', $requestFilter['created_at_start']);
}
if (isset($requestFilter['created_at_end']) && !empty($requestFilter['created_at_end'])) {
$grid->model()->where('player.created_at', '<=', $requestFilter['created_at_end']);
}
$activePlayer = Request::input('active_player') ?? null;
if (!empty($activePlayer)){
$grid->model()->whereHas('the_last_player_login_record', function ($query) use ($activePlayer) {
if ($activePlayer == 1){
$query->whereDate('created_at', date('Y-m-d'));
} else {
$query->whereYear('created_at', date('Y'))
->whereMonth('created_at', date('m'));
}
});
}
$subQuery = PlayerDeliveryRecord::select('player_id', Db::raw('sum(amount) as amount'))
->whereNotIn('type', [1,2,3,4,5,9,10])
->groupBy('player_id');
$grid->model()->with(['player_register_record', 'the_last_player_login_record'])
->select([
'player.*',
'player_extend.recharge_amount',
'player_extend.withdraw_amount',
'player_platform_cash.money as money',
'record.amount as present_coins'
])
->leftjoin('player_extend', 'player.id', '=', 'player_extend.player_id')
->leftjoin('player_platform_cash', 'player.id', '=', 'player_platform_cash.player_id')
->leftjoinSub($subQuery, 'record', function ($join) {
$join->on('player.id', '=', 'record.player_id');
})
->orderBy('player.id', 'desc');
$grid->autoHeight();
$grid->bordered();
$grid->column('id', admin_trans('player.fields.id'))->fixed(true)->align('center');
$grid->column('name', admin_trans('player.fields.name'))->display(function ($val, Player $data) {
$image = $data->avatar ? Avatar::create()->src(is_numeric($data->avatar) ? config('def_avatar.' . $data->avatar) : $data->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val),
]);
})->fixed(true)->align('center');
$grid->column('uuid', admin_trans('player.fields.uuid'))->fixed(true)->ellipsis(true)->align('center');
$grid->column('phone', admin_trans('player.fields.phone'))->fixed(true)->ellipsis(true)->align('center');
$grid->column('money', admin_trans('player_platform_cash.platform_name.' . PlayerPlatformCash::PLATFORM_SELF))->display(function ($val, Player $data) {
return Tag::create($val)->color('orange')->style(['cursor' => 'pointer'])->modal([$this, 'playerRecord'], ['id' => $data->id])->width('70%')->title($data->name . ' ' . $data->uuid);
})->ellipsis(true)->align('center')->sortable();
$grid->column('player_extend.recharge_amount', admin_trans('player_extend.fields.recharge_amount'))->ellipsis(true)->align('center')->sortable();
$grid->column('player_extend.withdraw_amount', admin_trans('player_extend.fields.withdraw_amount'))->ellipsis(true)->align('center')->sortable();
$grid->column('status', admin_trans('player.fields.status'))->switch()->ellipsis(true)->align('center');
$grid->column('player.created_at', admin_trans('player.fields.created_at'))->display(function ($val, Player $data) {
return Html::create()->content([
Html::div()->content(date('Y-m-d H:i:s', strtotime($data->created_at))),
Html::div()->content($data->player_register_record->ip ?? ''),
Html::div()->content($data->player_register_record->country_name ?? ''),
]);
})->ellipsis(true)->align('center')->sortable();
$grid->column('last_login', admin_trans('player.fields.player_login_record'))->display(function ($val, Player $data) {
return Html::create()->content([
Html::div()->content($val ?? (!empty($data->the_last_player_login_record->created_at) ? date('Y-m-d H:i:s', strtotime($data->the_last_player_login_record->created_at)) : '')),
Html::div()->content($data->the_last_player_login_record->ip ?? ''),
Html::div()->content($data->the_last_player_login_record->country_name ?? ''),
]);
})->ellipsis(true)->align('center')->sortable();
$grid->filter(function (Filter $filter) use ($channel) {
$filter->like()->text('uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('name')->placeholder(admin_trans('player.fields.name'));
$filter->like()->text('phone')->placeholder(admin_trans('player.fields.phone'));
$filter->eq()->select('level')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player.fields.level'))
->options(playerLevelOptions());
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->expandFilter();
$grid->hideDelete();
$grid->hideSelection();
$grid->tools(
$grid->addButton()->modal($this->form())
);
$grid->actions(function (Actions $actions, Player $data) use ($channel) {
$actions->edit()->modal($this->form())->width('60%');
$actions->hideDel();
$dropdown = $actions->dropdown();
if ($channel->wallet_action_status == 1) {
$dropdown->append(admin_trans('player.wallet.player_wallet'), 'MoneyCollectFilled')
->modal($this->playerWallet([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px');
}
$dropdown->append(admin_trans('player.wallet.artificial_recharge'), 'TransactionOutlined')
->modal($this->artificialRecharge([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_recharge'))->content(
ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_recharge_tip'))
));
$dropdown->append(admin_trans('player.wallet.artificial_withdrawal'), 'PayCircleOutlined')
->modal($this->artificialWithdrawal([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_withdrawal'))->content(
ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_withdrawal_tip'))
));
});
$grid->tools([
ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['margin-left' => '10px', 'margin-top' => '4px', 'line-height' => '28px', 'font-size' => '15px', 'cursor' => 'pointer']))->title(admin_trans('player.set_promoter_tip'))
]);
$grid->updateing(function ($ids, $data) {
if (isset($ids[0]) && isset($data['player_extend'])) {
if (PlayerExtend::updateOrCreate(
['player_id' => $ids[0]],
$data['player_extend']
)) {
return message_success(admin_trans('player.remark_edit_success'));
}
}
});
});
}
/**
* 人工提现
* @auth true
* @group channel
* @param $data
* @return Form
*/
public function artificialWithdrawal($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->number('coins', admin_trans('player_withdraw_record.fields.coins'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%'])
->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
->required();
$form->number('money', admin_trans('player_withdraw_record.fields.money'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%']);
$form->text('currency', admin_trans('player_withdraw_record.fields.currency'))->maxlength(10);
$form->text('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->maxlength(50);
$form->text('account', admin_trans('player_withdraw_record.fields.account'))->maxlength(50);
$form->text('account_name', admin_trans('player_withdraw_record.fields.account_name'))->maxlength(50);
$form->textarea('remark', admin_trans('player_withdraw_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
$form->layout('vertical');
$form->hidden('id')->value($data['id']);
$form->saving(function (Form $form) {
/** @var Player $player */
$player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
if ($player->status == 0) {
return message_error(admin_trans('player.disable'));
}
if ($player->wallet->money < $form->input('coins')) {
return message_error(admin_trans('player.insufficient_balance'));
}
DB::beginTransaction();
try {
// 生成订单
$playerWithdrawRecord = new PlayerWithdrawRecord();
$playerWithdrawRecord->player_id = $player->id;
$playerWithdrawRecord->talk_user_id = $player->talk_user_id;
$playerWithdrawRecord->department_id = $player->department_id;
$playerWithdrawRecord->tradeno = createOrderNo();
$playerWithdrawRecord->player_name = $player->name ?? '';
$playerWithdrawRecord->player_phone = $player->phone ?? '';
$playerWithdrawRecord->money = $form->input('money') ?? 0;
$playerWithdrawRecord->coins = $form->input('coins') ?? 0;
$playerWithdrawRecord->fee = 0;
$playerWithdrawRecord->inmoney = bcsub($playerWithdrawRecord->money, $playerWithdrawRecord->fee, 2); // 实际提现金额
$playerWithdrawRecord->currency = $form->input('currency') ?? 0;
$playerWithdrawRecord->bank_name = $form->input('bank_name') ?? 0;
$playerWithdrawRecord->account = $form->input('account') ?? 0;
$playerWithdrawRecord->account_name = $form->input('account_name') ?? 0;
$playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_ARTIFICIAL;
$playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_SUCCESS;
$playerWithdrawRecord->finish_time = date('Y-m-d H:i:s');
$playerWithdrawRecord->save();
$beforeGameAmount = $player->wallet->money;
// 玩家钱包扣减
$player->wallet->money = bcsub($player->wallet->money, $playerWithdrawRecord->coins, 2);
// 更新玩家统计
$player->player_extend->withdraw_amount = bcadd($player->player_extend->withdraw_amount, $playerWithdrawRecord->coins, 2);
$player->push();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerWithdrawRecord->player_id;
$playerDeliveryRecord->department_id = $playerWithdrawRecord->department_id;
$playerDeliveryRecord->target = $playerWithdrawRecord->getTable();
$playerDeliveryRecord->target_id = $playerWithdrawRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_WITHDRAWAL;
$playerDeliveryRecord->source = 'artificial_withdrawal';
$playerDeliveryRecord->amount = $playerWithdrawRecord->coins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = $playerWithdrawRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerWithdrawRecord->remark ?? '';
$playerDeliveryRecord->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.artificial_withdrawal_error'));
}
return message_success(admin_trans('player.artificial_withdrawal_success'));
});
});
}
/**
* 人工充值
* @auth true
* @group channel
* @param $data
* @return Form
*/
public function artificialRecharge($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->number('coins', admin_trans('player_recharge_record.fields.coins'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%'])
->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
->required();
$form->number('money', admin_trans('player_recharge_record.fields.money'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%']);
$form->text('currency', admin_trans('player_recharge_record.fields.currency'))->maxlength(10);
$form->textarea('remark', admin_trans('player_recharge_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
$form->layout('vertical');
$form->hidden('id')->value($data['id']);
$form->saving(function (Form $form) {
/** @var Player $player */
$player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
if ($player->status == 0) {
return message_error(admin_trans('player.disable'));
}
DB::beginTransaction();
try {
$beforeGameAmount = $player->wallet->money;
// 生成订单
$playerRechargeRecord = new PlayerRechargeRecord();
$playerRechargeRecord->player_id = $player->id;
$playerRechargeRecord->department_id = $player->department_id;
$playerRechargeRecord->tradeno = createOrderNo();
$playerRechargeRecord->player_name = $player->name ?? '';
$playerRechargeRecord->money = $form->input('money') ?? 0;
$playerRechargeRecord->inmoney = $form->input('money') ?? 0;
$playerRechargeRecord->currency = $form->input('currency') ?? '';
$playerRechargeRecord->type = PlayerRechargeRecord::TYPE_ARTIFICIAL;
$playerRechargeRecord->coins = $form->input('coins');
$playerRechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS;
$playerRechargeRecord->remark = $form->input('remark');
$playerRechargeRecord->finish_time = date('Y-m-d H:i:s');
$playerRechargeRecord->user_id = Admin::id() ?? 0;
$playerRechargeRecord->user_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : '';
$playerRechargeRecord->save();
$player->wallet->money = bcadd($player->wallet->money, $playerRechargeRecord->coins, 2);
$player->player_extend->recharge_amount = bcadd($player->player_extend->recharge_amount, $playerRechargeRecord->coins, 2);
$player->push();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerRechargeRecord->player_id;
$playerDeliveryRecord->department_id = $playerRechargeRecord->department_id;
$playerDeliveryRecord->target = $playerRechargeRecord->getTable();
$playerDeliveryRecord->target_id = $playerRechargeRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_RECHARGE;
$playerDeliveryRecord->source = 'artificial_recharge';
$playerDeliveryRecord->amount = $playerRechargeRecord->coins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = $playerRechargeRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerRechargeRecord->remark ?? '';
$playerDeliveryRecord->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.artificial_recharge_error'));
}
return message_success(admin_trans('player.artificial_recharge_success'));
});
});
}
/**
* 玩家钱包
* @auth true
* @group channel
* @param $data
* @return Form
*/
public function playerWallet($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->hidden('id')->default($data['id']);
$form->row(function (Form $form) {
$type = $form->getBindField('type');
$form->radio('type', admin_trans('player.wallet.type'))
->button()
->disabled($form->isEdit())
->default(PlayerMoneyEditLog::TYPE_INCREASE)
->options([
admin_trans('player.wallet.deduct'),
admin_trans('player.wallet.increase'),
])->required()->span(7);
$form->hidden('type')->bindAttr('value', $type)
->when(PlayerMoneyEditLog::TYPE_DEDUCT, function (Form $form) {
$form->select('deduct_action', admin_trans('player.wallet.action'))
->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_DEDUCT]))
->required()->span(16)->style(['margin-left' => '22px']);
})->when(PlayerMoneyEditLog::TYPE_INCREASE, function (Form $form) {
$form->select('increase_action', admin_trans('player.wallet.action'))
->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_INCREASE]))
->required()->span(16)->style(['margin-left' => '22px']);
});
});
$form->number('money', admin_trans('player.wallet.money'))->min(0)->max(100000000)->precision(2)->style(['width' => '100%'])->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)->required();
$form->textarea('remark', admin_trans('player.wallet.textarea'))->maxlength(255)->bindAttr('rows', 4)->required();
$form->actions()->hideResetButton();
$form->saving(function (Form $form) use ($data) {
/** @var Channel $channel */
$channel = Channel::where('department_id', Admin::user()->department_id)->first();
if ($channel->wallet_action_status == 0) {
return message_error(admin_trans('player.wallet_action_status_has_closed'));
}
return $this->store([
'id' => $form->input('id'),
'type' => $form->input('type'),
'deduct_action' => $form->input('deduct_action'),
'increase_action' => $form->input('increase_action'),
'money' => $form->input('money'),
'remark' => $form->input('remark'),
]);
});
$form->layout('vertical');
});
}
/**
* 钱包操作
* @param $data
* @return Msg
*/
public function store($data): Msg
{
try {
DB::beginTransaction();
playerManualSystem($data);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.wallet.wallet_operation_failed'));
}
return message_success(admin_trans('player.wallet.wallet_operation_success'));
}
/**
* 钱包操作类型
* @param $type
* @return mixed
*/
public function getTranOptions($type)
{
$options = [];
if ($type == PlayerMoneyEditLog::TYPE_INCREASE) {
$transactionType = [
PlayerMoneyEditLog::ACTIVITY_GIVE,
PlayerMoneyEditLog::ADMIN_INCREASE,
PlayerMoneyEditLog::OTHER
];
} else {
$transactionType = [
PlayerMoneyEditLog::ADMIN_DEDUCT,
PlayerMoneyEditLog::OTHER
];
}
foreach ($transactionType as $item) {
$options[] = [
'value' => $item,
'label' => admin_trans('player.wallet.wallet_type.' . $item),
];
}
return Response::success($options);
}
/**
* 处理标签
* @param array $value
* @return Html
*/
public function handleTagIds(array $value): Html
{
$options = $this->getPlayerTagOptions($value);
$html = Html::create();
foreach ($options as $option) {
$html->content(
Tag::create($option)
->color('success')
);
}
return $html;
}
/**
* 获取玩家标签选项(筛选id)
* @param array $ids
* @return array
*/
public function getPlayerTagOptions(array $ids = []): array
{
$idsStr = json_encode($ids);
$cacheKey = md5("player_tag_options_ids_$idsStr");
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
if (!empty($ids)) {
$data = (new PlayerTag())->whereIn('id', $ids)->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
return [];
}
}
/**
* 获取玩家标签(筛选id)
* @return array
*/
public function getPlayerTagOptionsFilter(): array
{
$cacheKey = "doc_player_tag_options_filter";
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
$data = (new PlayerTag())->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
}
/**
* 渠道玩家
* @auth true
* @group channel
* @return Form
*/
public function form(): Form
{
$options = [];
foreach (config('def_avatar') as $key => $item) {
$options[$key] = Avatar::create()->style(['padding' => '1px'])->src($item)->shape('square');
}
return Form::create(new $this->model(), function (Form $form) use ($options) {
if ($form->isEdit()) {
$form->title(admin_trans('player.details'));
$form->row(function (Form $form) use ($options) {
$form->column(function (Form $form) use ($options) {
$form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleNumber()
->rule([
(string)Rule::unique(plugin()->webman->config('database.player_model'))->ignore($form->input('id')) => admin_trans('player.phone_exist'),
])
->disabled(true);
$form->text('name', admin_trans('player.fields.name'))->maxlength(50);
$form->radio('avatar_type', admin_trans('player.avatar_type'))
->button()
->default(is_numeric($form->driver()->get('avatar')) ? 2 : 1)
->options([
1 => admin_trans('player.upload_avatar'),
2 => admin_trans('player.def_avatar')
])
->when(1, function (Form $form) {
$form->file('avatar', admin_trans('player.fields.avatar'))
->value(is_numeric($form->driver()->get('avatar')) ? '' : $form->driver()->get('avatar'))
->ext('jpg,png,jpeg')
->type('image')
->fileSize('1m')
->hideFinder()
->paste();
})->when(2, function (Form $form) use ($options) {
$form->radio('def_avatar', admin_trans('player.def_avatar'))
->default(1)
->options($options);
});
$form->text('player_extend.id_number', admin_trans('player_extend.fields.id_number'))->ruleAlphaNum()->maxlength(20);
$form->desc('the_last_player_login_record.created_at', admin_trans('player.fields.login_at'))->value($form->input('the_last_player_login_record.created_at') ? date('Y-m-d H:i:s', strtotime($form->input('the_last_player_login_record.created_at'))) : '');
$form->desc('created_at', admin_trans('player.fields.created_at'))->value($form->input('created_at') ? date('Y-m-d H:i:s', strtotime($form->input('created_at'))) : '');
$form->desc('player_register_record.ip', admin_trans('player.fields.register_ip'));
$form->desc('player_register_record.register_domain', admin_trans('player.fields.register_domain'));
})->span(12);
$form->column(function (Form $form) {
$form->text('player_extend.address', admin_trans('player_extend.fields.address'))->maxlength(255);
$form->date('player_extend.birthday', admin_trans('player_extend.fields.birthday'));
$form->text('player_extend.email', admin_trans('player_extend.fields.email'))->ruleEmail()->maxlength(20);
$form->text('player_extend.line', admin_trans('player_extend.fields.line'))->ruleAlphaNum()->maxlength(20);
$form->textarea('player_extend.remark', admin_trans('player_extend.fields.remark'))
->showCount()
->rule(['max:255' => admin_trans('player_extend.fields.remark')]);
$playerBank = PlayerBank::query()->where('player_id', $form->driver()->get('id'))->get()->toArray();
foreach ($playerBank as $key => $item) {
$form->row(function (Form $form) use ($item, $key) {
$form->text('bank_name'.$key, admin_trans('player.bank_name'))
->value($item['bank_name'] ?? 0)
->disabled(true);
$form->text('account_name'.$key, admin_trans('player.account_name'))
->value($item['account_name'] ?? 0)
->disabled(true);
$form->text('account'.$key, admin_trans('player.account'))
->value($item['account'] ?? 0)
->disabled(true);
});
}
})->span(12);
});
} else {
$form->title(admin_trans('player.add_player'));
$form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleAlphaNum()->required();
$form->radio('avatar_type', admin_trans('player.avatar_type'))
->button()
->default(2)
->options([
1 => admin_trans('player.upload_avatar'),
2 => admin_trans('player.def_avatar')
])
->when(1, function (Form $form) {
$form->image('avatar', admin_trans('player.fields.avatar'))->ext('jpg,png,jpeg')->fileSize('1m');
})->when(2, function (Form $form) use ($options) {
$form->radio('def_avatar', admin_trans('player.def_avatar'))
->default(1)
->options($options);
});
$form->select('country_code', admin_trans('player.fields.country_code'))->options([
PhoneSmsLog::COUNTRY_CODE_MY => PhoneSmsLog::COUNTRY_CODE_MY,
])->required();
$form->text('name', admin_trans('player.fields.name'))->maxlength(50)->required();
$form->password('password', admin_trans('player.new_password'))
->rule([
'confirmed' => admin_trans('player.password_confim_validate'),
'min:6' => admin_trans('player.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('player.confim_password'))
->required();
}
$form->saved(function () {
return message_success(admin_trans('player.save_player_info_success'));
});
$form->saving(function (Form $form) {
if ($form->isEdit()) {
$orgData = $form->driver()->get();
/** @var Player $player */
$player = Player::find($orgData['id']);
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
DB::beginTransaction();
try {
$player->name = $form->input('name');
$player->avatar = $form->input('avatar_type') == 1 ? $form->input('avatar') : $form->input('def_avatar');
$player->save();
PlayerExtend::query()->updateOrCreate(['player_id' => $orgData['id']], [
'address' => $form->input('player_extend.address'),
'birthday' => $form->input('player_extend.birthday'),
'id_number' => $form->input('player_extend.id_number'),
'email' => $form->input('player_extend.email'),
'line' => $form->input('player_extend.line'),
'remark' => $form->input('player_extend.remark'),
'player_id' => $orgData['id']]);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('player.save_player_info_success'));
} else {
$phone = $form->input('phone');
$password = $form->input('password');
$country_code = $form->input('country_code');
/** @var $player Player */
$player = Player::query()->where('phone', $country_code.$phone)->first();
if (!empty($player)) {
return message_error(admin_trans('player.phone_has_register'));
}
/** @var Channel $channel */
$channel = Channel::where('department_id', Admin::user()->department_id)->first();
if (empty($channel)) {
return message_error(admin_trans('channel.not_fount'));
}
DB::beginTransaction();
try {
$player = new Player();
$player->phone = $country_code.$phone;
$player->name = $form->input('name');
if ($form->input('avatar_type') == 1) {
$player->avatar = $form->input('avatar') ?? config('def_avatar.1');
}
if ($form->input('avatar_type') == 2) {
$player->avatar = $form->input('def_avatar') ?? config('def_avatar.1');
}
$player->country_code = $country_code;
$player->type = Player::TYPE_PLAYER;
$player->currency = $channel->currency;
$player->password = $password;
$player->uuid = gen_uuid();
$player->department_id = Admin::user()->department_id;
$player->recommend_code = createCode();
$player->save();
addPlayerExtend($player, [
'email' => $data['email'] ?? ''
]);
addRegisterRecord($player->id, PlayerRegisterRecord::TYPE_ADMIN, $player->department_id);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('player.save_player_info_success'));
}
});
});
}
/**
* 玩家记录
* @param $id
* @auth true
* @group channel
* @return Card
*/
public function playerRecord($id): Card
{
$tabs = Tabs::create()
->pane(admin_trans('player.player_recharge_record'), $this->rechargeRecord($id))
->pane(admin_trans('player.player_withdraw_record'), $this->withdrawalRecords($id))
->pane(admin_trans('player.player_delivery_record'), $this->playerDeliveryRecord($id))
->type('card');
return Card::create($tabs);
}
/**
* 钱包操作
* @param $id
* @return Grid
*/
public function playerDeliveryRecord($id): Grid
{
return Grid::create(new $this->playerDeliveryRecord, function (Grid $grid) use ($id) {
$lang = Container::getInstance()->translator->getLocale();
$grid->title(admin_trans('promoter_profit_record.player_activity_phase_record_title'));
$grid->model()
->where('player_id', $id)
->whereIn('type', [
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD,
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT,
])
->orderBy('id', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
}
$grid->autoHeight();
$grid->bordered(true);
$grid->column('id', admin_trans('player_delivery_record.fields.id'))->align('center');
$grid->column('source', admin_trans('player_delivery_record.fields.source'))->display(function ($val, PlayerDeliveryRecord $data) use ($lang) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Tag::create(trans($val, [], 'message', $lang))->color('red');
default:
return '';
}
})->align('center');
$grid->column('type', admin_trans('player_delivery_record.fields.type'))
->display(function ($value) {
switch ($value) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD))->color('#2db7f5');
break;
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT))->color('#108ee9');
break;
default:
$tag = '';
}
return Html::create()->content([
$tag
]);
})->align('center')->sortable();
$grid->column('amount', admin_trans('player_delivery_record.fields.amount'))->display(function ($val, PlayerDeliveryRecord $data) {
if ($data->amount == 0) {
return Html::create()->content([$val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('user_name', admin_trans('player_delivery_record.fields.user_name'))->display(function ($val, PlayerDeliveryRecord $data) {
$name = '--';
if (in_array($data->type, [PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD, PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT])) {
$name = $data->user_name ?? '管理员';
}
return Html::create()->content([
Html::div()->content($name),
]);
});
$grid->column('created_at', admin_trans('player_delivery_record.fields.created_at'))->align('center')->ellipsis(true);
$grid->hideDelete();
$grid->hideSelection();
$grid->hideTrashed();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('type')
->placeholder(admin_trans('player_delivery_record.fields.type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD),
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT),
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
});
}
/**
* 提现记录
* @param $id
* @return Grid
*/
public function withdrawalRecords($id): Grid
{
return Grid::create(new $this->withdraw(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_withdraw_record.title'));
$grid->model()->with(['player'])->where('player_id', $id)->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
}
$grid->bordered();
$grid->autoHeight();
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->ellipsis(true)->align('center')->fixed(true);
$grid->column('player_phone', admin_trans('player_withdraw_record.fields.player_phone'))->display(function ($val, PlayerWithdrawRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->align('center')->ellipsis(true)->fixed(true);
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->ellipsis(true)->copy()->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->ellipsis(true)->align('center');
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column(function (Grid $grid) {
$grid->column('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->copy()->align('center');
$grid->column('account_name', admin_trans('player_withdraw_record.fields.account_name'))->copy()->align('center');
$grid->column('account', admin_trans('player_withdraw_record.fields.account'))->copy()->align('center');
}, admin_trans('player_withdraw_record.player_bank'))->ellipsis(true);
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::TYPE_ACTIVITY:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#55acee');
case PlayerRechargeRecord::TYPE_REGULAR:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->ellipsis(true)->align('center');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function () {
return Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
})->align('center')->ellipsis(true)->sortable();
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->ellipsis(true)->sortable()->align('center');
$grid->column('finish_time', admin_trans('player_withdraw_record.fields.finish_time'))->ellipsis(true)->fixed('right')->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_withdraw_record.fields.finish_time'), admin_trans('player_withdraw_record.fields.finish_time')]);
});
});
}
/**
* 充值记录
* @param $id
* @return Grid
*/
public function rechargeRecord($id): Grid
{
return Grid::create(new $this->recharge(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_recharge_record.title'));
$grid->bordered();
$grid->autoHeight();
$grid->model()->with(['player'])->where('player_id', $id)->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
}
$grid->column('id', admin_trans('player_recharge_record.fields.id'))->ellipsis(true)->fixed(true)->align('center');
$grid->column('player.name', admin_trans('player_recharge_record.fields.player_name'))->display(function ($val, PlayerRechargeRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->ellipsis(true)->fixed(true)->align('center');
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->ellipsis(true)->copy();
$grid->column('channel.name', admin_trans('player_recharge_record.fields.department_id'))->ellipsis(true)->align('center');
$grid->column('type', admin_trans('player_recharge_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::TYPE_REGULAR:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#55acee');
case PlayerRechargeRecord::TYPE_ACTIVITY:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->ellipsis(true)->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->ellipsis(true)->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->ellipsis(true)->align('center');
$grid->column(function (Grid $grid) {
$grid->column('bank_name', admin_trans('channel_recharge_method.fields.bank_name'))->copy()->align('center');
$grid->column('sub_bank', admin_trans('channel_recharge_method.fields.sub_bank'))->copy()->align('center');
$grid->column('owner', admin_trans('channel_recharge_method.fields.owner'))->copy()->align('center');
$grid->column('account', admin_trans('channel_recharge_method.fields.account'))->copy()->align('center');
}, admin_trans('channel_recharge_setting.recharge_setting_info'))->ellipsis(true);
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function () {
return Tag::create(admin_trans('player_recharge_record.status_success'))->color('#87d068');
})->ellipsis(true)->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->ellipsis(true)->sortable()->align('center');
$grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->ellipsis(true)->fixed('right')->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.type'))
->options([
PlayerRechargeRecord::TYPE_REGULAR => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_REGULAR),
PlayerRechargeRecord::TYPE_ACTIVITY => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ACTIVITY),
PlayerRechargeRecord::TYPE_ARTIFICIAL => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ARTIFICIAL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);
});
});
}
/**
* 打码量记录
* @param $id
* @return Grid
*/
public function playerChipRecord($id): Grid
{
return Grid::create(new $this->playerChipRecord(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_chip_record.title'));
$grid->bordered();
$grid->autoHeight();
$grid->model()->with(['channel', 'player'])
->where('player_id', $id)
->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
$query = clone $grid->model();
$totalData = $query->where(function ($query) use($exAdminFilter) {
if(!empty($exAdminFilter['created_at'])) {
$query->whereBetween('created_at', $exAdminFilter['created_at']);
}
})->sum('chip_amount');
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->value($totalData)
->prefix(admin_trans('player_chip_record.fields.chip_amount'))
->valueStyle([
'font-size' => '14px',
'font-weight' => '500',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '30px',
'padding' => '0px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 4);
})->style(['background' => '#fff']);
$grid->tools([
$layout
]);
$grid->column('id', admin_trans('player_chip_record.fields.id'))->align('center');
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('chip_amount', admin_trans('player_chip_record.fields.chip_amount'))->display(function ($val, PlayerChipRecord $data) {
if ($val == 0) {
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerChipRecord::TYPE_DEC:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('must_chip_amount', admin_trans('player_chip_record.fields.must_chip_amount'))->display(function ($val, PlayerChipRecord $data) {
if ($val == 0) {
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerChipRecord::TYPE_DEC:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('record_type', admin_trans('player_chip_record.fields.record_type'))->display(function ($val) {
switch ($val) {
case PlayerChipRecord::RECORD_TYPE_SIGN:
case PlayerChipRecord::RECORD_TYPE_RECHARGE:
case PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#55acee');
break;
case PlayerChipRecord::RECORD_TYPE_ACTIVITY:
case PlayerChipRecord::RECORD_TYPE_GAME:
case PlayerChipRecord::RECORD_TYPE_BET_REBATE:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#3b5999');
break;
case PlayerChipRecord::RECORD_TYPE_COMMISSION:
case PlayerChipRecord::RECORD_TYPE_BANKRUPTCY:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#cd201f');
break;
default:
return '';
}
return Html::create()->content([
$tag,
]);
})->align('center');
$grid->column('amount', admin_trans('player_chip_record.fields.amount'))->align('center');
$grid->column('created_at', admin_trans('player_chip_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('record_type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_chip_record.fields.record_type'))
->options([
PlayerChipRecord::RECORD_TYPE_SIGN => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_SIGN),
PlayerChipRecord::RECORD_TYPE_RECHARGE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_RECHARGE),
PlayerChipRecord::RECORD_TYPE_ACTIVITY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_ACTIVITY),
PlayerChipRecord::RECORD_TYPE_GAME => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_GAME),
PlayerChipRecord::RECORD_TYPE_COMMISSION => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_COMMISSION),
PlayerChipRecord::RECORD_TYPE_BANKRUPTCY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BANKRUPTCY),
PlayerChipRecord::RECORD_TYPE_BET_REBATE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BET_REBATE),
PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD),
]);
$filter->between()->dateTimeRange('created_at')->placeholder([admin_trans('player_chip_record.fields.created_at'), admin_trans('player_chip_record.fields.created_at')]);
});
$grid->quickSearch();
});
}
/**
* 设置推广员
* @auth true
* @group channel
* @param $id
* @return Form
*/
public function setPromoter($id): Form
{
/** @var PlayerPromoter $promoter */
$promoter = PlayerPromoter::with(['parent_promoter'])->where('player_id', $id)->first();
return Form::create($promoter ?? new $this->promoter(), function (Form $form) use ($id) {
$form->push(Html::markdown('><font size=1 color="#ff4d4f">' . admin_trans('player_promoter.submit_confirm') . '</font>'));
/** @var PlayerPromoter $model */
$model = $form->driver()->model();
$maxRatio = $model->parent_promoter->ratio ?? 100;
$form->text('name')
->value($model->name ?? '')
->maxlength(30)
->required()->addonBefore(admin_trans('player_promoter.fields.name'));
$form->text('ratio')
->value($model->ratio ?? '')
->rulePattern('^[0-9]+(.[0-9]{1,2})?$', admin_trans('validator.twoDecimal'))
->rule([
'max:' . $maxRatio => admin_trans('validator.max', null, ['{max}' => $maxRatio]),
'min:0' => admin_trans('validator.min', null, ['{min}' => 0]),
'regex:/^[0-9]+(.[0-9]{1,2})?$/' => admin_trans('validator.twoDecimal'),
])
->required()
->addonAfter('%')
->help(!empty($model->parent_promoter->ratio) ? admin_trans('player_promoter.ratio_help_parent', null, ['{max_ratio}' => $maxRatio]) : admin_trans('player_promoter.ratio_help_platform', null, ['{max_ratio}' => $maxRatio]))
->placeholder(admin_trans('player_promoter.ratio_placeholder', null, ['{max_ratio}' => $maxRatio]))
->addonBefore(admin_trans('player_promoter.fields.ratio'));
$form->saving(function (Form $form) use ($id) {
return $this->savePromoter($id, $form->input('ratio'), $form->input('name'));
});
});
}
/**
* 保存推广员信息
* @param $id
* @param $ratio
* @param string $name
* @return Msg
*/
public function savePromoter($id, $ratio, string $name = ''): Msg
{
DB::beginTransaction();
try {
/** @var Player $player */
$player = Player::with(['player_promoter'])->find($id);
if (empty($player)) {
throw new Exception(admin_trans('player.not_fount'));
}
if (empty($player->player_promoter) && !empty($player->recommend_id)) {
throw new Exception(admin_trans('player.player_must_not_attributed'));
}
$promoter = $player->player_promoter ?? new PlayerPromoter();
$promoter->ratio = $ratio;
$promoter->player_id = $id;
$promoter->recommend_id = $parentPromoter->player_id ?? 0;
$promoter->department_id = $player->department_id;
$promoter->name = $name;
$promoter->path = $player->id;
$promoter->save();
// 更新玩家信息
$player->is_promoter = 1;
$player->recommend_code = createCode();
$player->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('form.save_success'));
}
/**
* 绑定推广员
* @auth true
* @group channel
* @param $id
* @return Form|Msg
*/
public function bindPromoter($id)
{
/** @var Player $player */
$player = Player::query()->find($id);
if (empty($player)) {
return message_error(admin_trans('player.player_not_found'));
}
if (!empty($player->recommended_code)) {
return message_error(admin_trans('player.player_has_bind'));
}
if ($player->is_promoter > 0) {
return message_error(admin_trans('player.has_been_promoter'));
}
/** @var Channel $channel */
$channel = Channel::query()->where('department_id', $player->department_id)->first();
if (empty($channel)) {
return message_error(admin_trans('player.channel_not_found'));
}
if ($channel->promotion_status != 1) {
return message_error(admin_trans('player.channel_close_promoter'));
}
return Form::create($player, function (Form $form) use ($player) {
$form->push(Html::markdown('><font size=1 color="#ff4d4f">' . admin_trans('player.bind_promoter_confirm') . '</font>'));
$options = PlayerPromoter::query()
->where('department_id', $player->department_id)
->where('status', 1)
->pluck('name', 'player_id')->toArray();
$form->select('recommend_id')
->style(['width' => '200px'])
->options($options);
$form->saving(function (Form $form) use ($player) {
/** @var PlayerPromoter $recommendPlayer */
$recommendPlayer = PlayerPromoter::query()
->where('player_id', $form->input('recommend_id'))
->where('department_id', $player->department_id)->first();
if (empty($recommendPlayer)) {
return message_error(admin_trans('player.promoter_not_found'));
}
if ($recommendPlayer->player->status == 0) {
return message_error(admin_trans('player.promoter_has_disable'));
}
$player->recommend_id = $recommendPlayer->player->id;
$player->recommended_code = $recommendPlayer->player->recommend_code;
$player->save();
$recommendPlayer->increment('player_num');
return message_success(admin_trans('player.action_success'));
});
});
}
}

View File

@@ -0,0 +1,206 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\PlayerDeliveryRecord;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\FilterColumn;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
/**
* 账变记录
* @group channel
*/
class ChannelPlayerDeliveryRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_delivery_record_model');
}
/**
* 玩家账变
* @group channel
* @auth true
*/
public function index(): Grid
{
$lang = Container::getInstance()->translator->getLocale();
return Grid::create(new $this->model(), function (Grid $grid) use ($lang) {
$grid->title(admin_trans('player_delivery_record.title'));
$grid->model()->with(['player'])->orderBy('created_at', 'desc');
$grid->autoHeight();
$grid->bordered(true);
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['search_source']) && !empty($exAdminFilter['search_source'])) {
$searchSource = $exAdminFilter['search_source'];
$grid->model()->where(function ($query) use ($searchSource) {
$query->where(function ($query) use ($searchSource) {
$query->where([
['source', 'like', '%' . $searchSource . '%', 'and'],
]);
});
});
}
$grid->column('id', admin_trans('player_delivery_record.fields.id'))->align('center');
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->align('center');
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerDeliveryRecord $data) {
$image = $data->player->avatar ? Avatar::create()->src(is_numeric($data->player->avatar) ? config('def_avatar.' . $data->player->avatar) : $data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($data->player->name),
]);
})->align('center')->filter(
FilterColumn::like()->text('player.phone')
);
$grid->column('source', admin_trans('player_delivery_record.fields.source'))->display(function ($val, PlayerDeliveryRecord $data) use ($lang) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
case PlayerDeliveryRecord::TYPE_RECHARGE:
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
case PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK:
return Tag::create(trans($val, [], 'message', $lang))->color('red');
case PlayerDeliveryRecord::TYPE_REGISTER_PRESENT:
return Tag::create(trans($val, [], 'message', $lang))->color('blue');
case PlayerDeliveryRecord::TYPE_COMMISSION:
case PlayerDeliveryRecord::TYPE_GAME_OUT:
return Tag::create(trans($val, [], 'message', $lang))->color('purple');
case PlayerDeliveryRecord::TYPE_SIGN:
case PlayerDeliveryRecord::TYPE_GAME_IN:
case PlayerDeliveryRecord::TYPE_BET_REBATE:
case PlayerDeliveryRecord::TYPE_DAMAGE_REBATE:
case PlayerDeliveryRecord::TYPE_RECHARGE_REWARD:
case PlayerDeliveryRecord::TYPE_PROFIT:
return Tag::create(trans($val, [], 'message', $lang))->color('orange');
default:
return '';
}
})->align('center');
$grid->column('type', admin_trans('player_delivery_record.fields.type'))
->display(function ($value) {
switch ($value) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD))->color('#2db7f5');
break;
case PlayerDeliveryRecord::TYPE_RECHARGE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL))->color('#C98341');
break;
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT))->color('#108ee9');
break;
case PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_COMMISSION:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_COMMISSION))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_REGISTER_PRESENT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_REGISTER_PRESENT))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_SIGN:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_SIGN))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_GAME_IN:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_IN))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_GAME_OUT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_OUT))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_BET_REBATE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_BET_REBATE))->color('#C98341');
break;
case PlayerDeliveryRecord::TYPE_DAMAGE_REBATE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_DAMAGE_REBATE))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_RECHARGE_REWARD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE_REWARD))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_PROFIT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_PROFIT))->color('#3C87C9');
break;
default:
$tag = '';
}
return Html::create()->content([
$tag
]);
})->align('center')->sortable();
$grid->column('amount', admin_trans('player_delivery_record.fields.amount'))->display(function ($val, PlayerDeliveryRecord $data) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('amount_after', admin_trans('player_delivery_record.fields.amount_after'))->align('center');
$grid->column('amount_before', admin_trans('player_delivery_record.fields.amount_before'))->align('center');
$grid->column('user_name', admin_trans('player_delivery_record.fields.user_name'))->display(function ($val, PlayerDeliveryRecord $data) {
$name = '玩家';
if (in_array($data->type, [PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD, PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT])) {
$name = $data->user_name ?? '管理员';
}
return Html::create()->content([
Html::div()->content($name),
]);
});
$grid->column('created_at', admin_trans('player_delivery_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->like()->text('search_source')->placeholder(admin_trans('player_delivery_record.fields.source'));
$filter->eq()->select('type')
->placeholder(admin_trans('player_delivery_record.fields.type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD),
PlayerDeliveryRecord::TYPE_RECHARGE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE),
PlayerDeliveryRecord::TYPE_WITHDRAWAL => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL),
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT),
PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK),
PlayerDeliveryRecord::TYPE_REGISTER_PRESENT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_REGISTER_PRESENT),
PlayerDeliveryRecord::TYPE_COMMISSION => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_COMMISSION),
PlayerDeliveryRecord::TYPE_SIGN => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_SIGN),
PlayerDeliveryRecord::TYPE_GAME_OUT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_OUT),
PlayerDeliveryRecord::TYPE_GAME_IN => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_IN),
PlayerDeliveryRecord::TYPE_BET_REBATE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_BET_REBATE),
PlayerDeliveryRecord::TYPE_DAMAGE_REBATE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_DAMAGE_REBATE),
PlayerDeliveryRecord::TYPE_RECHARGE_REWARD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE_REWARD),
PlayerDeliveryRecord::TYPE_PROFIT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_PROFIT),
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->quickSearch();
});
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminDepartment;
use addons\webman\model\AdminPost;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Request;
/**
* 渠道岗位管理
* @group channel
*/
class ChannelPostController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.post_model');
}
/**
* 岗位
* @group channel
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('post.title'));
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->bordered(true);
$grid->column('name', admin_trans('post.fields.name'));
$grid->column('status', admin_trans('post.fields.status'))->switch([[1 => ''], [0 => '']]);
$grid->sortInput('sort', admin_trans('post.fields.sort'));
$grid->column('created_at', admin_trans('post.fields.create_at'));
$grid->filter(function (Filter $filter) {
$filter->like()->text('name')->placeholder(admin_trans('post.fields.name'));
$filter->eq()->select('status')
->placeholder(admin_trans('post.fields.status'))
->options([
1 => admin_trans('post.normal'),
0 => admin_trans('post.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);;
});
$grid->setForm()->modal($this->form());
$grid->quickSearch();
});
}
/**
* 岗位
* @group channel
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('post.title'));
$form->text('name', admin_trans('post.fields.name'))
->required();
$form->number('sort', admin_trans('post.fields.sort'))->default(0);
$form->saving(function (Form $form) {
if (!$form->isEdit()) {
$adminPost = new AdminPost();
$adminPost->name = $form->input('name');
$adminPost->sort = $form->input('sort');
$adminPost->department_id = Admin::user()->department_id;
$adminPost->type = AdminDepartment::TYPE_CHANNEL;
} else {
$adminPost = AdminPost::find($form->input('id'));
}
if (!$adminPost->save()) {
return message_error(admin_trans('form.save_error'));
}
return message_success(admin_trans('form.save_success'));
});
});
}
}

View File

@@ -0,0 +1,572 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminUser;
use addons\webman\model\ChannelRechargeMethod;
use addons\webman\model\ChannelRechargeMethodLang;
use addons\webman\model\ChannelRechargeSetting;
use addons\webman\model\SepayRecharge;
use addons\webman\model\SystemSetting;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\field\Switches;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\layout\Divider;
use ExAdmin\ui\support\Arr;
use ExAdmin\ui\support\Container;
use Illuminate\Database\Eloquent\Builder;
use support\Db;
/**
* 充值渠道
* @group channel
*/
class ChannelRechargeController
{
protected $model;
protected $method;
protected $sepay_model;
public function __construct()
{
$this->model = plugin()->webman->config('database.channel_recharge_setting_model');
$this->method = plugin()->webman->config('database.channel_recharge_method_model');
$this->sepay_model = plugin()->webman->config('database.sepay_recharge_model');
}
/**
* 充值账号
* @group channel
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$lang = Container::getInstance()->translator->getLocale();
$channelRechargeMethods = ChannelRechargeMethod::query()
->where('status', 1)
->select(['id', 'account', 'currency'])
->with(['methodLang' => function ($query) use ($lang) {
$query->where('lang', $lang);
}])
->get()->toArray();
foreach ($channelRechargeMethods as &$item) {
$item['name'] = $item['method_lang'][0]['name'] ?? '';
}
$grid->sidebar('method_id', $channelRechargeMethods)
->setForm($this->methodForm());
$grid->title(admin_trans('channel_recharge_setting.title'));
$grid->model()->with(['channel_recharge_method'])->whereHas('channel_recharge_method', function ($query) {
$query->whereNull('deleted_at');
});
$grid->autoHeight();
$grid->bordered(true);
$lang = Container::getInstance()->translator->getLocale();
$grid->tools([
Button::create(admin_trans('channel_recharge_setting.first_recharge_setting'))
->danger()
->drawer($this->rechargeSetting())
]);
$grid->column('id', admin_trans('channel_recharge_setting.fields.id'))->align('center');
$grid->column('title', admin_trans('channel_recharge_setting.fields.title'))->align('center');
$grid->column('method_name', admin_trans('channel_recharge_setting.fields.method_name'))
->display(function ($val, ChannelRechargeSetting $data) use ($lang) {
/** @var ChannelRechargeMethodLang $methodLang */
$methodLang = $data->channel_recharge_method->methodLang->where('lang', $lang)->first();
return $methodLang->name ?? '';
})
->align('center')
->ellipsis(true);
$grid->column('type', admin_trans('player_delivery_record.fields.type'))
->display(function ($value) {
switch ($value) {
case ChannelRechargeSetting::TYPE_REGULAR:
$tag = Tag::create(admin_trans('channel_recharge_setting.type.' . ChannelRechargeSetting::TYPE_REGULAR))->color('#2db7f5');
break;
case ChannelRechargeSetting::TYPE_ACTIVITY:
$tag = Tag::create(admin_trans('channel_recharge_setting.type.' . ChannelRechargeSetting::TYPE_ACTIVITY))->color('#3C87C9');
break;
default:
$tag = '';
}
return Html::create()->content([
$tag
]);
})->align('center')->sortable();
$grid->column('chip_multiple', admin_trans('channel_recharge_setting.fields.chip_multiple'))->align('center');
$grid->column('coins_num', admin_trans('channel_recharge_setting.fields.coins_num'))->align('center');
$grid->column('gift_coins', admin_trans('channel_recharge_setting.fields.gift_coins'))->align('center');
$grid->column('money', admin_trans('channel_recharge_setting.fields.money'))->align('center');
$grid->column('user_name', admin_trans('channel_recharge_setting.fields.user_name'))->align('center');
$grid->column('status', admin_trans('channel_recharge_setting.fields.status'))->switch()->align('center');
$grid->filter(function (Filter $filter) {
$filter->eq()->number('coins_num')->placeholder(admin_trans('channel_recharge_setting.fields.coins_num'));
$filter->eq()->number('money')->placeholder(admin_trans('channel_recharge_setting.fields.money'));
});
$grid->quickSearch(function (Builder $builder, $quickSearch) {
$builder->whereHas('channel_recharge_method.methodLang', function ($query) use ($quickSearch) {
$query->where([
['name', 'like', '%' . $quickSearch . '%', 'or'],
['bank_name', 'like', '%' . $quickSearch . '%', 'or'],
['sub_bank', 'like', '%' . $quickSearch . '%', 'or'],
['account', 'like', '%' . $quickSearch . '%', 'or'],
['owner', 'like', '%' . $quickSearch . '%', 'or'],
]);
});
});
$grid->hideDelete();
$grid->hideSelection();
$grid->hideDeleteSelection();
$grid->hideTrashed();
$grid->addButton()->drawer($this->form());
$grid->setForm()->drawer($this->form());
$grid->actions(function (Actions $actions) {
$actions->hideEdit();
});
});
}
/**
* 充值账号配置
* @auth true
* @group channel
* @return Form
*/
public function form(): Form
{
/** @var ChannelRechargeMethod $channelRechargeMethod */
$channelRechargeMethod = ChannelRechargeMethod::query()
->where('department_id', Admin::user()->department_id)
->where('type', 2)
->first();
if (!$channelRechargeMethod) {
$channelRechargeMethod = [
'id' => '',
'wallet_address' => '',
'qr_code' => '',
'rate' => '',
'status' => '',
];
}
return Form::create($channelRechargeMethod, function (Form $form) use ($channelRechargeMethod) {
$form->text('wallet_address', admin_trans('channel_recharge_setting.fields.wallet_address'))
->value($channelRechargeMethod['wallet_address'])
->required()
->maxlength(250);
$form->file('qr_code', admin_trans('channel_recharge_setting.fields.qr_code'))
->ext('jpg,png,jpeg')
->value($channelRechargeMethod['qr_code'])
->type('image')
->fileSize('1m')
->required()
->hideFinder()
->paste();
$form->number('rate', admin_trans('channel_recharge_setting.fields.rate'))
->min(0)
->max(100)
->value($channelRechargeMethod['rate'])
->span(24)
->style(['width' => '50%'])
->required()
->precision(2);
$form->switch('status', admin_trans('channel_recharge_method.fields.status'))
->value($channelRechargeMethod['status'])->required()->span(11);
$form->colon(false);
$form->removeAttr('labelCol');
$form->actions()->hideResetButton();
$form->actions()->submitButton()->content(admin_trans('form.submit'));
$form->layout('vertical');
$form->saving(function (Form $form) use ($channelRechargeMethod) {
try {
DB::beginTransaction();
if (!$channelRechargeMethod['id']) {
$channelRechargeMethod = new ChannelRechargeMethod();
$channelRechargeMethod->type = 2;
$channelRechargeMethod->currency = Admin::user()->department->channel->currency;
$channelRechargeMethod->department_id = Admin::user()->department_id;
$channelRechargeMethod->user_id = Admin::id();
$channelRechargeMethod->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
}
$channelRechargeMethod->qr_code = $form->input('qr_code');
$channelRechargeMethod->wallet_address = $form->input('wallet_address');
$channelRechargeMethod->status = $form->input('status');
$channelRechargeMethod->rate = $form->input('rate');
$channelRechargeMethod->save();
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
return message_error(admin_trans('form.save_error') . $exception->getMessage());
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* 获取充值方式
* @return array
*/
public function getRechargeMethod(): array
{
$options = [];
$lang = Container::getInstance()->translator->getLocale();
$methodList = ChannelRechargeMethod::query()->get();
/** @var ChannelRechargeMethod $item */
foreach ($methodList as $item) {
/** @var ChannelRechargeMethodLang $methodLang */
$methodLang = $item->methodLang->where('lang', $lang)->first();
$options[$item->id] = $methodLang->name ?? '';
}
return $options;
}
/**
* 充值方式
* @auth true
* @group channel
* @return Form
*/
public function methodForm(): Form
{
/** @var ChannelRechargeMethod $channelRechargeMethod */
$channelRechargeMethod = ChannelRechargeMethod::query()
->where('department_id', Admin::user()->department_id)
->where('type', 1)
->first();
if (!$channelRechargeMethod) {
$channelRechargeMethod = [
'id' => '',
'account' => '',
'status' => '',
];
}
return Form::create($channelRechargeMethod, function (Form $form) use ($channelRechargeMethod) {
$form->row(function (Form $form) use ($channelRechargeMethod) {
$form->text('account', admin_trans('channel_recharge_method.fields.account'))
->maxlength(100)
->value($channelRechargeMethod['account'])
->required()
->span(11);
$form->push(Divider::create()->content(' ')->style(['margin-left' => '11px']));
$form->switch('status', admin_trans('channel_recharge_method.fields.status'))
->value($channelRechargeMethod['status'])->required()->span(11);
});
$langList = plugin()->webman->config('ui.lang.list');
$tabs = $form->tabs()->destroyInactiveTabPane();
$contents = [];
if ($channelRechargeMethod['id']) {
$channelRechargeMethodLang = ChannelRechargeMethodLang::query()->where('method_id', $channelRechargeMethod['id'])->get();
/** @var ChannelRechargeMethodLang $content */
foreach ($channelRechargeMethodLang as $content) {
$contents[$content->lang] = [
'name' => $content->name,
'bank_name' => $content->bank_name,
'sub_bank' => $content->sub_bank,
'owner' => $content->owner,
'id' => $content->id,
];
}
}
foreach ($langList as $k => $v) {
$tabs->pane($v, function (Form $form) use ($k, $contents) {
$form->row(function (Form $form) use ($k, $contents) {
$form->text("content." . $k . ".name", admin_trans('channel_recharge_method.fields.method_name'))
->maxlength(120)
->value($contents[$k]['name'] ?? '')
->required()
->span(11);
$form->push(Divider::create()->content(' ')->style(['margin-left' => '11px']));
$form->text("content." . $k . ".bank_name", admin_trans('channel_recharge_method.fields.bank_name'))
->value($contents[$k]['bank_name'] ?? '')
->maxlength(100)
->required()
->span(11);
})->style(['width' => '100 % ', 'margin - left' => '1px']);
$form->row(function (Form $form) use ($k, $contents) {
$form->text("content." . $k . ".sub_bank", admin_trans('channel_recharge_method.fields.sub_bank'))
->value($contents[$k]['sub_bank'] ?? '')
->maxlength(100)
->required()
->span(11);
$form->push(Divider::create()->content(' ')->style(['margin-left' => '11px']));
$form->text("content." . $k . ".owner", admin_trans('channel_recharge_method.fields.owner'))
->value($contents[$k]['owner'] ?? '')
->maxlength(100)
->required()
->span(11);
})->style(['width' => '100 % ', 'margin - left' => '1px']);
});
}
$form->colon(false);
$form->removeAttr('labelCol');
$form->actions()->hideResetButton();
$form->actions()->submitButton()->content(admin_trans('form.submit'));
$form->layout('vertical');
$form->saving(function (Form $form) use ($channelRechargeMethod) {
try {
DB::beginTransaction();
if ($channelRechargeMethod['id']) {
$channelRechargeMethod->account = $form->input('account');
$channelRechargeMethod->currency = Admin::user()->department->channel->currency;
} else {
$channelRechargeMethod = new ChannelRechargeMethod();
$channelRechargeMethod->account = $form->input('account');
$channelRechargeMethod->currency = Admin::user()->department->channel->currency;
$channelRechargeMethod->department_id = Admin::user()->department_id;
$channelRechargeMethod->user_id = Admin::id();
$channelRechargeMethod->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
}
$channelRechargeMethod->status = $form->input('status');
$channelRechargeMethod->save();
$contents = $form->input('content');
foreach ($contents as $key => $content) {
if (empty($content['name'])) {
continue;
}
ChannelRechargeMethodLang::query()->updateOrCreate(
[
'lang' => $key,
'method_id' => $channelRechargeMethod->id,
],
[
'name' => $content['name'],
'bank_name' => $content['bank_name'] ?? '',
'sub_bank' => $content['sub_bank'] ?? '',
'owner' => $content['owner'] ?? ''
]
);
}
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
return message_error(admin_trans('form.save_error') . $exception->getMessage());
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* @return Form
*/
public function rechargeSetting(): Form
{
/** @var SystemSetting $systemSetting */
$systemSetting = SystemSetting::query()
->where('department_id', Admin::user()->department_id)
->where('feature', 'first_recharge_setting')
->first();
return Form::create($systemSetting ? [
'id' => $systemSetting->id,
'department_id' => $systemSetting->department_id,
'feature' => $systemSetting->feature,
'content' => json_decode($systemSetting->content, true),
'status' => $systemSetting->status,
] : [], function (Form $form) use ($systemSetting) {
$form->push(
Switches::create('status')
->options([[1 => admin_trans('admin.open')], [0 => admin_trans('admin.close')]])
->field('status')
->title('状态')
->url('ex-admin/addons-webman-controller-ActivityController/changeStatus')
->params([
'id' => $systemSetting->id,
])->style(['margin-bottom' => '14px'])
);
$form->hasMany('content', '', function (Form $form) {
$form->row(function (Form $form) {
$form->radio('model', admin_trans('first_recharge_setting.fields.model'))
->button()
->required()
->default(SystemSetting::FIRST_RECHARGE_MODEL_ONE)
->bindAttr('buttonStyle', $form->getBindField('buttonStyle'))
->options([
SystemSetting::FIRST_RECHARGE_MODEL_ONE => admin_trans('first_recharge_setting.model.' . SystemSetting::FIRST_RECHARGE_MODEL_ONE),
SystemSetting::FIRST_RECHARGE_MODEL_ADD => admin_trans('first_recharge_setting.model.' . SystemSetting::FIRST_RECHARGE_MODEL_ADD),
])->when(SystemSetting::FIRST_RECHARGE_MODEL_ADD, function (Form $form) {
$form->text('add_number', admin_trans('first_recharge_setting.fields.add_number'))
->rule([
'integer' => admin_trans('validator.integer'),
'max:100000' => admin_trans('validator.max', null, ['{max}' => 100000000]),
'min:1' => admin_trans('validator.min', null, ['{min}' => 1]),
])
->span(24)
->required();
})->span(24);
$form->radio('type', admin_trans('first_recharge_setting.fields.type'))
->button()
->required()
->default(SystemSetting::FIRST_RECHARGE_TYPE_VALUE)
->bindAttr('buttonStyle', $form->getBindField('buttonStyle'))
->options([
SystemSetting::FIRST_RECHARGE_TYPE_VALUE => admin_trans('first_recharge_setting.type.' . SystemSetting::FIRST_RECHARGE_TYPE_VALUE),
SystemSetting::FIRST_RECHARGE_TYPE_PERCENT => admin_trans('first_recharge_setting.type.' . SystemSetting::FIRST_RECHARGE_TYPE_PERCENT),
])
->when(SystemSetting::FIRST_RECHARGE_TYPE_VALUE, function (Form $form) {
$form->text('number', admin_trans('first_recharge_setting.fields.number'))
->rule([
'integer' => admin_trans('validator.integer'),
'max:100000' => admin_trans('validator.max', null, ['{max}' => 100000000]),
'min:1' => admin_trans('validator.min', null, ['{min}' => 1]),
])
->required()
->span(24)
->suffix('coin');
})
->when(SystemSetting::FIRST_RECHARGE_TYPE_PERCENT, function (Form $form) {
$form->text('number', admin_trans('first_recharge_setting.fields.number_percent'))
->rule([
'integer' => admin_trans('validator.integer'),
'max:100000' => admin_trans('validator.max', null, ['{max}' => 100000000]),
'min:1' => admin_trans('validator.min', null, ['{min}' => 1]),
])
->required()
->span(24)
->suffix('%');
});
$form->number('chip_multiple', admin_trans('first_recharge_setting.fields.chip_amount'))
->min(0)
->max(100000000)
->span(24)
->style(['width' => '100%'])
->required()
->precision(2);
})->class(['activity-phase-has-many']);
})->sortField('sort')->defaultRow(1);
$form->layout('vertical');
$form->saving(function (Form $form) {
$content = $form->input('content');
$settingContent = [];
foreach ($content as $item) {
$settingContent[] = [
'model' => $item['model'],
'type' => $item['type'],
'add_number' => $item['add_number'] ?? 0,
'chip_multiple' => $item['chip_multiple'],
'number' => $item['number'],
];
}
if (!SystemSetting::updateOrCreate(
[
'department_id' => Admin::user()->department_id,
'feature' => 'first_recharge_setting',
],
[
'content' => json_encode($settingContent)
]
)) {
return message_error(admin_trans('form.save_error'));
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* 在线充值
* @group channel
* @auth true
*/
public function speedPayList(): Grid
{
return Grid::create(new $this->sepay_model(), function (Grid $grid) {
$grid->autoHeight();
$grid->bordered(true);
$grid->tools([
Button::create(admin_trans('channel_recharge_setting.manual_recharge_setting'))
->danger()
->drawer($this->methodForm()),
Button::create(admin_trans('channel_recharge_setting.usdt_recharge_setting'))
->danger()
->drawer($this->form())
]);
$grid->model()->where('department_id', Admin::user()->department_id)->orderBy('money');
$grid->column('id', admin_trans('channel_recharge_setting.fields.id'))->align('center');
$grid->column('title', admin_trans('channel_recharge_setting.fields.title'))->align('center');
$grid->column('coins_num', admin_trans('channel_recharge_setting.fields.coins_num'))->align('center');
$grid->column('first_coins', admin_trans('channel_recharge_setting.fields.first_coins'))->align('center');
$grid->column('money', admin_trans('channel_recharge_setting.fields.money'))->align('center');
$grid->column('admin_id', admin_trans('channel_recharge_setting.fields.user_name'))->display(function ($val) {
return AdminUser::query()->find($val)->username;
})
->align('center');
$grid->column('status', admin_trans('channel_recharge_setting.fields.status'))->switch()->align('center');
$grid->column('created_at', admin_trans('qrcode.qrcode_batch.created_at'))->align('center')->fixed(true);
$grid->hideDelete();
$grid->hideSelection();
$grid->hideDeleteSelection();
$grid->hideTrashed();
$grid->addButton()->drawer($this->addSpeedPay());
$grid->actions(function (Actions $actions) {
$actions->hideEdit();
});
});
}
/**
* 在线充值配置
* @auth true
* @group channel
* @return Form
*/
public function addSpeedPay(): Form
{
return Form::create(new $this->sepay_model(), function (Form $form) {
$form->text('title', admin_trans('channel_recharge_setting.fields.title'))->maxlength(30)->required();
$form->number('coins_num', admin_trans('channel_recharge_setting.fields.coins_num'))
->style(['width' => '100%'])
->min(1)
->max(100000000)
->precision(2)
->required()
->rule([
'required' => admin_trans('channel_recharge_setting.rul.coins_num'),
'min:1' => admin_trans('channel_recharge_setting.rul.coins_num_1'),
'max:100000000' => admin_trans('channel_recharge_setting.rul.coins_num_max_100000000'),
])
->placeholder(admin_trans('channel_recharge_setting.placeholder_coins_num'));
$form->number('first_coins', admin_trans('channel_recharge_setting.fields.first_coins'))
->style(['width' => '100%'])
->min(0)
->max(100000000)
->precision(2)
->rule([
'required' => admin_trans('channel_recharge_setting.rul.first_coins'),
'min:0' => admin_trans('channel_recharge_setting.rul.gift_coins_1'),
'max:100000000' => admin_trans('channel_recharge_setting.rul.gift_coins_max_100000000'),
])
->placeholder(admin_trans('channel_recharge_setting.placeholder_coins_num'));
$form->number('money', admin_trans('channel_recharge_setting.fields.money'))
->style(['width' => '100%'])
->min(5)
->max(20000)
->precision(2)
->required()
->placeholder(admin_trans('channel_recharge_setting.placeholder_money'));
$form->layout('vertical');
$form->saving(function (Form $form) {
try {
$setting = new SepayRecharge();
$setting->department_id = Admin::user()->department_id;
$setting->title = $form->input('title');
$setting->coins_num = $form->input('coins_num');
$setting->first_coins = $form->input('first_coins');
$setting->money = $form->input('money');
$setting->admin_id = Admin::id();
$setting->save();
} catch (\Exception $exception) {
return message_error(admin_trans('form.save_error'));
}
return message_success(admin_trans('form.save_success'));
});
});
}
}

View File

@@ -0,0 +1,644 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\ChannelFinancialRecord;
use addons\webman\model\ChannelRechargeMethodLang;
use addons\webman\model\ChannelRechargeSetting;
use addons\webman\model\CommissionRecord;
use addons\webman\model\Player;
use addons\webman\model\PlayerChipRecord;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerLevel;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\SystemSetting;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\detail\Detail;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\EmptyStatus;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\component\navigation\dropdown\Dropdown;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use support\Db;
use support\Log;
/**
* 充值记录
* @group channel
*/
class ChannelRechargeRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_recharge_record_model');
}
/**
* 渠道充值
* @group channel
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_recharge_record.title'));
$grid->model()->with(['player', 'channel_recharge_setting'])->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ARTIFICIAL, PlayerRechargeRecord::TYPE_ACTIVITY])->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
if (!empty($exAdminFilter['player']['uuid'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('uuid', 'like', '%' . $exAdminFilter['player']['uuid'] . '%');
});
}
if (!empty($exAdminFilter['player']['name'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('name', 'like', '%' . $exAdminFilter['player']['name'] . '%');
});
}
if (!empty($exAdminFilter['type'])) {
$grid->model()->where('type', $exAdminFilter['type']);
}
if (isset($exAdminFilter['status']) && (!empty($exAdminFilter['status']) || $exAdminFilter['status'] === 0)) {
$grid->model()->where('status', $exAdminFilter['status']);
}
if (!empty($exAdminFilter['tradeno'])) {
$grid->model()->where('tradeno', $exAdminFilter['tradeno']);
}
}
$query = clone $grid->model();
$totalData = $query->selectRaw(
"ifNull(sum(IF(type = 4, money,0)), 0) as total_artificial_money,
ifNull(sum(IF(type = 1, money,0)), 0) as total_espay_money,
ifNull(sum(IF(payment_method = 'DUITNOWP2P', money,0)), 0) as total_espay_duitnow_money,
ifNull(sum(IF(payment_method = 'P2PDEPOSIT', money,0)), 0) as total_espay_deposit_money,
ifNull(sum(IF(payment_method = 'duitnowqr', money,0)), 0) as total_onepay_duitnow_money,
ifNull(sum(IF(payment_method = 'online_banking', money,0)), 0) as total_onepay_deposit_money,
ifNull(sum(IF(payment_method = 'QR', money,0)), 0) as total_skl_duitnow_money,
ifNull(sum(IF(payment_method = 'P2P', money,0)), 0) as total_skl_deposit_money"
)->first();
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_artificial_money'))
->value(!empty($totalData['total_artificial_money']) ? floatval($totalData['total_artificial_money']) : 0)->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_espay_money'))
->value(!empty($totalData['total_espay_money']) ? floatval($totalData['total_espay_money']) : 0)->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_espay_inmoney'))
->value(bcadd(bcadd(
bcadd(bcmul($totalData['total_espay_duitnow_money'], 0.97, 3), bcmul($totalData['total_espay_deposit_money'], 0.985, 3), 3),
bcadd(bcmul($totalData['total_onepay_duitnow_money'], 0.984, 3), bcmul($totalData['total_onepay_deposit_money'], 0.986, 3), 3),
3), bcadd(bcmul($totalData['total_skl_duitnow_money'], 0.987, 3), bcmul($totalData['total_skl_deposit_money'], 0.989, 3), 3), 3))
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
})->style(['background' => '#fff']);
$grid->header($layout);
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('player_recharge_record.fields.id'))->align('center')->fixed(true);
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->copy()->fixed(true);
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->copy()->fixed(true);
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerRechargeRecord $data) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
})->align('center');
$grid->column('inmoney', admin_trans('player_recharge_record.fields.inmoney'))->display(function ($val, PlayerRechargeRecord $data) {
if ($data->payment_method == 'DUITNOWP2P') {
$ratio = 0.97;
} elseif ($data->payment_method == 'P2PDEPOSIT') {
$ratio = 0.985;
} elseif ($data->payment_method == 'duitnowqr') {
$ratio = 0.984;
} elseif ($data->payment_method == 'online_banking') {
$ratio = 0.986;
} elseif ($data->payment_method == 'P2P') {
$ratio = 0.989;
} elseif ($data->payment_method == 'QR') {
$ratio = 0.987;
} else {
$ratio = 1;
}
if ($data->currency == 'USDT') {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
}
return $data->money * $ratio . ' ' . ($data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->align('center')->sortable();
$grid->column('gift_coins', admin_trans('player_recharge_record.fields.gift_coins'))->align('center');
$grid->column('type', admin_trans('player_recharge_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::TYPE_REGULAR:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#55acee');
case PlayerRechargeRecord::TYPE_ACTIVITY:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->align('center');
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::STATUS_WAIT:
return Tag::create(admin_trans('player_recharge_record.status_wait'))
->color('#108ee9');
case PlayerRechargeRecord::STATUS_RECHARGING:
return Tag::create(admin_trans('player_recharge_record.status_examine'))
->color('#3b5999');
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return Tag::create(admin_trans('player_recharge_record.status_success'))
->color('#87d068');
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return Tag::create(admin_trans('player_recharge_record.status_fail'))
->color('#f50');
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_cancel'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
return Tag::create(admin_trans('player_recharge_record.status_reject'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_system_cancel'))
->color('#2db7f5');
default:
return '';
}
})->align('center');
$grid->column('remark', admin_trans('player_recharge_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_recharge_record.fields.remark')])
)->width('150px')->align('center');
$grid->column('user_name', admin_trans('player_recharge_record.fields.user_name'))->align('center');
$grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->sortable()->align('center')->fixed('right');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.type'))
->options([
PlayerRechargeRecord::TYPE_REGULAR => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_REGULAR),
PlayerRechargeRecord::TYPE_ARTIFICIAL => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ARTIFICIAL),
]);
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.status'))
->options([
PlayerRechargeRecord::STATUS_WAIT => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_WAIT),
PlayerRechargeRecord::STATUS_RECHARGING => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGING),
PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS),
PlayerRechargeRecord::STATUS_RECHARGED_FAIL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_FAIL),
PlayerRechargeRecord::STATUS_RECHARGED_CANCEL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_CANCEL),
PlayerRechargeRecord::STATUS_RECHARGED_REJECT => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_REJECT),
PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);
});
});
}
/**
* 充值审核
* @group channel
* @auth true
*/
public function examineList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_recharge_record.examine_title'));
$grid->bordered(true);
$grid->autoHeight();
$requestFilter = Request::input('ex_admin_filter', []);
$tradeno = Request::input('tradeno', []);
if (!empty($tradeno)) {
$grid->model()->where('tradeno', $tradeno);
}
$grid->model()->with(['player', 'channel_recharge_setting'])->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ACTIVITY])
->whereIn('status', [PlayerRechargeRecord::STATUS_RECHARGING, PlayerRechargeRecord::STATUS_WAIT, PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS, PlayerRechargeRecord::STATUS_RECHARGED_REJECT, PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL])
->whereNull('payment_method')
->orderBy('created_at', 'desc');
if (isset($requestFilter['created_at_start']) && !empty($requestFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $requestFilter['created_at_start']);
}
if (isset($requestFilter['created_at_end']) && !empty($requestFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $requestFilter['created_at_end']);
}
$grid->column('id', admin_trans('player_recharge_record.fields.id'))->align('center');
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->copy();
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->copy();
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerRechargeRecord $data) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . $data->currency;
})->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->align('center');
$grid->column('gift_coins', admin_trans('player_recharge_record.fields.gift_coins'))->align('center');
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::STATUS_WAIT:
return Tag::create(admin_trans('player_recharge_record.status_wait'))
->color('#108ee9');
case PlayerRechargeRecord::STATUS_RECHARGING:
return Tag::create(admin_trans('player_recharge_record.status_examine'))
->color('#3b5999');
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return Tag::create(admin_trans('player_recharge_record.status_success'))
->color('#87d068');
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return Tag::create(admin_trans('player_recharge_record.status_fail'))
->color('#f50');
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_cancel'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
return Tag::create(admin_trans('player_recharge_record.status_reject'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_system_cancel'))
->color('#2db7f5');
default:
return '';
}
})->align('center');
$grid->column('remark', admin_trans('player_recharge_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_recharge_record.fields.remark')])
)->width('150px')->align('center');
$grid->column('reject_reason', admin_trans('player_recharge_record.fields.reject_reason'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->tip()->width('150px')->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions, PlayerRechargeRecord $data) {
$actions->hideDel();
$actions->hideEdit();
$dropdown = Dropdown::create(
Button::create([
admin_trans('player_recharge_record.btn.action'), Icon::create('DownOutlined')->style(['marginRight' => '5px'])
]))->trigger(['click']);
$dropdown->item(admin_trans('player_recharge_record.btn.view_channel_recharge_setting'), 'AppstoreAddOutlined')
->modal([$this, 'rechargeSetting'], ['setting_id' => $data->setting_id]);
$dropdown->item(admin_trans('player_recharge_record.btn.view_recharge_certificate'), 'far fa-file-image')
->modal($this->rechargeCertificate([
'tradeno' => $data->tradeno,
'certificate' => $data->certificate,
]))->title(admin_trans('player_recharge_record.view_recharge_certificate_title', null, ['{tradeno}' => $data->tradeno]));
$dropdown->item(admin_trans('player_recharge_record.btn.examine_pass'), 'SafetyCertificateOutlined')
->confirm(admin_trans('player_recharge_record.btn.examine_pass_confirm'), [$this, 'pass'], ['id' => $data->id]);
$dropdown->item(admin_trans('player_recharge_record.btn.examine_reject'), 'WarningFilled')
->modal([$this, 'reject'], ['id' => $data->id]);
$actions->prepend(
$dropdown
);
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.status'))
->options([
PlayerRechargeRecord::STATUS_WAIT => admin_trans('player_recharge_record.status_wait'),
PlayerRechargeRecord::STATUS_RECHARGING => admin_trans('player_recharge_record.status_examine'),
PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS => admin_trans('player_recharge_record.status_examine_pass'),
PlayerRechargeRecord::STATUS_RECHARGED_REJECT => admin_trans('player_recharge_record.status_examine_reject'),
PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL => admin_trans('player_recharge_record.status_system_cancel'),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->eq()->number('money')->precision(2)->style(['width' => '200px'])->placeholder(admin_trans('player_recharge_record.fields.money'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
});
}
/**
* 充值订单审核拒绝
* @auth true
* @group channel
* @param $id
* @return Form
*/
public function reject($id): Form
{
return Form::create(new $this->model(), function (Form $form) use ($id) {
$form->textarea('reject_reason')->rows(5)->required();
$form->saving(function (Form $form) use ($id) {
/** @var PlayerRechargeRecord $playerRechargeRecord */
$playerRechargeRecord = $this->model::find($id);
if (empty($playerRechargeRecord)) {
return message_error(admin_trans('player_recharge_record.not_fount'));
}
if ($playerRechargeRecord->type != PlayerRechargeRecord::TYPE_REGULAR && $playerRechargeRecord->type != PlayerRechargeRecord::TYPE_ACTIVITY) {
return message_error(admin_trans('player_recharge_record.recharge_record_error'));
}
switch ($playerRechargeRecord->status) {
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_pass'));
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_fail'));
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_cancel'));
case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_reject'));
case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_system_cancel'));
}
try {
// 生成订单
$playerRechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGED_REJECT;
$playerRechargeRecord->reject_reason = $form->input('reject_reason');
$playerRechargeRecord->finish_time = date('Y-m-d H:i:s');
$playerRechargeRecord->user_id = Admin::id() ?? 0;
$playerRechargeRecord->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
if ($playerRechargeRecord->save()) {
saveChannelFinancialRecord($playerRechargeRecord, ChannelFinancialRecord::ACTION_RECHARGE_REJECT);
}
} catch (\Exception $e) {
return message_error(admin_trans('player_recharge_record.action_error'));
}
return message_success(admin_trans('player_recharge_record.action_success'));
});
});
}
/**
* 充值订单审核通过
* @param $id
* @auth true
* @group channel
* @return Msg
*/
public function pass($id): Msg
{
/** @var PlayerRechargeRecord $playerRechargeRecord */
$playerRechargeRecord = $this->model::find($id);
if (empty($playerRechargeRecord)) {
return message_error(admin_trans('player_recharge_record.not_fount'));
}
if ($playerRechargeRecord->type != PlayerRechargeRecord::TYPE_REGULAR && $playerRechargeRecord->type != PlayerRechargeRecord::TYPE_ACTIVITY) {
return message_error(admin_trans('player_recharge_record.recharge_record_error'));
}
switch ($playerRechargeRecord->status) {
case PlayerRechargeRecord::STATUS_WAIT:
return message_warning(admin_trans('player_recharge_record.recharge_record_not_complete'));
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_pass'));
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_fail'));
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_cancel'));
case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_reject'));
case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
return message_warning(admin_trans('player_recharge_record.recharge_record_has_system_cancel'));
}
/** @var Channel $channel */
$channel = Channel::where('department_id', Admin::user()->department_id)->first();
if (empty($channel)) {
return message_error(admin_trans('channel.not_fount'));
}
DB::beginTransaction();
try {
$firstRecharge = PlayerRechargeRecord::query()
->where('player_id', $playerRechargeRecord->player_id)
->where('status', 2)
->where('setting_id', '>', 0)
->doesntExist();
if (!$firstRecharge) {
$playerRechargeRecord->gift_coins = 0;
}
$beforeGameAmount = $playerRechargeRecord->player->wallet->money;
// 生成订单
$playerRechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS;
$playerRechargeRecord->finish_time = date('Y-m-d H:i:s');
$playerRechargeRecord->user_id = Admin::id() ?? 0;
$playerRechargeRecord->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
$allCoins = bcadd($playerRechargeRecord->coins, $playerRechargeRecord->gift_coins, 2);
$playerRechargeRecord->player->wallet->money = bcadd($playerRechargeRecord->player->wallet->money, $allCoins, 2);
$playerRechargeRecord->player->player_extend->recharge_amount = bcadd($playerRechargeRecord->player->player_extend->recharge_amount, $allCoins, 2);
// 寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerRechargeRecord->player_id;
$playerDeliveryRecord->department_id = $playerRechargeRecord->department_id;
$playerDeliveryRecord->target = $playerRechargeRecord->getTable();
$playerDeliveryRecord->target_id = $playerRechargeRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_RECHARGE;
$playerDeliveryRecord->source = 'self_recharge';
$playerDeliveryRecord->amount = $allCoins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $playerRechargeRecord->player->wallet->money;
$playerDeliveryRecord->tradeno = $playerRechargeRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerRechargeRecord->remark ?? '';
$playerDeliveryRecord->save();
// 更新渠道信息
$channel->recharge_amount = bcadd($channel->recharge_amount, $allCoins, 2);
$channel->save();
$playerRechargeRecord->push();
// 記錄財務操作
saveChannelFinancialRecord($playerRechargeRecord, ChannelFinancialRecord::ACTION_RECHARGE_PASS);
DB::commit();
sendSocketMessage('private-recharge_withdrawal', [
'msg_type' => 'withdrawal',
'player_id' => $playerRechargeRecord->player_id,
'amount' => $playerRechargeRecord->player->wallet->money,
]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('充值错误', [$e->getTrace()]);
return message_error(admin_trans('player_recharge_record.action_error') . $e->getMessage() . $e->getLine());
}
return message_success(admin_trans('player_recharge_record.action_success'))->refresh();
}
/**
* 查看付款凭证
* @auth true
* @group channel
* @param $data
* @return Detail
*/
public function rechargeCertificate($data): Detail
{
return Detail::create($data, function (Detail $detail) {
$detail->item('certificate')->display(function ($val) {
if (!empty($val)) {
$image = Image::create()
->width(100)
->height(100)
->style(['objectFit' => 'cover'])
->src($val);
}
return Html::create()->content([
$image ?? EmptyStatus::create()->style(['margin' => '0 160px !important'])
])->style(['margin' => '0 auto']);
});
})->column(1);
}
/**
* 查看充值账号配置
* @auth true
* @group channel
* @param $setting_id
* @return Detail
*/
public function rechargeSetting($setting_id): Detail
{
$lang = Container::getInstance()->translator->getLocale();
/** @var ChannelRechargeSetting $data */
$data = ChannelRechargeSetting::find($setting_id);
/** @var ChannelRechargeMethodLang $methodLang */
$methodLang = $data->channel_recharge_method->methodLang->where('lang', $lang)->first();
return Detail::create([
'bank_name' => $methodLang->bank_name ?? '',
'sub_bank' => $methodLang->sub_bank ?? '',
'owner' => $methodLang->owner ?? '',
'account' => $data->channel_recharge_method->account,
], function (Detail $detail) {
$detail->item('bank_name', admin_trans('channel_recharge_method.fields.bank_name'));
$detail->item('sub_bank', admin_trans('channel_recharge_method.fields.sub_bank'));
$detail->item('owner', admin_trans('channel_recharge_method.fields.owner'));
$detail->item('account', admin_trans('channel_recharge_method.fields.account'));
})->column(2);
}
/**
* 筛选玩家下拉
* @return mixed
*/
public function getPlayerOptions()
{
$request = Request::input();
$player = Player::orderBy('created_at', 'desc')
->forPage(1, 20);
if (!empty($request['search'])) {
$player->where('phone', 'like', '%' . $request['search'] . '%');
}
$playerList = $player->get();
$data = [];
/** @var Player $player */
foreach ($playerList as $player) {
$data[] = [
'value' => $player->id,
'label' => $player->phone,
];
}
return Response::success($data);
}
}

View File

@@ -0,0 +1,846 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\ChannelFinancialRecord;
use addons\webman\model\Notice;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerWithdrawRecord;
use app\service\OnePayServices;
use app\service\SePayServices;
use app\service\SklPayServices;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\badge\Badge;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\component\navigation\dropdown\Dropdown;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\support\Request;
use Illuminate\Support\Str;
/**
* 提现记录
* @group channel
*/
class ChannelWithdrawRecordController
{
protected $model;
protected $rechargeModel;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_withdraw_record_model');
$this->rechargeModel = plugin()->webman->config('database.player_recharge_record_model');
}
/**
* 提现审核
* @group channel
* @auth true
*/
public function examineList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_withdraw_record.examine_title'));
$grid->bordered(true);
$grid->autoHeight();
$tradeno = Request::input('tradeno', []);
if (!empty($tradeno)) {
$grid->model()->where('tradeno', $tradeno);
}
$grid->model()->with(['player'])
->where('type', PlayerWithdrawRecord::TYPE_SELF)
->orWhere('status',PlayerWithdrawRecord::STATUS_WAIT)
->orderBy('created_at', 'desc')
->orderBy('status', 'asc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
}
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->align('center');
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->copy();
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->copy();
$grid->column('player.name', admin_trans('player_withdraw_record.fields.player'))->display(function ($val, PlayerWithdrawRecord $data) {
if (!empty($data->player)) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
}
return '';
})->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerWithdrawRecord::TYPE_SELF:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#3b5999');
default:
return '';
}
})->align('center');
$grid->column('withdraw_setting_info',
admin_trans('player_withdraw_record.player_bank'))->display(function (
$val,
PlayerWithdrawRecord $data
) {
$info = [];
switch ($data->type) {
case PlayerWithdrawRecord::TYPE_USDT:
$info[] = Html::markdown('- ' . admin_trans('channel_recharge_setting.fields.wallet_address') . ': ' . $data->wallet_address);
$info[] = Html::div()->content(Image::create()
->width(40)
->src($data->qr_code));
break;
case PlayerWithdrawRecord::TYPE_SELF:
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account_name') . ': ' . $data->account_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.bank_name') . ': ' . $data->bank_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account') . ': ' . $data->account);
break;
}
return Html::create()->content($info);
})->align('left');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function ($value, PlayerWithdrawRecord $data) {
$rejectReason = $data->reject_reason;
switch ($value) {
case PlayerWithdrawRecord::STATUS_SUCCESS:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
break;
case PlayerWithdrawRecord::STATUS_WAIT:
$tag = Tag::create(admin_trans('player_withdraw_record.status_wait'))->color('#108ee9');
break;
case PlayerWithdrawRecord::STATUS_FAIL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL))->color('#f50');
break;
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT))->color('#cd201f');
break;
case PlayerWithdrawRecord::STATUS_PENDING_PAYMENT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT))->color('#3b5999');
break;
case PlayerWithdrawRecord::STATUS_CANCEL:
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL))->color('#2db7f5');
break;
default:
$tag = '';
}
if (!empty($rejectReason)) {
return ToolTip::create(Badge::create(
$tag
)->count('!')->title(''))->title($rejectReason)->color('orange');
} else {
return $tag;
}
})->align('center')->sortable();
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->sortable()->align('center');
$grid->column('remark', admin_trans('player_withdraw_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_withdraw_record.fields.remark')])
)->width('150px')->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions, PlayerWithdrawRecord $data) {
$actions->hideDel();
$actions->hideEdit();
$dropdown = Dropdown::create(
Button::create([
admin_trans('player_withdraw_record.btn.action'), Icon::create('DownOutlined')->style(['marginRight' => '5px'])
]))->trigger(['click']);
$dropdown->item(admin_trans('player_withdraw_record.btn.view_channel_recharge_list'), 'AppstoreAddOutlined')
->modal($this->viewRechargeList($data->player_id))->width('70%');
$dropdown->item(admin_trans('player_withdraw_record.btn.examine_pass'), 'SafetyCertificateOutlined')
->confirm(admin_trans('player_withdraw_record.btn.examine_pass_confirm'), [$this, 'pass'], ['id' => $data->id])->gridRefresh();
$dropdown->item(admin_trans('player_withdraw_record.btn.examine_reject'), 'WarningFilled')
->modal([$this, 'reject'], ['id' => $data->id]);
$actions->prepend(
$dropdown
);
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.status'))
->options([
PlayerWithdrawRecord::STATUS_WAIT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_WAIT),
PlayerWithdrawRecord::STATUS_SUCCESS => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS),
PlayerWithdrawRecord::STATUS_FAIL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL),
PlayerWithdrawRecord::STATUS_PENDING_PAYMENT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT),
PlayerWithdrawRecord::STATUS_PENDING_REJECT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT),
PlayerWithdrawRecord::STATUS_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL),
PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->eq()->number('money')->precision(2)->style(['width' => '150px'])->placeholder(admin_trans('player_withdraw_record.fields.money'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('player_withdraw_record.fields.created_at'), admin_trans('player_withdraw_record.fields.created_at')]);
});
});
}
/**
* 提现打款
* @group channel
* @auth true
*/
public function paymentList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_withdraw_record.payment_title'));
$grid->bordered(true);
$grid->autoHeight();
$grid->model()->with(['player'])
->Where('status', PlayerWithdrawRecord::STATUS_PENDING_PAYMENT)
->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
}
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->align('center');
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->copy();
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->copy();
$grid->column('player.name', admin_trans('player_withdraw_record.fields.player'))->display(function ($val, PlayerWithdrawRecord $data) {
if (!empty($data->player)) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
}
return '';
})->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ( $data->currency);
})->align('center')->sortable();
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#3b5999');
})->align('center');
$grid->column('withdraw_setting_info',
admin_trans('player_withdraw_record.player_bank'))->display(function (
$val,
PlayerWithdrawRecord $data
) {
$info = [];
switch ($data->type) {
case PlayerWithdrawRecord::TYPE_USDT:
$info[] = Html::markdown('- ' . admin_trans('channel_recharge_setting.fields.wallet_address') . ': ' . $data->wallet_address);
$info[] = Html::div()->content(Image::create()
->width(40)
->src($data->qr_code));
break;
case PlayerWithdrawRecord::TYPE_SELF:
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account_name') . ': ' . $data->account_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.bank_name') . ': ' . $data->bank_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account') . ': ' . $data->account);
break;
}
return Html::create()->content($info);
})->align('left');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function () {
return Html::create()->content([
Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT))->color('#3b5999')
]);
})->sortable();
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->sortable()->align('center');
$grid->column('remark', admin_trans('player_withdraw_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->tip()->width('150px')->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions, PlayerWithdrawRecord $data) {
$actions->hideDel();
$actions->hideEdit();
$actions->prepend(
Button::create(admin_trans('player_withdraw_record.btn.complete_payment'))
->type('danger')
->modal($this->payment($data->id))
);
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->eq()->number('money')->precision(2)->style(['width' => '150px'])->placeholder(admin_trans('player_withdraw_record.fields.money'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('player_withdraw_record.fields.created_at'), admin_trans('player_withdraw_record.fields.created_at')]);
});
});
}
/**
* 提交打款凭证
* @auth true
* @group channel
* @param $id
* @return Form
*/
public function payment($id): Form
{
return Form::create(new $this->model(), function (Form $form) use ($id) {
$form->file('certificate')
->ext('jpg,png,jpeg')
->type('image')
->fileSize('2m')
->hideFinder()
->paste()
->style(['margin-left' => '35%', 'margin-bottom' => '16px'])
->help(Html::create()->content(admin_trans('player_withdraw_record.certificate_help'))->style([
'margin-left' => '135px',
'display' => 'block',
'width' => '235px'
]));
$form->saving(function (Form $form) use ($id) {
if (empty($form->input('certificate'))) {
return message_warning(admin_trans('player_withdraw_record.certificate_required'));
}
/** @var PlayerWithdrawRecord $playerWithdrawRecord */
$playerWithdrawRecord = $this->model::find($id);
if (empty($playerWithdrawRecord)) {
return message_error(admin_trans('player_withdraw_record.not_fount'));
}
switch ($playerWithdrawRecord->status) {
case PlayerWithdrawRecord::STATUS_WAIT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_not_examine'));
case PlayerWithdrawRecord::STATUS_SUCCESS:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_complete'));
case PlayerWithdrawRecord::STATUS_FAIL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_fail'));
case PlayerWithdrawRecord::STATUS_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_cancel'));
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_reject'));
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_system_cancel'));
}
if ($playerWithdrawRecord->status != PlayerWithdrawRecord::STATUS_PENDING_PAYMENT) {
return message_error(admin_trans('player_withdraw_record.withdraw_record_status_error'));
}
/** @var Channel $channel */
$channel = Channel::where('department_id', Admin::user()->department_id)->first();
if (empty($channel)) {
return message_error(admin_trans('channel.not_fount'));
}
try {
// 更新订单
$playerWithdrawRecord->certificate = $form->input('certificate');
$playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_SUCCESS;
$playerWithdrawRecord->finish_time = date('Y-m-d H:i:s');
if ($playerWithdrawRecord->save()) {
saveChannelFinancialRecord($playerWithdrawRecord, ChannelFinancialRecord::ACTION_WITHDRAW_PAYMENT);
// 更新渠道数据
$channel->withdraw_amount = bcadd($channel->withdraw_amount, $playerWithdrawRecord->coins, 2);
$channel->save();
}
} catch (\Exception $e) {
return message_error(admin_trans('player_recharge_record.action_error'));
}
return message_success(admin_trans('player_withdraw_record.action_success'));
});
});
}
/**
* 查看充值
* @group channel
* @auth true
*/
public function viewRechargeList($playerId): Grid
{
return Grid::create(new $this->rechargeModel(), function (Grid $grid) use ($playerId) {
$grid->title(admin_trans('player_recharge_record.title'));
$grid->model()->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('player_id', $playerId)->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
}
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->align('center');
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->align('center');
$grid->column('player.name', admin_trans('player_recharge_record.fields.player'))->display(function ($val, PlayerRechargeRecord $data) {
if (!empty($data->player)) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
}
return '';
})->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return $val . ' ' . ($data->currency == 'TALK' ? admin_trans('player_recharge_record.talk_currency') : $data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->align('center');
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::STATUS_WAIT:
return Tag::create(admin_trans('player_recharge_record.status.' . $val))
->color('#108ee9');
case PlayerRechargeRecord::STATUS_RECHARGING:
return Tag::create(admin_trans('player_recharge_record.status.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return Tag::create(admin_trans('player_recharge_record.status.' . $val))
->color('#87d068');
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return Tag::create(admin_trans('player_recharge_record.status.' . $val))
->color('#f50');
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status.' . $val))
->color('#2db7f5');
default:
return '';
}
})->align('center');
$grid->column('remark', admin_trans('player_recharge_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_recharge_record.fields.remark')])
)->width('150px')->align('center');
$grid->column('user_name', admin_trans('player_recharge_record.fields.user_name'))->align('center');
$grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->eq()->number('money')->precision(2)->style(['width' => '150px'])->placeholder(admin_trans('player_recharge_record.fields.money'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);
});
$grid->expandFilter();
});
}
/**
* 提现订单审核拒绝
* @auth true
* @group channel
* @param $id
* @return Form
*/
public function reject($id): Form
{
return Form::create(new $this->model(), function (Form $form) use ($id) {
$form->textarea('reject_reason')->rows(5)->required();
$form->saving(function (Form $form) use ($id) {
/** @var PlayerWithdrawRecord $playerWithdrawRecord */
$playerWithdrawRecord = $this->model::find($id);
if (empty($playerWithdrawRecord)) {
return message_error(admin_trans('player_withdraw_record.not_fount'));
}
switch ($playerWithdrawRecord->status) {
case PlayerWithdrawRecord::STATUS_SUCCESS:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_complete'));
case PlayerWithdrawRecord::STATUS_FAIL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_fail'));
case PlayerWithdrawRecord::STATUS_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_cancel'));
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_reject'));
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_system_cancel'));
case PlayerWithdrawRecord::STATUS_PENDING_PAYMENT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_pass'));
}
if ($playerWithdrawRecord->status != PlayerWithdrawRecord::STATUS_WAIT) {
return message_error(admin_trans('player_withdraw_record.withdraw_record_status_error'));
}
try {
if (withdrawBack($playerWithdrawRecord, $form->input('reject_reason'))) {
saveChannelFinancialRecord($playerWithdrawRecord, ChannelFinancialRecord::ACTION_WITHDRAW_REJECT);
}
} catch (\Exception $e) {
return message_error(admin_trans('player_withdraw_record.action_error'));
}
return message_success(admin_trans('player_withdraw_record.action_success'));
});
});
}
/**
* 提现订单审核通过
* @param $id
* @auth true
* @group channel
* @return Msg
*/
public function pass($id): Msg
{
/** @var PlayerWithdrawRecord $playerWithdrawRecord */
$playerWithdrawRecord = $this->model::find($id);
if (empty($playerWithdrawRecord)) {
return message_error(admin_trans('player_withdraw_record.not_fount'));
}
switch ($playerWithdrawRecord->status) {
case PlayerWithdrawRecord::STATUS_SUCCESS:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_complete'));
case PlayerWithdrawRecord::STATUS_FAIL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_fail'));
case PlayerWithdrawRecord::STATUS_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_cancel'));
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_reject'));
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_system_cancel'));
case PlayerWithdrawRecord::STATUS_PENDING_PAYMENT:
return message_warning(admin_trans('player_withdraw_record.withdraw_record_has_pass'));
}
if ($playerWithdrawRecord->status != PlayerWithdrawRecord::STATUS_WAIT) {
return message_error(admin_trans('player_withdraw_record.withdraw_record_status_error'));
}
try {
if ($playerWithdrawRecord->type == PlayerWithdrawRecord::TYPE_SKLPAYOUT) {
$params = [
'amount' => $playerWithdrawRecord->coins,
'bankCode' => $playerWithdrawRecord->bank_code,
'bankAccountNo' => $playerWithdrawRecord->account,
'bankAccountName' => $playerWithdrawRecord->account_name,
'orderNo' => $playerWithdrawRecord->tradeno,
];
$res = (new SklPayServices())->payout($params);
if ($res['code'] == 'success') {
// 更新订单
$playerWithdrawRecord->user_id = Admin::id() ?? 0;
$playerWithdrawRecord->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
$notice = new Notice();
$notice->department_id = $playerWithdrawRecord->player->department_id;
$notice->player_id = $playerWithdrawRecord->player_id;
$notice->source_id = $playerWithdrawRecord->id;
$notice->type = Notice::TYPE_WITHDRAW;
$notice->receiver = Notice::RECEIVER_PLAYER;
$notice->is_private = 1;
$notice->title = '下分成功';
$notice->content = '本次申请已成功处理,下分 ' . $playerWithdrawRecord->money . ' ,请查收。 ';
$notice->save();
if ($playerWithdrawRecord->save()) {
saveChannelFinancialRecord($playerWithdrawRecord, ChannelFinancialRecord::ACTION_WITHDRAW_PASS);
}
} else {
return message_error($res['message']);
}
} elseif (in_array($playerWithdrawRecord->type, [PlayerWithdrawRecord::TYPE_SELF, PlayerWithdrawRecord::TYPE_USDT])) {
$playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_PENDING_PAYMENT;
$playerWithdrawRecord->user_id = Admin::id() ?? 0;
$playerWithdrawRecord->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
if ($playerWithdrawRecord->save()) {
saveChannelFinancialRecord($playerWithdrawRecord, ChannelFinancialRecord::ACTION_WITHDRAW_PASS);
}
}
} catch (\Exception $e) {
return message_error(admin_trans('player_withdraw_record.action_error'));
}
return message_success(admin_trans('player_withdraw_record.action_success'));
}
/**
* 提现
* @group channel
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_withdraw_record.payment_title'));
$grid->model()->with(['player'])->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
if (!empty($exAdminFilter['player']['uuid'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('uuid', 'like', '%' . $exAdminFilter['player']['uuid'] . '%');
});
}
if (!empty($exAdminFilter['player']['name'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('name', 'like', '%' . $exAdminFilter['player']['name'] . '%');
});
}
if (!empty($exAdminFilter['type'])) {
$grid->model()->where('type', $exAdminFilter['type']);
}
if (!empty($exAdminFilter['status'])) {
$grid->model()->where('status', $exAdminFilter['status']);
}
if (!empty($exAdminFilter['tradeno'])) {
$grid->model()->where('tradeno', $exAdminFilter['tradeno']);
}
}
$query = clone $grid->model();
$totalData = $query->selectRaw(
'ifNull(sum(money), 0) as total_money,
ifNull(sum(IF(type = 6, money,0)), 0) as total_skl_money'
)->first();
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_withdraw_record.total_money'))
->value($totalData['total_money'])
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_withdraw_record.total_inmoney'))
->value(bcadd(bcsub($totalData['total_money'], $totalData['total_skl_money'], 3), bcmul($totalData['total_skl_money'], 1.008, 3), 3))
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
})->style(['background' => '#fff']);
$grid->header($layout);
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->align('center')->fixed(true);
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->copy()->fixed(true);
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->copy()->fixed(true);
$grid->column('player.name', admin_trans('player_withdraw_record.fields.player'))->display(function ($val, PlayerWithdrawRecord $data) {
if (!empty($data->player)) {
$image = isset($data->player->avatar) && !empty($data->player->avatar) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
}
return '';
})->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->align('center')->sortable();
$grid->column('inmoney', admin_trans('player_recharge_record.fields.inmoney'))->display(function ($val, PlayerWithdrawRecord $data) {
if ($data->type == PlayerWithdrawRecord::TYPE_ESPAYOUT) {
$ratio = 1.005;
} elseif ($data->type == PlayerWithdrawRecord::TYPE_ONEPAYOUT){
$ratio = 1.008;
} elseif ($data->type == PlayerWithdrawRecord::TYPE_SKLPAYOUT){
$ratio = 1.008;
} else {
$ratio = 1;
}
if ($data->currency == 'USDT') {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
}
return $data->money * $ratio . ' ' . ($data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerWithdrawRecord::TYPE_SELF:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#3b5999');
case PlayerWithdrawRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#cd201f');
case PlayerWithdrawRecord::TYPE_USDT:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#2db7f5');
case PlayerWithdrawRecord::TYPE_SKLPAYOUT:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#108ee9');
default:
return '';
}
})->align('center');
$grid->column('withdraw_setting_info',
admin_trans('player_withdraw_record.player_bank'))->display(function (
$val,
PlayerWithdrawRecord $data
) {
$info = [];
switch ($data->type) {
case PlayerWithdrawRecord::TYPE_USDT:
$info[] = Html::markdown('- ' . admin_trans('channel_recharge_setting.fields.wallet_address') . ': ' . $data->wallet_address);
$info[] = Html::div()->content(Image::create()
->width(40)
->src($data->qr_code));
break;
case PlayerWithdrawRecord::TYPE_SELF:
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account_name') . ': ' . $data->account_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.bank_name') . ': ' . $data->bank_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account') . ': ' . $data->account);
break;
}
return Html::create()->content($info);
})->align('left');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function ($value, PlayerWithdrawRecord $data) {
$rejectReason = $data->reject_reason;
switch ($value) {
case PlayerWithdrawRecord::STATUS_SUCCESS:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
break;
case PlayerWithdrawRecord::STATUS_WAIT:
$tag = Tag::create(admin_trans('player_withdraw_record.status_wait'))->color('#108ee9');
break;
case PlayerWithdrawRecord::STATUS_FAIL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL))->color('#f50');
break;
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT))->color('#cd201f');
break;
case PlayerWithdrawRecord::STATUS_PENDING_PAYMENT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT))->color('#3b5999');
break;
case PlayerWithdrawRecord::STATUS_CANCEL:
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL))->color('#2db7f5');
break;
default:
$tag = '';
}
if (!empty($rejectReason)) {
return ToolTip::create(Badge::create(
$tag
)->count('!')->title(''))->title($rejectReason)->color('orange');
} else {
return $tag;
}
})->align('center')->sortable();
$grid->column('finish_time', admin_trans('player_withdraw_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->sortable()->align('center');
$grid->column('remark', admin_trans('player_withdraw_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->tip()->width('150px')->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.status'))
->options([
PlayerWithdrawRecord::STATUS_WAIT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_WAIT),
PlayerWithdrawRecord::STATUS_SUCCESS => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS),
PlayerWithdrawRecord::STATUS_FAIL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL),
PlayerWithdrawRecord::STATUS_PENDING_PAYMENT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT),
PlayerWithdrawRecord::STATUS_PENDING_REJECT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT),
PlayerWithdrawRecord::STATUS_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL),
PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL),
]);
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.type'))
->options([
PlayerWithdrawRecord::TYPE_ESPAYOUT => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_ESPAYOUT),
PlayerWithdrawRecord::TYPE_ONEPAYOUT => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_ONEPAYOUT),
PlayerWithdrawRecord::TYPE_SKLPAYOUT => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_SKLPAYOUT),
PlayerWithdrawRecord::TYPE_ARTIFICIAL => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_ARTIFICIAL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('player_withdraw_record.fields.created_at'), admin_trans('player_withdraw_record.fields.created_at')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_withdraw_record.fields.finish_time'), admin_trans('player_withdraw_record.fields.finish_time')]);
});
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace addons\webman\controller;
use addons\webman\form\Driver\Config;
use ExAdmin\ui\component\form\Form;
/**
* 配置管理
*/
class ConfigController
{
/**
* 系统配置
* @auth true
* @return Form
*/
public function form(): Form
{
return Form::create(new Config(), function (Form $form) {
$form->title(admin_trans('config.title'));
$form->layout('vertical');
$form->image('web_logo', admin_trans('config.logo'))->size(80, 80);
$form->text('web_name', admin_trans('config.name'));
$form->text('web_miitbeian', admin_trans('config.miitbeian'));
$form->text('web_copyright', admin_trans('config.copyright'));
});
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Currency;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Arr;
/**
* 货币管理
*/
class CurrencyController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.currency_model');
}
/**
* 货币
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('currency.title'));
$grid->bordered();
$grid->autoHeight();
$grid->column('id', admin_trans('currency.fields.id'))->align('center');
$grid->column('name', admin_trans('currency.fields.name'))->display(function ($val, Currency $data) {
return admin_trans('currency.currency_name' . '.' . $data->identifying);
})->align('center');
$grid->column('identifying', admin_trans('currency.fields.identifying'))->align('center');
$grid->column('ratio', admin_trans('currency.fields.ratio'))->display(function ($val) {
return floatval($val);
})->append(' ' . admin_trans('currency.game_coins'))->align('center');
$grid->column('status', admin_trans('currency.fields.status'))->switch([[1 => ''], [0 => '']])->align('center');;
$grid->column('admin_user.username', admin_trans('admin.fields.username'))->align('center');
$grid->column('created_at', admin_trans('currency.fields.create_at'))->align('center');
$grid->setForm()->modal($this->form());
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
});
});
}
/**
* 货币
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$disabledValue = Arr::pluck($this->model::select('identifying')->get()->toArray(), 'identifying');
$form->title(admin_trans('currency.title'));
$form->select('identifying', admin_trans('currency.fields.identifying'))
->disabled($form->isEdit())
->options(plugin()->webman->config('currency'))
->disabledValue($disabledValue)
->required();
$form->number('ratio', admin_trans('currency.fields.ratio') . '=')
->min(0)
->max(1000000)
->precision(4)
->required()
->style(['width' => '100%'])
->addonAfter(admin_trans('currency.game_coins'));
$form->input('admin_id', Admin::id());
$form->saving(function (Form $form) {
if (!$form->isEdit()) {
$identifying = $form->input('identifying');
if ($this->model::where('identifying', $identifying)->first()) {
return message_error(admin_trans('currency.currency_has_exists'));
}
}
});
});
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\AdminDepartment;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Request;
/**
* 部门管理
*/
class DepartmentController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.department_model');
}
/**
* 部门
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('department.title'));
$grid->model()->where('type', AdminDepartment::TYPE_DEPARTMENT);
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
}
$grid->autoHeight();
$grid->tree();
$grid->column('name', admin_trans('department.fields.name'));
$grid->column('leader', admin_trans('department.fields.leader'));
$grid->column('mobile', admin_trans('department.fields.mobile'));
$grid->column('status', admin_trans('department.fields.status'))->switch([[1=>''],[0=>'']]);
$grid->sortInput('sort', admin_trans('department.fields.sort'));
$grid->column('created_at', admin_trans('department.fields.create_at'));
$grid->filter(function (Filter $filter) {
$filter->like()->text('name')->placeholder(admin_trans('department.fields.name'));
$filter->like()->text('leader')->placeholder(admin_trans('department.fields.leader'));
$filter->like()->text('mobile')->placeholder(admin_trans('department.fields.mobile'));
$filter->eq()->select('status')->placeholder(admin_trans('department.fields.status'))->options([
1 => admin_trans('department.normal'),
0 => admin_trans('department.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->setForm()->modal($this->form());
});
}
/**
* 部门
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('department.title'));
$form->treeSelect('pid', admin_trans('department.fields.pid'))
->options($this->model::where('type', AdminDepartment::TYPE_DEPARTMENT)->get()->toArray());
$form->text('name', admin_trans('department.fields.name'))
->required();
$form->text('leader', admin_trans('department.fields.leader'));
$form->text('mobile', admin_trans('department.fields.mobile'))
->ruleMobile();
$form->number('sort', admin_trans('department.fields.sort'))->default(0);
$form->saving(function (Form $form) {
if ($form->isEdit() && $form->input('id') == $form->input('pid')) {
return message_error(admin_trans('department.parent_id_repeat'));
}
});
$form->saved(function (Form $form) {
$path = $this->model::where('id',$form->input('pid'))->value('path');
$paths = explode(',',$path);
$paths= array_filter($paths);
$model = $form->driver()->model();
$paths[] = $model->id;
$model->path = implode(',',$paths);
$model->save();
});
});
}
}

View File

@@ -0,0 +1,376 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\Game;
use addons\webman\model\GamePlatform;
use addons\webman\model\Player;
use addons\webman\model\Prize;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Notification;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Request;
use support\Db;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Actions;
use addons\webman\model\GameType;
use Tinywan\Jwt\JwtToken;
/**
* 游戏平台
* @group channel
*/
class GameController
{
protected $model;
protected $game;
public function __construct()
{
$this->game = plugin()->webman->config('database.game_model');
$this->prize = plugin()->webman->config('database.prize_model');
}
/**
* 游戏列表
* @auth true
* @return Grid
*/
public function index(): Grid
{
return Grid::create(new $this->game(), function (Grid $grid) {
$grid->title(admin_trans('game.title'));
if (plugin()->webman->config('admin_auth_id') != Admin::id()){
$grid->model()->where('status', 1);
}
$grid->model()->orderBy('status', 'desc')->orderBy('id', 'asc');
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('game.fields.id'))->align('center');
$grid->column('logo', 'LOGO')->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->style(['border-radius' => '50%', 'objectFit' => 'cover'])
->src($data['logo']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('name', admin_trans('game.fields.name'))->align('center');
$grid->column('game_image', admin_trans('game.fields.game_image'))->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->style(['border-radius' => '50%', 'objectFit' => 'cover'])
->src($data['game_image']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('consume', admin_trans('game.fields.consume'))->align('center');
$grid->column('prize_num', admin_trans('game.fields.prize_num'))->align('center');
$grid->column('description', admin_trans('game.fields.description'))->align('center');
$grid->column('game_url', admin_trans('game.fields.game_url'))->align('center');
if (plugin()->webman->config('admin_auth_id') != Admin::id()){
$grid->column('status', admin_trans('game_platform.fields.status'))->switch()->align('center');
}
$grid->column('updated_at', admin_trans('game.fields.updated_at'))->align('center');
$grid->expandFilter();
$grid->setForm()->drawer($this->form());
$grid->actions(function (Actions $actions, $data) {
$actions->hideDel();
$actions->prepend(
Button::create(admin_trans('game.enter_game'))->ajax([$this, 'enterGame'],
['id' => $data['id']])
);
$actions->prepend(
Button::create(admin_trans('game.view_prize'))->modal([$this, 'getPrizeList'],
['id' => $data['id']])->width('100%')
);
})->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->hideAdd();
$grid->hideTrashed();
});
}
/**
* 进入游戏
* @param $id
* @auth true
* @return Notification
*/
public function enterGame($id): Notification
{
$game = Game::query()->where('id', $id)->first();
$url = $game->test_url;
return notification_success(admin_trans('admin.success'),
admin_trans('game_platform.action_success'))->redirect($url);
}
/**
* 游戏详情
* @auth true
* @return Form
*/
public function form(): Form
{
return Form::create(new $this->game(), function (Form $form) {
$form->title(admin_trans('prize.title'));
$form->text('name', admin_trans('game.fields.name'))->required()->maxlength(50);
$form->image('logo', admin_trans('game.fields.logo'))->required();
$form->image('game_image', admin_trans('game.fields.game_image'))->required();
$form->number('consume', admin_trans('game.fields.consume'))->required();
$form->number('prize_num', admin_trans('game.fields.prize_num'))->required();
$form->textarea('description', admin_trans('game.fields.description'))->maxlength(500)->bindAttr('rows', 10);
$form->text('game_url', admin_trans('game.fields.game_url'))->required()->maxlength(500);
$form->switch('status', admin_trans('game_platform.fields.status'))->required()->span(11);
$form->layout('vertical');
});
}
/**
* 查看奖品
* @param $id
* @return Grid
* @auth true
*/
public function getPrizeList($id): Grid
{
return Grid::create(new $this->prize(), function (Grid $grid) use($id) {
$grid->title(admin_trans('prize.title'));
$grid->model()->where('game_id', $id)->orderBy('probability');
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('prize.fields.id'))->align('center')->width('5%');
$grid->column('name', admin_trans('prize.fields.name'))->align('center')->width('10%');
$grid->column('pic', admin_trans('prize.fields.pic'))->display(function ($val, $data) {
$image = Image::create()
->width(50)
->height(50)
->src($data['pic']);
return Html::create()->content([
$image,
]);
})->align('center');
$grid->column('probability', admin_trans('prize.fields.probability'))->align('center')->width('10%');
$grid->column('total_stock', admin_trans('prize.fields.total_stock'))->align('center')->width('8%');
$grid->column('daily_stock', admin_trans('prize.fields.daily_stock'))->align('center')->width('8%');
$grid->column('total_remaining', admin_trans('prize.fields.total_remaining'))->align('center')->width('8%');
$grid->column('daily_remaining', admin_trans('prize.fields.daily_remaining'))->align('center')->width('8%');
$grid->column('description', admin_trans('prize.fields.description'))->align('center')->width('20%');
if (plugin()->webman->config('admin_auth_id') != Admin::id()) {
$grid->column('status', admin_trans('prize.fields.status'))->switch()->align('center')->width('8%');
}
$grid->column('admin_name', admin_trans('prize.fields.admin_name'))->align('center')->width('8%');
$grid->column('updated_at', admin_trans('prize.fields.updated_at'))->align('center')->width('8%');
$grid->expandFilter();
$grid->setForm()->drawer($this->editPrize($id));
$grid->actions(function (Actions $actions, $data) {
$actions->hideDel();
$actions->hideEdit();
$actions->prepend(
Button::create(admin_trans('prize.replenish_daily_stock'))->ajax([$this, 'replenishDailyStock'],
['id' => $data['id']])
);
})->align('center');
$grid->hideDelete();
$grid->hideAdd();
$grid->hideSelection();
$grid->hideTrashed();
});
}
/**
* 补充每日库存
* @param $id
* @auth true
* @return Msg
*/
public function replenishDailyStock($id): Msg
{
/** @var Prize $prize */
$prize = Prize::query()->where('id', $id)->first();
if ($prize->daily_remaining < $prize->daily_stock) {
$diff = $prize->daily_stock - $prize->daily_remaining;
$prize->daily_remaining = $prize->daily_stock;
$prize->total_remaining = $prize->total_remaining + $diff;
$prize->total_stock = $prize->total_stock + $diff;
}
$prize->save();
return message_success(admin_trans('prize.action_success'));
}
/**
* 奖品详情
* @auth true
* @param $gameId
* @return Form
*/
public function editPrize($gameId): Form
{
return Form::create(new $this->prize(), function (Form $form) use ($gameId) {
$form->title(admin_trans('prize.title'));
$form->text('name', admin_trans('prize.fields.name'))->required()->maxlength(50);
$form->image('pic', admin_trans('prize.fields.pic'));
$form->hidden('game_id')->default($gameId);
$form->number('probability', admin_trans('prize.fields.probability'))->min(1)->max(999)->required();
$form->number('total_stock', admin_trans('prize.fields.total_stock'))->min(1)->max(100000)->required();
$form->number('daily_stock', admin_trans('prize.fields.daily_stock'))->min(1)->max(100000)
->help(admin_trans('prize.daily_stock_help'))->required();
$form->textarea('description', admin_trans('prize.fields.description'))->maxlength(500)->bindAttr('rows', 10);
$form->switch('status', admin_trans('prize.fields.status'))->default(true)->required()->span(11);
$form->layout('vertical');
$form->saving(function (Form $form) {
try {
if (!$form->isEdit()) {
$prize = new Prize();
$prize->game_id = $form->input('game_id');
$prize->total_remaining = $form->input('total_stock');
$prize->daily_remaining = $form->input('daily_stock');
} else {
$prizeId = $form->driver()->get('id');
$prize = Prize::query()->find($prizeId);
}
$prize->name = $form->input('name');
$prize->pic = $form->input('pic');
$prize->probability = $form->input('probability');
$prize->total_stock = $form->input('total_stock');
$prize->daily_stock = $form->input('daily_stock');
if ($prize->daily_stock > $prize->total_stock) {
return message_error(admin_trans('prize.daily_stock_help'));
}
$prize->description = $form->input('description');
$prize->status = $form->input('status');
$prize->admin_id = Admin::id();
$prize->admin_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : trans('system_automatic', [], 'message');
$prize->save();
} catch (\Exception $e) {
return message_error(admin_trans('form.save_fail'));
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* 筛选游戏平台
* @return mixed
*/
public function getGamePlatformOptions()
{
$request = Request::input();
$gamePlatform = GamePlatform::query()->orderBy('created_at', 'desc');
if (!empty($request['search'])) {
$gamePlatform->where('name', 'like', '%' . $request['search'] . '%');
}
$channelList = $gamePlatform->get();
$data = [];
/** @var GamePlatform $gamePlatform */
foreach ($channelList as $gamePlatform) {
$data[] = [
'value' => $gamePlatform->id,
'label' => $gamePlatform->name,
];
}
return Response::success($data);
}
/**
* 游戏类型列表
* @auth true
*/
public function serviceList(): Grid
{
return Grid::create(new GameType(), function (Grid $grid) {
$grid->title(admin_trans('game_type.title'));
$grid->autoHeight();
$grid->bordered(true);
$grid->column('game_type', admin_trans('game_type.fields.game_type'))->display(function ($val) {
return $val ? admin_trans('game_type.game_type.' . $val) : admin_trans('game_type.nu_set');
})->align('center');
$grid->column('ratio', admin_trans('game_type.fields.ratio'))->display(function ($value) {
return $value . '%';
})->editable(
(new Editable)->number('ratio')
->min(1)
->max(100)
->addonAfter('%')
)->align('center')->ellipsis(true);
$grid->column('updated_at', admin_trans('game_type.fields.updated_at'))->align('center')->display(function ($val) {
return $val ? date('Y-m-d H:i:s', strtotime($val)) : '';
})->ellipsis(true);
$grid->actions(function (Action $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->hideDelete();
$grid->hideSelection();
$grid->hideAdd();
});
}
/**
* 游戏类型
* @auth true
*/
public function serviceForm(): Form
{
return Form::create(new GamePlatform, function (Form $form) {
$form->title(admin_trans('game_platform.game_platform'));
$form->text('name', admin_trans('game_platform.fields.name'));
$form->text('title', admin_trans('game_platform.fields.title'));
$form->number('service_ratio', admin_trans('game_platform.fields.service_ratio'))->addonAfter('%');
$form->layout('vertical');
$form->saving(function (Form $form) {
if (!$form->isEdit()) {
return message_error(admin_trans('game_platform.save_error'));
DB::beginTransaction();
try {
$gamePlatform = new GamePlatform();
$gamePlatform->name = $form->input('name');
$gamePlatform->title = $form->input('title');
$gamePlatform->service_ratio = $form->input('service_ratio');
$gamePlatform->status = 1;
$gamePlatform->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('game_platform.save_success'));
} else {
$gamePlatform = GamePlatform::find($form->input('id'));
if (empty($gamePlatform)) {
return message_error(admin_trans('game_platform.not_fount'));
}
DB::beginTransaction();
try {
$gamePlatform->name = $form->input('name');
$gamePlatform->title = $form->input('title');
$gamePlatform->service_ratio = $form->input('service_ratio');
$gamePlatform->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('game_platform.save_success'));
}
});
});
}
}

View File

@@ -0,0 +1,313 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\Player;
use addons\webman\model\PlayerLoginRecord;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\echart\BarChart;
use ExAdmin\ui\component\echart\LineChart;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\layout\Divider;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\response\Msg;
use Illuminate\Support\Carbon;
use support\Db;
use support\Response;
/**
* 数据中心
*/
class IndexController
{
/**
* 数据中心
* @auth true
*/
public function index(): Layout
{
$rechargeData = $this->rechargeData();
$withdrawData = $this->withdrawData();
$playerData = $this->playerData();
$loginData = $this->loginData();
$layout = Layout::create();
$layout->row(function (Row $row) use ($rechargeData, $withdrawData, $playerData, $loginData) {
$row->gutter([10, 10]);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-money-bill')->style(['fontSize' => '45px', 'color' => '#409eff', 'marginRight' => '20px']), 4),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.recharge_all'))->value(floatval($rechargeData['all']))->style(['fontSize' => '45px', 'text-align' => 'center']), 6),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.recharge_activity'))->value(floatval($rechargeData['activity']))->style(['fontSize' => '45px', 'text-align' => 'center']), 6),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.recharge_regular'))->value(floatval($rechargeData['regular']))->style(['fontSize' => '45px', 'text-align' => 'center']), 6),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-RechargeRecordController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-money-bill-alt')->style(['fontSize' => '45px', 'color' => '#ff9800', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.withdraw_all'))
->value(floatval($withdrawData['all']))->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.withdraw_self'))
->value(floatval($withdrawData['self']))->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-WithdrawRecordController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-user')->style(['fontSize' => '45px', 'color' => '#409eff', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.today_add_player'))
->value($playerData['today'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.player_all'))
->value($playerData['all'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8),
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()->extra(Icon::create('MoreOutlined')
->redirect('ex-admin/addons-webman-controller-PlayerController/index'))
->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 12);
$row->column(
Card::create([
Row::create()->column(Icon::create('fas fa-user')->style(['fontSize' => '45px', 'color' => '#e91e63', 'marginRight' => '20px']), 6),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.today_active_player'))
->value($loginData['today'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8)
->redirect('ex-admin/addons-webman-controller-PlayerController/index',['active_player' => 1]),
Divider::create()->type('vertical')->style(['height' => '4.9em']),
Row::create()->column(Statistic::create()->title(admin_trans('data_center.mouth_active_player'))
->value($loginData['month'])->style(['fontSize' => '45px', 'text-align' => 'center']), 8)
->redirect('ex-admin/addons-webman-controller-PlayerController/index',['active_player' => 2])
])->bodyStyle(['display' => 'flex', 'align-items' => 'center'])->hoverable()
, 12);
$row->column(Card::create($this->rechargeChart())->hoverable(), 24);
$row->column(Card::create($this->withdrawChart())->hoverable(), 12);
$row->column(Card::create($this->playerChart())->hoverable(), 12);
});
return $layout;
}
/**
* 获取活跃玩家数据
* @return array
*/
public function loginData(): array
{
return [
'month' => PlayerLoginRecord::whereYear('created_at', date('Y'))->whereMonth('created_at', date('m'))->distinct('player_id')->count(),
'today' => PlayerLoginRecord::whereDate('created_at', date('Y-m-d'))->distinct('player_id')->count(),
];
}
/**
* 获取玩家数据
* @return array
*/
public function playerData(): array
{
return [
'all' => Player::count('*'),
'today' => Player::whereDate('created_at', date('Y-m-d'))->count(),
];
}
/**
* 获取充值数据
* @return array
*/
public function rechargeData(): array
{
return [
'all' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ACTIVITY, PlayerRechargeRecord::TYPE_ARTIFICIAL])->sum('coins'),
'activity' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('type', PlayerRechargeRecord::TYPE_ACTIVITY)->sum('coins'),
'regular' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('type', PlayerRechargeRecord::TYPE_REGULAR)->sum('coins'),
'artificial' => PlayerRechargeRecord::where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->where('type', PlayerRechargeRecord::TYPE_ARTIFICIAL)->sum('coins'),
];
}
/**
* 获取提现数据
* @return array
*/
public function withdrawData(): array
{
return [
'all' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->sum('coins'),
'self' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->where('type', PlayerWithdrawRecord::TYPE_SELF)->sum('coins'),
'artificial' => PlayerWithdrawRecord::where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->where('type', PlayerWithdrawRecord::TYPE_ARTIFICIAL)->sum('coins'),
];
}
/**
* 充值趋势图
* @return LineChart
*/
public function rechargeChart(): LineChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = PlayerRechargeRecord::whereDate('created_at', '>=', $range)
->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)
->whereIn('type', [PlayerRechargeRecord::TYPE_REGULAR, PlayerRechargeRecord::TYPE_ACTIVITY, PlayerRechargeRecord::TYPE_ARTIFICIAL])
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('SUM(`coins`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return LineChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.recharge_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.recharge_amount'), $yAxis);
}
/**
* 提现趋势图
* @return LineChart
*/
public function withdrawChart(): LineChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = PlayerWithdrawRecord::whereDate('created_at', '>=', $range)
->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('SUM(`coins`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return LineChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.withdraw_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.withdraw_amount'), $yAxis);
}
/**
* 上传
* @return Response|void
*/
public function myEditorUpload()
{
$file = request()->file('file');
if ($file && $file->isValid()) {
$size = $file->getSize();
if ($file->getSize() >= 1024 * 1024) {
return jsonFailResponse(trans('image_upload_size_fail', ['{size}' => '1M'], 'message'));
}
$extension = $file->getUploadExtension();
if (!in_array($extension, ['png', 'jpg', 'jpeg'])) {
return jsonFailResponse(trans('image_upload_size_fail', ['{size}' => '1M'], 'message'));
}
$uploadName = $file->getUploadName();
$basePath = public_path() . '/storage/' . date('Ymd') . DIRECTORY_SEPARATOR;
$baseUrl = env('APP_URL', 'http://127.0.0.1:8787') . '/storage/' . date('Ymd') . '/';
$uniqueId = hash_file('md5', $file->getPathname());
$saveFilename = $uniqueId . '.' . $file->getUploadExtension();
$savePath = $basePath . $saveFilename;
$file->move($savePath);
return jsonSuccessResponse('success', [
'origin_name' => $uploadName,
'save_name' => $saveFilename,
'save_path' => $savePath,
'url' => $baseUrl . $saveFilename,
'unique_id' => $uniqueId,
'size' => $size,
'mime_type' => $file->getUploadMimeType(),
'extension' => $extension,
]);
}
}
/**
* 新增玩家
* @return BarChart
*/
public function playerChart(): BarChart
{
$range = Carbon::now()->subDays(15)->format('Y-m-d');
$data = Player::whereDate('created_at', '>=', $range)
->groupBy('date')
->orderBy('date', 'DESC')
->get([
DB::raw('Date(`created_at`) as date'),
DB::raw('COUNT(`id`) as value')
])
->toArray();
$data = $data ? array_column($data, 'value', 'date') : [];
$xAxis = [];
$yAxis = [];
for ($i = 14; $i >= 0; $i--) {
$date = Carbon::now()->subDays($i)->format('Y-m-d');
$xAxis[] = $date;
$yAxis[] = $data[$date] ?? 0;
}
return BarChart::create()
->height('280px')
->hideDateFilter()
->header(Html::create(admin_trans('data_center.player_chart'))->tag('h2')->style(['text-align' => 'center']))
->xAxis($xAxis)
->data(admin_trans('data_center.player_amount'), $yAxis);
}
/**
* 活動圖片上傳
* @return Msg|Response
*/
public function activityUpload()
{
$file = request()->file('file');
if ($file && $file->isValid()) {
if ($file->getSize() >= 1024 * 1024 * 5) {
return message_error(trans('image_upload_size_fail', ['{size}' => '5M'], 'message'));
}
$extension = $file->getUploadExtension();
if (!in_array($extension, ['png', 'jpg', 'jpeg'])) {
return message_error(trans('image_upload_fail', [], 'message'));
}
$basePath = public_path() . '/storage/' . date('Ymd') . DIRECTORY_SEPARATOR;
$baseUrl = env('APP_URL', 'http://127.0.0.1:8787') . '/storage/' . date('Ymd') . '/';
$uniqueId = hash_file('md5', $file->getPathname());
$saveFilename = $uniqueId . '.' . $file->getUploadExtension();
$savePath = $basePath . $saveFilename;
$file->move($savePath);
return jsonSuccessResponse('success', [$baseUrl . $saveFilename]);
} else {
return message_error(trans('image_upload_fail', [], 'message'));
}
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminDepartment;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\support\Arr;
/**
* 菜单管理
*/
class MenuController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.menu_model');
}
/**
* 系统菜单
* @auth true
* @return Card
*/
public function index(): Card
{
return Card::create(Tabs::create()
->destroyInactiveTabPane()
->pane(admin_trans('menu.type.' . AdminDepartment::TYPE_DEPARTMENT), $this->menuList())
->pane(admin_trans('menu.type.' . AdminDepartment::TYPE_CHANNEL), $this->menuList(AdminDepartment::TYPE_CHANNEL))
->type('card')
);
}
/**
* 系统菜单
* @param int $type 菜单类型
* @return Grid
*/
public function menuList(int $type = AdminDepartment::TYPE_DEPARTMENT):Grid
{
return Grid::create(new $this->model(),function (Grid $grid) use($type){
$grid->title(admin_trans('menu.title'));
$grid->model()->where('type', $type)->orderBy('sort');
$grid->autoHeight();
$grid->tree();
$grid->column('name', admin_trans('menu.fields.name'))->display(function ($value, $data) {
return Html::create([
Icon::create($data['icon']),
' ',
$value
]);
});
$grid->column('url', admin_trans('menu.fields.url'))->display(function ($value) {
if (empty($value) || $value == '#') {
return $value;
}
return Html::create($value)->tag('a')->redirect($value);
});
$grid->column('status', admin_trans('menu.fields.status'))->switch();
$grid->column('open', admin_trans('menu.fields.open'))->switch();
$grid->sortInput();
$grid->quickSearch();
$grid->setForm()->modal($this->form());
$grid->updated(function (){
return message_success(admin_trans('grid.update_success'))->refreshMenu();
});
$grid->deleted(function (){
return message_success(admin_trans('grid.update_success'))->refreshMenu();
});
});
}
/**
* 系统菜单
* @auth true
* @param int $pid
* @return Form
*/
public function form(int $pid = 0): Form
{
return Form::create(new $this->model,function (Form $form) use($pid){
$form->title(admin_trans('menu.title'));
$form->text('name', admin_trans('menu.fields.name'))->required();
$form->radio('type', admin_trans('menu.fields.type'))
->default(AdminDepartment::TYPE_DEPARTMENT)
->disabled($form->isEdit())
->options([
AdminDepartment::TYPE_DEPARTMENT => admin_trans('menu.type.' . AdminDepartment::TYPE_DEPARTMENT),
AdminDepartment::TYPE_CHANNEL => admin_trans('menu.type.' . AdminDepartment::TYPE_CHANNEL)
])->when('==', AdminDepartment::TYPE_DEPARTMENT, function (Form $form) use($pid){
$menus = $this->model::where('type', AdminDepartment::TYPE_DEPARTMENT)->get()->toArray();
array_unshift($menus, ['id' => 0, 'name' => admin_trans('menu.fields.top'), 'pid' => -1]);
$form->treeSelect('pid', admin_trans('menu.fields.pid'))
->default($pid)
->options($menus)
->required();
})->when('==', AdminDepartment::TYPE_CHANNEL, function (Form $form) use($pid){
$menus = $this->model::where('type', AdminDepartment::TYPE_CHANNEL)->get()->toArray();
array_unshift($menus, ['id' => 0, 'name' => admin_trans('menu.fields.top'), 'pid' => -1]);
$form->treeSelect('pid', admin_trans('menu.fields.pid'))
->default($pid)
->options($menus)
->required();
});
$form->autoComplete('url', admin_trans('menu.fields.url'))
->groupOptions(Arr::tree(Admin::node()->all()),'children','title','url');
$form->icon('icon', admin_trans('menu.fields.icon'))
->default('far fa-circle')
->required();
$form->number('sort', admin_trans('menu.fields.sort'))
->default($this->model::where('pid', $pid)->max('sort') + 1);
$form->saved(function(){
return message_success(admin_trans('form.save_success'))->refreshMenu();
});
});
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\DrawRecord;
use addons\webman\model\Game;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Request;
/**
* 游戏游玩记录
*/
class PlayGameRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.draw_records_model');
}
/**
* 玩家游戏记录
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('play_game_record.title'));
$grid->model()->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->bordered(true);
$grid->hideAction();
$grid->hideDelete();
$grid->hideDeleteSelection();
$grid->hideSelection();
$grid->column('id', admin_trans('play_game_record.fields.id'))->fixed(true)->align('center');
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, DrawRecord $data) {
$image = !empty($data->player->avatar) ? Avatar::create()->src(is_numeric($data->player->avatar) ? config('def_avatar.' . $data->player->avatar) : $data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val),
]);
})->fixed(true)->align('center');
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('game_type', admin_trans('game.fields.game_type'))->display(function ($val) {
return $val ? admin_trans('game.game_type.' . $val) : admin_trans('game.nu_set');
})->align('center');
$grid->column('prize_name', admin_trans('prize.fields.name'))->align('center');
$grid->column('prize_type', admin_trans('prize.fields.type'))->display(function ($val) {
return $val ? admin_trans('prize.prize_type.' . $val) : admin_trans('prize.nu_set');
})->align('center');
$grid->column('created_at', admin_trans('play_game_record.fields.create_at'))->align('center');
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('game_type')
->placeholder(admin_trans('play_game_record.fields.game_type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
Game::GAME_TYPE_EGG => admin_trans('game.game_type.' . Game::GAME_TYPE_EGG),
Game::GAME_TYPE_TURNTABLE => admin_trans('game.game_type.' . Game::GAME_TYPE_TURNTABLE),
Game::GAME_TYPE_BLINDBOX => admin_trans('game.game_type.' . Game::GAME_TYPE_BLINDBOX),
Game::GAME_TYPE_TICKET => admin_trans('game.game_type.' . Game::GAME_TYPE_TICKET),
Game::GAME_TYPE_LOTTERY => admin_trans('game.game_type.' . Game::GAME_TYPE_LOTTERY),
Game::GAME_TYPE_DICE => admin_trans('game.game_type.' . Game::GAME_TYPE_DICE),
]);
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('channel.fields.department_name'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->quickSearch();
});
}
}

View File

@@ -0,0 +1,1355 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\PhoneSmsLog;
use addons\webman\model\Player;
use addons\webman\model\PlayerBank;
use addons\webman\model\PlayerChipRecord;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerExtend;
use addons\webman\model\PlayerLevel;
use addons\webman\model\PlayerMoneyEditLog;
use addons\webman\model\PlayerPlatformCash;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerRegisterRecord;
use addons\webman\model\PlayerTag;
use addons\webman\model\PlayerWalletTransfer;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Button;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\response\Msg;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
use support\Cache;
use support\Db;
/**
* 玩家
*/
class PlayerController
{
protected $model;
protected $playerTag;
private $withdraw;
private $recharge;
private $playerChipRecord;
protected $playerDeliveryRecord;
protected $playerLevel;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_model');
$this->playerTag = plugin()->webman->config('database.player_tag_model');
$this->withdraw = plugin()->webman->config('database.player_withdraw_record_model');
$this->recharge = plugin()->webman->config('database.player_recharge_record_model');
$this->playerChipRecord = plugin()->webman->config('database.player_chip_record_model');
$this->playerDeliveryRecord = plugin()->webman->config('database.player_delivery_record_model');
$this->playerLevel = plugin()->webman->config('database.player_level_model');
}
/**
* 玩家
* @auth true
* @return Grid
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player.title'));
$requestFilter = Request::input('ex_admin_filter', []);
if (!empty($requestFilter)) {
if (isset($requestFilter['created_at_start']) && !empty($requestFilter['created_at_start'])) {
$grid->model()->where('player.created_at', '>=', $requestFilter['created_at_start']);
}
if (isset($requestFilter['created_at_end']) && !empty($requestFilter['created_at_end'])) {
$grid->model()->where('player.created_at', '<=', $requestFilter['created_at_end']);
}
}
$activePlayer = Request::input('active_player') ?? null;
if (!empty($activePlayer)){
$grid->model()->whereHas('the_last_player_login_record', function ($query) use ($activePlayer) {
if ($activePlayer == 1){
$query->whereDate('created_at', date('Y-m-d'));
} else {
$query->whereYear('created_at', date('Y'))
->whereMonth('created_at', date('m'));
}
});
}
$subQuery = PlayerDeliveryRecord::select('player_id', Db::raw('sum(amount) as amount'))
->whereNotIn('type', [1,2,3,4,5,9,10])
->groupBy('player_id');
$grid->model()->with(['player_register_record', 'channel', 'the_last_player_login_record'])
->select([
'player.*',
'player_extend.recharge_amount',
'player_extend.withdraw_amount',
'player_platform_cash.money as money',
'record.amount as present_coins'
])
->leftjoin('player_extend', 'player.id', '=', 'player_extend.player_id')
->leftjoin('player_platform_cash', 'player.id', '=', 'player_platform_cash.player_id')
->leftjoinSub($subQuery, 'record', function ($join) {
$join->on('player.id', '=', 'record.player_id');
})
->orderBy('player.id', 'desc');
$grid->autoHeight();
$grid->bordered(true);
$grid->column('id', admin_trans('player.fields.id'))->fixed(true)->align('center');
$grid->column('name', admin_trans('player.fields.name'))->display(function ($val, Player $data) {
$image = $data->avatar ? Avatar::create()->src(is_numeric($data->avatar) ? config('def_avatar.' . $data->avatar) : $data->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val),
]);
})->fixed(true)->align('center');
$grid->column('uuid', admin_trans('player.fields.uuid'))->fixed(true)->ellipsis(true)->align('center');
$grid->column('phone', admin_trans('player.fields.phone'))->fixed(true)->ellipsis(true)->align('center');
$grid->column('money', admin_trans('player_platform_cash.platform_name.' . PlayerPlatformCash::PLATFORM_SELF))->display(function ($val, Player $data) {
return Tag::create($val)->color('orange')->style(['cursor' => 'pointer'])->modal([$this, 'playerRecord'], ['id' => $data->id])->width('70%')->title($data->name . ' ' . $data->uuid);
})->ellipsis(true)->align('center')->sortable();
$grid->column('player_extend.recharge_amount', admin_trans('player_extend.fields.recharge_amount'))->ellipsis(true)->align('center')->sortable();
$grid->column('player_extend.withdraw_amount', admin_trans('player_extend.fields.withdraw_amount'))->ellipsis(true)->align('center')->sortable();
$grid->column('status', admin_trans('player.fields.status'))->switch()->ellipsis(true)->align('center');
$grid->column('player.created_at', admin_trans('player.fields.created_at'))->display(function ($val, Player $data) {
return Html::create()->content([
Html::div()->content(date('Y-m-d H:i:s', strtotime($data->created_at))),
Html::div()->content($data->player_register_record->ip ?? ''),
Html::div()->content($data->player_register_record->country_name ?? ''),
]);
})->ellipsis(true)->align('center')->sortable();
$grid->column('last_login', admin_trans('player.fields.player_login_record'))->display(function ($val, Player $data) {
return Html::create()->content([
Html::div()->content($val ?? (!empty($data->the_last_player_login_record->created_at) ? date('Y-m-d H:i:s', strtotime($data->the_last_player_login_record->created_at)) : '')),
Html::div()->content($data->the_last_player_login_record->ip ?? ''),
Html::div()->content($data->the_last_player_login_record->country_name ?? ''),
]);
})->ellipsis(true)->align('center')->sortable();
$grid->filter(function (Filter $filter) {
$filter->like()->text('uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('name')->placeholder(admin_trans('player.fields.name'));
$filter->like()->text('phone')->placeholder(admin_trans('player.fields.phone'));
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player.fields.department_id'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->eq()->select('level')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player.fields.level'))
->options(playerLevelOptions());
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->expandFilter();
$grid->hideDelete();
$grid->hideSelection();
$grid->tools([
$grid->addButton()->modal($this->form()),
Button::create(admin_trans('player.level_setting'))
->danger()
->style(['margin-left' => '10px'])
->drawer($this->levelSetting())
]
);
$grid->actions(function (Actions $actions, Player $data) {
$actions->edit()->modal($this->form())->width('60%');
$actions->hideDel();
$dropdown = $actions->dropdown();
$dropdown->prepend(admin_trans('admin.reset_password'), 'fas fa-key')
->modal($this->resetPassword($data->id));
$dropdown->append(admin_trans('player.wallet.player_wallet'), 'MoneyCollectFilled')
->modal($this->playerWallet([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px');
$dropdown->append(admin_trans('player.wallet.artificial_recharge'), 'TransactionOutlined')
->modal($this->artificialRecharge([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_recharge'))->content(
ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_recharge_tip'))
));
$dropdown->append(admin_trans('player.wallet.artificial_withdrawal'), 'PayCircleOutlined')
->modal($this->artificialWithdrawal([
'id' => $data->id,
'money' => $data->wallet->money ?? 0,
]))->width('600px')->title(Html::create(admin_trans('player.wallet.artificial_withdrawal'))->content(
ToolTip::create(Icon::create('QuestionCircleOutlined')->style(['marginLeft' => '5px', 'cursor' => 'pointer']))->title(admin_trans('player.wallet.artificial_withdrawal_tip'))
));
});
$grid->updateing(function ($ids, $data) {
if (isset($ids[0]) && isset($data['player_extend'])) {
if (PlayerExtend::updateOrCreate(
['player_id' => $ids[0]],
$data['player_extend']
)) {
return message_success(admin_trans('player.remark_edit_success'));
}
}
});
});
}
/**
* @return Form
*/
public function levelSetting(): Form
{
$list = PlayerLevel::query()->orderBy('level')->get();
$data = [];
/** @var PlayerLevel $playerLevel */
foreach ($list as $playerLevel) {
$data['id'][$playerLevel->level] = $playerLevel->id;
$data['level'][$playerLevel->level] = $playerLevel->level;
$data['recharge_amount'][$playerLevel->level] = $playerLevel->recharge_amount;
$data['chip_multiple'][$playerLevel->level] = $playerLevel->chip_multiple;
$data['bet_rebate_ratio'][$playerLevel->level] = $playerLevel->bet_rebate_ratio;
$data['damage_rebate_ratio'][$playerLevel->level] = $playerLevel->damage_rebate_ratio;
$data['content'][$playerLevel->level] = json_decode($playerLevel->content, true);
}
return Form::create($data, function (Form $form) {
$form->labelWidth('200');
$form->layout('vertical');
$langList = plugin()->webman->config('ui.lang.list');
$tabs = $form->tabs()
->tabPosition('left')
->destroyInactiveTabPane();
for ($i = 1; $i <= 13; $i++) {
$tabs->pane(admin_trans('player.level.' . $i), function (Form $form) use ($i, $langList) {
$tabs = $form->tabs()->destroyInactiveTabPane();
foreach ($langList as $k => $v) {
$tabs->pane($v, function (Form $form) use ($k, $i) {
$form->text("content." . $i . '.' . $k . ".level_name", admin_trans('player_level.level_name'))
->required()->maxlength(20)
->help(admin_trans('player_level.help.level_name'));
$form->textarea("content." . $i . '.' . $k . ".content", admin_trans('player_level.level_content'))
->rows(5)
->required()->showCount()->maxlength(500)
->help(admin_trans('player_level.help.level_content'));
});
}
$form->hidden('id.' . $i);
$form->hidden('level.' . $i)->value($i);
$form->number('recharge_amount.' . $i, admin_trans('player_level.recharge_amount'))
->min(0)
->max(1000000000)
->precision(0)
->style(['width' => '300px'])
->default(0)
->required()
->controls(false)
->help(admin_trans('player_level.help.recharge_amount', null, ['{max_amount}' => 1000000000]));
$form->number('chip_multiple.' . $i, admin_trans('player_level.chip_multiple'))
->min(0)
->max(10000)
->precision(2)
->style(['width' => '300px'])
->controls(false)
->default(0)
->required()
->addonAfter('%')
->help(admin_trans('player_level.help.chip_multiple', null, ['{max_multiple}' => 10000]));
$form->number('bet_rebate_amount.' . $i, admin_trans('player_level.bet_rebate_amount'))
->min(0)
->max(1000000000)
->precision(0)
->style(['width' => '300px'])
->controls(false)
->default(0)
->required()
->help(admin_trans('player_level.help.bet_rebate_amount', null, ['{max_amount}' => 1000000000]));
$form->number('bet_rebate_ratio.' . $i, admin_trans('player_level.bet_rebate_ratio'))
->min(0)
->max(100)
->precision(2)
->style(['width' => '300px'])
->controls(false)
->addonAfter('%')
->default(0)
->required()
->help(admin_trans('player_level.help.bet_rebate_ratio', null, ['{max_ratio}' => 100]));
$form->number('damage_rebate_ratio.' . $i, admin_trans('player_level.damage_rebate_ratio'))
->min(0)
->max(100)
->precision(2)
->style(['width' => '300px'])
->controls(false)
->addonAfter('%')
->default(0)
->required()
->help(admin_trans('player_level.help.damage_rebate_ratio', null, ['{max_ratio}' => 100]));
});
}
$form->saving(function (Form $form) {
$idArr = $form->input('id');
$levelArr = $form->input('level');
$rechargeAmountArr = $form->input('recharge_amount');
$chipMultipleArr = $form->input('chip_multiple');
$betRebateAmountArr = $form->input('bet_rebate_amount');
$betRebateRatioArr = $form->input('bet_rebate_ratio');
$damageRebateRatioArr = $form->input('damage_rebate_ratio');
$content = $form->input('content');
DB::beginTransaction();
try {
foreach ($idArr as $key => $item) {
if (empty($rechargeAmountArr[$key])) {
throw new \Exception(admin_trans('player_level.recharge_amount_not_found', null, ['{level}' => admin_trans('player_level.level') . $key]));
}
if (!empty($item)) {
$playerLevel = PlayerLevel::query()->find($item);
} else {
$playerLevel = new PlayerLevel();
}
$playerLevel->level = $levelArr[$key];
$playerLevel->content = json_encode($content[$key]);
$playerLevel->recharge_amount = $rechargeAmountArr[$key];
$playerLevel->chip_multiple = $chipMultipleArr[$key];
$playerLevel->bet_rebate_amount = $betRebateAmountArr[$key];
$playerLevel->bet_rebate_ratio = $betRebateRatioArr[$key];
$playerLevel->damage_rebate_ratio = $damageRebateRatioArr[$key];
if ($key > 1 && $rechargeAmountArr[$key] <= $rechargeAmountArr[$key - 1]) {
throw new \Exception(admin_trans('player_level.recharge_amount_must_gt_upper', null, ['{level}' => admin_trans('player_level.level') . $key]));
}
if ($key > 1 && $key < 7 && $rechargeAmountArr[$key] >= $rechargeAmountArr[$key + 1]) {
throw new \Exception(admin_trans('player_level.recharge_amount_must_lt_next', null, ['{level}' => admin_trans('player_level.level') . $key]));
}
$playerLevel->save();
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('form.save_success'));
});
});
}
/**
* 人工提现
* @auth true
* @param $data
* @return Form
*/
public function artificialWithdrawal($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->number('coins', admin_trans('player_withdraw_record.fields.coins'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%'])
->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
->required();
$form->number('money', admin_trans('player_withdraw_record.fields.money'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%']);
$form->text('currency', admin_trans('player_withdraw_record.fields.currency'))->maxlength(10);
$form->text('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->maxlength(50);
$form->text('account', admin_trans('player_withdraw_record.fields.account'))->maxlength(50);
$form->text('account_name', admin_trans('player_withdraw_record.fields.account_name'))->maxlength(50);
$form->textarea('remark', admin_trans('player_withdraw_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
$form->layout('vertical');
$form->hidden('id')->value($data['id']);
$form->saving(function (Form $form) {
/** @var Player $player */
$player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
if ($player->status == 0) {
return message_error(admin_trans('player.disable'));
}
if ($player->wallet->money < $form->input('coins')) {
return message_error(admin_trans('player.insufficient_balance'));
}
DB::beginTransaction();
try {
$beforeGameAmount = $player->wallet->money;
// 生成订单
$playerWithdrawRecord = new PlayerWithdrawRecord();
$playerWithdrawRecord->player_id = $player->id;
$playerWithdrawRecord->talk_user_id = $player->talk_user_id;
$playerWithdrawRecord->department_id = $player->department_id;
$playerWithdrawRecord->tradeno = createOrderNo();
$playerWithdrawRecord->player_name = $player->name ?? '';
$playerWithdrawRecord->player_phone = $player->phone ?? '';
$playerWithdrawRecord->money = $form->input('money') ?? 0;
$playerWithdrawRecord->coins = $form->input('coins') ?? 0;
$playerWithdrawRecord->fee = 0;
$playerWithdrawRecord->inmoney = bcsub($playerWithdrawRecord->money, $playerWithdrawRecord->fee, 2); // 实际提现金额
$playerWithdrawRecord->currency = $form->input('currency') ?? 0;
$playerWithdrawRecord->bank_name = $form->input('bank_name') ?? 0;
$playerWithdrawRecord->account = $form->input('account') ?? 0;
$playerWithdrawRecord->account_name = $form->input('account_name') ?? 0;
$playerWithdrawRecord->type = PlayerWithdrawRecord::TYPE_ARTIFICIAL;
$playerWithdrawRecord->status = PlayerWithdrawRecord::STATUS_SUCCESS;
$playerWithdrawRecord->finish_time = date('Y-m-d H:i:s');
$playerWithdrawRecord->save();
// 玩家钱包扣减
$player->wallet->money = bcsub($player->wallet->money, $playerWithdrawRecord->coins, 2);
// 更新玩家统计
$player->player_extend->withdraw_amount = bcadd($player->player_extend->withdraw_amount, $playerWithdrawRecord->coins, 2);
$player->push();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerWithdrawRecord->player_id;
$playerDeliveryRecord->department_id = $playerWithdrawRecord->department_id;
$playerDeliveryRecord->target = $playerWithdrawRecord->getTable();
$playerDeliveryRecord->target_id = $playerWithdrawRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_WITHDRAWAL;
$playerDeliveryRecord->source = 'artificial_withdrawal';
$playerDeliveryRecord->amount = $playerWithdrawRecord->coins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = $playerWithdrawRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerWithdrawRecord->remark ?? '';
$playerDeliveryRecord->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.artificial_withdrawal_error'));
}
return message_success(admin_trans('player.artificial_withdrawal_success'));
});
});
}
/**
* 人工充值
* @auth true
* @param $data
* @return Form
*/
public function artificialRecharge($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->number('coins', admin_trans('player_recharge_record.fields.coins'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%'])
->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)
->required();
$form->number('money', admin_trans('player_recharge_record.fields.money'))
->min(0)
->max(100000000)
->precision(2)
->style(['width' => '100%']);
$form->text('currency', admin_trans('player_recharge_record.fields.currency'))->maxlength(10);
$form->textarea('remark', admin_trans('player_recharge_record.fields.remark'))->maxlength(255)->bindAttr('rows', 4);
$form->layout('vertical');
$form->hidden('id')->value($data['id']);
$form->saving(function (Form $form) {
/** @var Player $player */
$player = Player::where('id', $form->input('id'))->whereNull('deleted_at')->first();
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
if ($player->status == 0) {
return message_error(admin_trans('player.disable'));
}
DB::beginTransaction();
try {
$beforeGameAmount = $player->wallet->money;
// 生成订单
$playerRechargeRecord = new PlayerRechargeRecord();
$playerRechargeRecord->player_id = $player->id;
$playerRechargeRecord->department_id = $player->department_id;
$playerRechargeRecord->tradeno = createOrderNo();
$playerRechargeRecord->player_name = $player->name ?? '';
$playerRechargeRecord->money = $form->input('money') ?? 0;
$playerRechargeRecord->inmoney = $form->input('money') ?? 0;
$playerRechargeRecord->currency = $form->input('currency') ?? '';
$playerRechargeRecord->type = PlayerRechargeRecord::TYPE_ARTIFICIAL;
$playerRechargeRecord->coins = $form->input('coins');
$playerRechargeRecord->status = PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS;
$playerRechargeRecord->remark = $form->input('remark');
$playerRechargeRecord->finish_time = date('Y-m-d H:i:s');
$playerRechargeRecord->user_id = Admin::id() ?? 0;
$playerRechargeRecord->user_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : '';
$playerRechargeRecord->save();
$player->wallet->money = bcadd($player->wallet->money, $playerRechargeRecord->coins, 2);
$player->player_extend->recharge_amount = bcadd($player->player_extend->recharge_amount, $playerRechargeRecord->coins, 2);
$player->push();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerRechargeRecord->player_id;
$playerDeliveryRecord->department_id = $playerRechargeRecord->department_id;
$playerDeliveryRecord->target = $playerRechargeRecord->getTable();
$playerDeliveryRecord->target_id = $playerRechargeRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_RECHARGE;
$playerDeliveryRecord->source = 'artificial_recharge';
$playerDeliveryRecord->amount = $playerRechargeRecord->coins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = $playerRechargeRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerRechargeRecord->remark ?? '';
$playerDeliveryRecord->save();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.artificial_recharge_error'));
}
return message_success(admin_trans('player.artificial_recharge_success'));
});
});
}
/**
* 处理标签
* @param array $value
* @return Html
*/
public function handleTagIds(array $value): Html
{
$options = $this->getPlayerTagOptions($value);
$html = Html::create();
foreach ($options as $option) {
$html->content(
Tag::create($option)
->color('success')
);
}
return $html;
}
/**
* 获取玩家标签选项(筛选id)
* @param array $ids
* @return array
*/
public function getPlayerTagOptions(array $ids = []): array
{
$idsStr = json_encode($ids);
$cacheKey = md5("player_tag_options_ids_$idsStr");
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
if (!empty($ids)) {
$data = (new PlayerTag())->whereIn('id', $ids)->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
return [];
}
}
/**
* 获取玩家标签(筛选id)
* @return array
*/
public function getPlayerTagOptionsFilter(): array
{
$cacheKey = "doc_player_tag_options_filter";
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
$data = (new PlayerTag())->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
}
/**
* 玩家标签修改保存
* @return Form
*/
public function playerTagForm(): Form
{
return Form::create(new $this->playerTag, function (Form $form) {
$form->text('name', '名称');
$form->saving(function (Form $form) {
if ($form->isEdit()) {
$id = $form->driver()->get('id');
/** @var PlayerTag $tag */
$tag = PlayerTag::find($id);
$tag->name = $form->input('name');
$tag->save();
} else {
$tag = new PlayerTag();
$tag->name = $form->input('name');
$tag->save();
}
return message_success(admin_trans('form.save_success'))->refreshMenu();
});
});
}
/**
* 玩家信息
* @auth true
* @return Form
*/
public function form(): Form
{
$options = [];
foreach (config('def_avatar') as $key => $item) {
$options[$key] = Avatar::create()->style(['padding' => '1px'])->src($item)->shape('square');
}
return Form::create(new $this->model(), function (Form $form) use ($options) {
if ($form->isEdit()) {
$form->title(admin_trans('player.details'));
$form->row(function (Form $form) use ($options) {
$form->column(function (Form $form) use ($options) {
$form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleNumber()->disabled(true);
$form->text('name', admin_trans('player.fields.name'))->maxlength(50);
$form->radio('avatar_type', admin_trans('player.avatar_type'))
->button()
->default(is_numeric($form->driver()->get('avatar')) ? 2 : 1)
->options([
1 => admin_trans('player.upload_avatar'),
2 => admin_trans('player.def_avatar')
])
->when(1, function (Form $form) {
$form->image('avatar', admin_trans('player.fields.avatar'))->value(is_numeric($form->driver()->get('avatar')) ? '' : $form->driver()->get('avatar'))->ext('jpg,png,jpeg')->fileSize('1m');
})->when(2, function (Form $form) use ($options) {
$form->radio('def_avatar', admin_trans('player.def_avatar'))
->default(1)
->options($options);
});
$form->text('player_extend.id_number', admin_trans('player_extend.fields.id_number'))->ruleAlphaNum()->maxlength(20);
$form->desc('the_last_player_login_record.created_at', admin_trans('player.fields.login_at'))->value($form->input('the_last_player_login_record.created_at') ? date('Y-m-d H:i:s', strtotime($form->input('the_last_player_login_record.created_at'))) : '');
$form->desc('created_at', admin_trans('player.fields.created_at'))->value($form->input('created_at') ? date('Y-m-d H:i:s', strtotime($form->input('created_at'))) : '');
$form->desc('player_register_record.ip', admin_trans('player.fields.register_ip'));
$form->desc('player_register_record.register_domain', admin_trans('player.fields.register_domain'));
})->span(12);
$form->column(function (Form $form) {
$form->text('player_extend.address', admin_trans('player_extend.fields.address'))->maxlength(255);
$form->date('player_extend.birthday', admin_trans('player_extend.fields.birthday'));
$form->text('player_extend.email', admin_trans('player_extend.fields.email'))->ruleEmail()->maxlength(20);
$form->text('player_extend.line', admin_trans('player_extend.fields.line'))->ruleAlphaNum()->maxlength(20);
$form->textarea('player_extend.remark', admin_trans('player_extend.fields.remark'))
->showCount()
->rule(['max:255' => admin_trans('player_extend.fields.remark')]);
$playerBank = PlayerBank::query()->where('player_id', $form->driver()->get('id'))->get()->toArray();
foreach ($playerBank as $key => $item) {
$form->row(function (Form $form) use ($item, $key) {
$form->text('bank_name'.$key, admin_trans('player.bank_name'))
->value($item['bank_name'] ?? 0)
->disabled(true);
$form->text('account_name'.$key, admin_trans('player.account_name'))
->value($item['account_name'] ?? 0)
->disabled(true);
$form->text('account'.$key, admin_trans('player.account'))
->value($item['account'] ?? 0)
->disabled(true);
});
}
})->span(12);
});
} else {
$form->title(admin_trans('player.add_player'));
$form->text('phone', admin_trans('player.fields.phone'))->maxlength(50)->ruleAlphaNum()->required();
$form->radio('avatar_type', admin_trans('player.avatar_type'))
->button()
->default(2)
->options([
1 => admin_trans('player.upload_avatar'),
2 => admin_trans('player.def_avatar')
])
->when(1, function (Form $form) {
$form->image('avatar', admin_trans('player.fields.avatar'))->ext('jpg,png,jpeg')->fileSize('1m');
})->when(2, function (Form $form) use ($options) {
$form->radio('def_avatar', admin_trans('player.def_avatar'))
->default(1)
->options($options);
});
$form->select('country_code', admin_trans('player.fields.country_code'))->options([
PhoneSmsLog::COUNTRY_CODE_MY => PhoneSmsLog::COUNTRY_CODE_MY,
])->required();
$form->select('department_id', admin_trans('player.fields.department_id'))->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']))->required();
$form->text('name', admin_trans('player.fields.name'))->maxlength(50)->required();
$form->password('password', admin_trans('player.new_password'))
->rule([
'confirmed' => admin_trans('player.password_confim_validate'),
'min:6' => admin_trans('player.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('player.confim_password'))
->required();
}
$form->saved(function () {
return message_success(admin_trans('player.save_player_info_success'));
});
$form->saving(function (Form $form) {
if ($form->isEdit()) {
$orgData = $form->driver()->get();
/** @var Player $player */
$player = Player::find($orgData['id']);
if (empty($player)) {
return message_error(admin_trans('player.not_fount'));
}
DB::beginTransaction();
try {
$player->name = $form->input('name');
$player->avatar = $form->input('avatar_type') == 1 ? $form->input('avatar') : $form->input('def_avatar');
$player->save();
PlayerExtend::query()->updateOrCreate(['player_id' => $orgData['id']], [
'address' => $form->input('player_extend.address'),
'birthday' => $form->input('player_extend.birthday'),
'id_number' => $form->input('player_extend.id_number'),
'email' => $form->input('player_extend.email'),
'line' => $form->input('player_extend.line'),
'remark' => $form->input('player_extend.remark'),
'player_id' => $orgData['id']]);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('player.save_player_info_success'));
} else {
$phone = $form->input('phone');
$password = $form->input('password');
$country_code = $form->input('country_code');
/** @var $player Player */
$player = Player::query()->where('phone', $country_code.$phone)->first();
if (!empty($player)) {
return message_error(admin_trans('player.phone_has_register'));
}
/** @var Channel $channel */
$channel = Channel::where('department_id', $form->input('department_id'))->first();
if (empty($channel)) {
return jsonFailResponse(trans('channel_not_found', [], 'message'));
}
DB::beginTransaction();
try {
$player = new Player();
$player->phone = $country_code.$phone;
$player->name = $form->input('name');
if ($form->input('avatar_type') == 1) {
$player->avatar = $form->input('avatar') ?? config('def_avatar.1');
}
if ($form->input('avatar_type') == 2) {
$player->avatar = $form->input('def_avatar') ?? config('def_avatar.1');
}
$player->country_code = $country_code;
$player->type = Player::TYPE_PLAYER;
$player->currency = $channel->currency;
$player->department_id = $channel->department_id;
$player->password = $password;
$player->uuid = gen_uuid();
$player->recommend_code = createCode();
$player->save();
addPlayerExtend($player, [
'email' => $data['email'] ?? ''
]);
addRegisterRecord($player->id, PlayerRegisterRecord::TYPE_ADMIN, $player->department_id);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error($e->getMessage());
}
return message_success(admin_trans('player.save_player_info_success'));
}
});
});
}
/**
* 重置密码
* @auth true
* @param $id
* @return Form
*/
public function resetPassword($id): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->password('password', admin_trans('player.new_password'))
->rule([
'confirmed' => admin_trans('player.password_confim_validate'),
'min:6' => admin_trans('player.password_min_number')
])
->value('')
->required();
$form->password('password_confirmation', admin_trans('player.confim_password'))
->required();
});
}
/**
* 玩家钱包
* @auth true
* @param $data
* @return Form
*/
public function playerWallet($data): Form
{
return Form::create(new $this->model, function (Form $form) use ($data) {
$form->hidden('id')->default($data['id']);
$form->row(function (Form $form) {
$type = $form->getBindField('type');
$form->radio('type', admin_trans('player.wallet.type'))
->button()
->disabled($form->isEdit())
->default(PlayerMoneyEditLog::TYPE_INCREASE)
->options([
admin_trans('player.wallet.deduct'),
admin_trans('player.wallet.increase'),
])->required()->span(7);
$form->hidden('type')->bindAttr('value', $type)
->when(PlayerMoneyEditLog::TYPE_DEDUCT, function (Form $form) {
$form->select('deduct_action', admin_trans('player.wallet.action'))
->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_DEDUCT]))
->required()->span(16)->style(['margin-left' => '22px']);
})->when(PlayerMoneyEditLog::TYPE_INCREASE, function (Form $form) {
$form->select('increase_action', admin_trans('player.wallet.action'))
->remoteOptions(admin_url([$this, 'getTranOptions'], ['type' => PlayerMoneyEditLog::TYPE_INCREASE]))
->required()->span(16)->style(['margin-left' => '22px']);
});
});
$form->number('money', admin_trans('player.wallet.money'))->min(0)->max(100000000)->precision(2)->style(['width' => '100%'])->addonBefore(admin_trans('player.wallet.wallet') . ' ' . $data['money'] ?? 0)->required();
$form->textarea('remark', admin_trans('player.wallet.textarea'))->maxlength(255)->bindAttr('rows', 4)->required();
$form->actions()->hideResetButton();
$form->saving(function (Form $form) use ($data) {
return $this->store([
'id' => $form->input('id'),
'type' => $form->input('type'),
'deduct_action' => $form->input('deduct_action'),
'increase_action' => $form->input('increase_action'),
'money' => $form->input('money'),
'remark' => $form->input('remark'),
]);
});
$form->layout('vertical');
});
}
/**
* 钱包操作
* @param $data
* @return Msg
*/
public function store($data): Msg
{
try {
DB::beginTransaction();
playerManualSystem($data);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return message_error(admin_trans('player.wallet.wallet_operation_failed'));
}
return message_success(admin_trans('player.wallet.wallet_operation_success'));
}
/**
* 钱包操作类型
* @param $type
* @return mixed
*/
public function getTranOptions($type)
{
$options = [];
if ($type == PlayerMoneyEditLog::TYPE_INCREASE) {
$transactionType = [
PlayerMoneyEditLog::ACTIVITY_GIVE,
PlayerMoneyEditLog::ADMIN_INCREASE,
PlayerMoneyEditLog::OTHER
];
} else {
$transactionType = [
PlayerMoneyEditLog::ADMIN_DEDUCT,
PlayerMoneyEditLog::OTHER
];
}
foreach ($transactionType as $item) {
$options[] = [
'value' => $item,
'label' => admin_trans('player.wallet.wallet_type.' . $item),
];
}
return Response::success($options);
}
/**
* 玩家记录
* @param $id
* @auth true
* @return Card
*/
public function playerRecord($id): Card
{
$tabs = Tabs::create()
->pane(admin_trans('player.player_recharge_record'), $this->rechargeRecord($id))
->pane(admin_trans('player.player_withdraw_record'), $this->withdrawalRecords($id))
->pane(admin_trans('player.player_delivery_record'), $this->playerDeliveryRecord($id));
return Card::create($tabs);
}
/**
* 提现记录
* @param $id
* @return Grid
*/
public function withdrawalRecords($id): Grid
{
return Grid::create(new $this->withdraw(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_withdraw_record.title'));
$grid->model()->with(['channel'])->where('player_id', $id)->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
}
$grid->bordered();
$grid->autoHeight();
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->align('center');
$grid->column('player_phone', admin_trans('player_withdraw_record.fields.player_phone'))->display(function ($val, PlayerWithdrawRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->align('center');
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->copy()->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column(function (Grid $grid) {
$grid->column('bank_name', admin_trans('player_withdraw_record.fields.bank_name'))->copy()->align('center');
$grid->column('account_name', admin_trans('player_withdraw_record.fields.account_name'))->copy()->align('center');
$grid->column('account', admin_trans('player_withdraw_record.fields.account'))->copy()->align('center');
}, admin_trans('player_withdraw_record.player_bank'));
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerWithdrawRecord::TYPE_SELF:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#3b5999');
case PlayerWithdrawRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->align('center');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function () {
return Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
})->align('center')->sortable();
$grid->column('channel.name', admin_trans('player_withdraw_record.fields.department_id'))->align('center');
$grid->column('finish_time', admin_trans('player_withdraw_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_withdraw_record.fields.finish_time'), admin_trans('player_withdraw_record.fields.finish_time')]);
});
$grid->quickSearch();
});
}
/**
* 钱包操作
* @param $id
* @return Grid
*/
public function playerDeliveryRecord($id): Grid
{
return Grid::create(new $this->playerDeliveryRecord, function (Grid $grid) use ($id) {
$lang = Container::getInstance()->translator->getLocale();
$grid->title(admin_trans('promoter_profit_record.player_activity_phase_record_title'));
$grid->model()
->where('player_id', $id)
->whereIn('type', [
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD,
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT,
])
->orderBy('id', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
}
$grid->autoHeight();
$grid->bordered(true);
$grid->column('id', admin_trans('player_delivery_record.fields.id'))->align('center');
$grid->column('source', admin_trans('player_delivery_record.fields.source'))->display(function ($val, PlayerDeliveryRecord $data) use ($lang) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Tag::create(trans($val, [], 'message', $lang))->color('red');
default:
return '';
}
})->align('center');
$grid->column('type', admin_trans('player_delivery_record.fields.type'))
->display(function ($value) {
switch ($value) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD))->color('#2db7f5');
break;
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT))->color('#108ee9');
break;
default:
$tag = '';
}
return Html::create()->content([
$tag
]);
})->align('center')->sortable();
$grid->column('amount', admin_trans('player_delivery_record.fields.amount'))->display(function ($val, PlayerDeliveryRecord $data) {
if ($data->amount == 0) {
return Html::create()->content([$val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('user_name', admin_trans('player_delivery_record.fields.user_name'))->display(function ($val, PlayerDeliveryRecord $data) {
$name = '--';
if (in_array($data->type, [PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD, PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT])) {
$name = $data->user_name ?? '管理员';
}
return Html::create()->content([
Html::div()->content($name),
]);
});
$grid->column('created_at', admin_trans('player_delivery_record.fields.created_at'))->align('center')->ellipsis(true);
$grid->hideDelete();
$grid->hideSelection();
$grid->hideTrashed();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('type')
->placeholder(admin_trans('player_delivery_record.fields.type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD),
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT),
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
});
}
/**
* 充值记录
* @param $id
* @return Grid
*/
public function rechargeRecord($id): Grid
{
return Grid::create(new $this->recharge(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_recharge_record.title'));
$grid->bordered();
$grid->autoHeight();
$grid->model()->with(['channel', 'channel_recharge_setting'])->where('player_id', $id)->where('status', PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS)->orderBy('created_at', 'desc');
$grid->column('id', admin_trans('player_recharge_record.fields.id'))->align('center');
$grid->column('player_phone', admin_trans('player_recharge_record.fields.player_phone'))->display(function ($val, PlayerRechargeRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
]);
})->align('center');
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->copy()->align('center');
$grid->column('channel.name', admin_trans('player_recharge_record.fields.department_id'))->align('center');
$grid->column('type', admin_trans('player_recharge_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::TYPE_ACTIVITY:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#55acee');
case PlayerRechargeRecord::TYPE_REGULAR:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return $val . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->align('center');
$grid->column(function (Grid $grid) {
$grid->column('bank_name', admin_trans('channel_recharge_method.fields.bank_name'))->copy()->align('center');
$grid->column('sub_bank', admin_trans('channel_recharge_method.fields.sub_bank'))->copy()->align('center');
$grid->column('owner', admin_trans('channel_recharge_method.fields.owner'))->copy()->align('center');
$grid->column('account', admin_trans('channel_recharge_method.fields.account'))->copy()->align('center');
}, admin_trans('channel_recharge_setting.recharge_setting_info'));
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function () {
return Tag::create(admin_trans('player_recharge_record.status_success'))->color('#87d068');
})->align('center');
$grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.type'))
->options([
PlayerRechargeRecord::TYPE_REGULAR => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_REGULAR),
PlayerRechargeRecord::TYPE_ACTIVITY => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ACTIVITY),
PlayerRechargeRecord::TYPE_ARTIFICIAL => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ARTIFICIAL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->between()->dateTimeRange('created_at')->placeholder([admin_trans('player_recharge_record.fields.created_at'), admin_trans('player_recharge_record.fields.created_at')]);
$filter->between()->dateTimeRange('finish_time')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);
});
$grid->quickSearch();
});
}
/**
* 打码量记录
* @param $id
* @return Grid
*/
public function playerChipRecord($id): Grid
{
return Grid::create(new $this->playerChipRecord(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('player_chip_record.title'));
$grid->bordered();
$grid->autoHeight();
$grid->model()->with(['channel', 'player'])
->where('player_id', $id)
->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
$query = clone $grid->model();
$totalData = $query->where(function ($query) use($exAdminFilter) {
if(!empty($exAdminFilter['created_at'])) {
$query->whereBetween('created_at', $exAdminFilter['created_at']);
}
})->sum('chip_amount');
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->value($totalData)
->prefix(admin_trans('player_chip_record.fields.chip_amount'))
->valueStyle([
'font-size' => '14px',
'font-weight' => '500',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '30px',
'padding' => '0px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 4);
})->style(['background' => '#fff']);
$grid->tools([
$layout
]);
$grid->column('id', admin_trans('player_chip_record.fields.id'))->align('center');
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('chip_amount', admin_trans('player_chip_record.fields.chip_amount'))->display(function ($val, PlayerChipRecord $data) {
if ($val == 0) {
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerChipRecord::TYPE_DEC:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('must_chip_amount', admin_trans('player_chip_record.fields.must_chip_amount'))->display(function ($val, PlayerChipRecord $data) {
if ($val == 0) {
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
switch ($data->type) {
case PlayerChipRecord::TYPE_DEC:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('record_type', admin_trans('player_chip_record.fields.record_type'))->display(function ($val) {
switch ($val) {
case PlayerChipRecord::RECORD_TYPE_SIGN:
case PlayerChipRecord::RECORD_TYPE_RECHARGE:
case PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#55acee');
break;
case PlayerChipRecord::RECORD_TYPE_ACTIVITY:
case PlayerChipRecord::RECORD_TYPE_GAME:
case PlayerChipRecord::RECORD_TYPE_BET_REBATE:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#3b5999');
break;
case PlayerChipRecord::RECORD_TYPE_COMMISSION:
case PlayerChipRecord::RECORD_TYPE_BANKRUPTCY:
$tag = Tag::create(admin_trans('player_chip_record.record_type.' . $val))
->color('#cd201f');
break;
default:
return '';
}
return Html::create()->content([
$tag,
]);
})->align('center');
$grid->column('amount', admin_trans('player_chip_record.fields.amount'))->align('center');
$grid->column('created_at', admin_trans('player_chip_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->eq()->select('record_type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_chip_record.fields.record_type'))
->options([
PlayerChipRecord::RECORD_TYPE_SIGN => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_SIGN),
PlayerChipRecord::RECORD_TYPE_RECHARGE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_RECHARGE),
PlayerChipRecord::RECORD_TYPE_ACTIVITY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_ACTIVITY),
PlayerChipRecord::RECORD_TYPE_GAME => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_GAME),
PlayerChipRecord::RECORD_TYPE_COMMISSION => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_COMMISSION),
PlayerChipRecord::RECORD_TYPE_BANKRUPTCY => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BANKRUPTCY),
PlayerChipRecord::RECORD_TYPE_BET_REBATE => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_BET_REBATE),
PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD => admin_trans('player_chip_record.record_type.' . PlayerChipRecord::RECORD_TYPE_FIRST_RECHARGE_REWARD),
]);
$filter->between()->dateTimeRange('created_at')->placeholder([admin_trans('player_chip_record.fields.created_at'), admin_trans('player_chip_record.fields.created_at')]);
});
$grid->quickSearch();
});
}
/**
* 取消转账
* @param $id
* @auth true
* @return Msg
*/
public function cancelTransfer($id): Msg
{
/** @var PlayerWalletTransfer $playerWalletTransfer */
$playerWalletTransfer = PlayerWalletTransfer::query()->where('player_id', $id)->orderBy('id', 'desc')->first();
/** @var Player $player */
$player = Player::query()->find($id);
if (!empty($playerWalletTransfer) && $playerWalletTransfer->type == PlayerWalletTransfer::TYPE_OUT) {
$playerWalletTransferOut = new PlayerWalletTransfer();
$playerWalletTransferOut->player_id = $player->id;
$playerWalletTransferOut->platform_id = $playerWalletTransfer->platform_id;
$playerWalletTransferOut->department_id = $player->department_id;
$playerWalletTransferOut->type = PlayerWalletTransfer::TYPE_IN;
$playerWalletTransferOut->amount = 0;
$playerWalletTransferOut->reward = 0;
$playerWalletTransferOut->platform_no = 'cancelTransfer';
$playerWalletTransferOut->tradeno = createOrderNo();
$playerWalletTransferOut->save();
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_CANCELTRANSFER;
//寫入金流明細
$playerDeliveryRecord->player_id = $playerWalletTransferOut->player_id;
$playerDeliveryRecord->department_id = $playerWalletTransferOut->department_id;
$playerDeliveryRecord->target = $playerWalletTransferOut->getTable();
$playerDeliveryRecord->target_id = $playerWalletTransferOut->id;
$playerDeliveryRecord->source = 'cancel_transfer';
$playerDeliveryRecord->amount = $playerWalletTransferOut->amount;
$playerDeliveryRecord->amount_before = $player->wallet->money;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = '';
$playerDeliveryRecord->remark = '管理员取消转账平台ID' . $playerWalletTransfer->platform_id;
$playerDeliveryRecord->save();
return message_success(admin_trans('player.action_success'));
}
return message_error(admin_trans('player.action_error'));
}
}

View File

@@ -0,0 +1,204 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\PlayerDeliveryRecord;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\FilterColumn;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\support\Container;
use ExAdmin\ui\support\Request;
/**
* 账变记录
*/
class PlayerDeliveryRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_delivery_record_model');
}
/**
* 玩家账变
* @auth true
*/
public function index(): Grid
{
$lang = Container::getInstance()->translator->getLocale();
return Grid::create(new $this->model(), function (Grid $grid) use ($lang) {
$grid->title(admin_trans('player_delivery_record.title'));
$grid->model()->with(['player'])->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['search_source']) && !empty($exAdminFilter['search_source'])) {
$searchSource = $exAdminFilter['search_source'];
$grid->model()->where(function ($query) use ($searchSource) {
$query->where([
['source', 'like', '%' . $searchSource . '%', 'and'],
]);
});
}
$grid->autoHeight();
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->align('center');
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerDeliveryRecord $data) {
$image = $data->player->avatar ? Avatar::create()->src(is_numeric($data->player->avatar) ? config('def_avatar.' . $data->player->avatar) : $data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($data->player->name),
]);
})->align('center')->filter(
FilterColumn::like()->text('player.phone')
);
$grid->column('source', admin_trans('player_delivery_record.fields.source'))->display(function ($val, PlayerDeliveryRecord $data) use ($lang) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
case PlayerDeliveryRecord::TYPE_RECHARGE:
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
case PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK:
return Tag::create(trans($val, [], 'message', $lang))->color('red');
case PlayerDeliveryRecord::TYPE_REGISTER_PRESENT:
return Tag::create(trans($val, [], 'message', $lang))->color('blue');
case PlayerDeliveryRecord::TYPE_COMMISSION:
case PlayerDeliveryRecord::TYPE_GAME_OUT:
return Tag::create(trans($val, [], 'message', $lang))->color('purple');
case PlayerDeliveryRecord::TYPE_SIGN:
case PlayerDeliveryRecord::TYPE_GAME_IN:
case PlayerDeliveryRecord::TYPE_BET_REBATE:
case PlayerDeliveryRecord::TYPE_DAMAGE_REBATE:
case PlayerDeliveryRecord::TYPE_RECHARGE_REWARD:
case PlayerDeliveryRecord::TYPE_PROFIT:
return Tag::create(trans($val, [], 'message', $lang))->color('orange');
default:
return '';
}
})->align('center');
$grid->column('type', admin_trans('player_delivery_record.fields.type'))
->display(function ($value) {
switch ($value) {
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD))->color('#2db7f5');
break;
case PlayerDeliveryRecord::TYPE_RECHARGE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL))->color('#C98341');
break;
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT))->color('#108ee9');
break;
case PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_COMMISSION:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_COMMISSION))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_REGISTER_PRESENT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_REGISTER_PRESENT))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_SIGN:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_SIGN))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_GAME_IN:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_IN))->color('#CC6600');
break;
case PlayerDeliveryRecord::TYPE_GAME_OUT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_OUT))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_BET_REBATE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_BET_REBATE))->color('#C98341');
break;
case PlayerDeliveryRecord::TYPE_DAMAGE_REBATE:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_DAMAGE_REBATE))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_RECHARGE_REWARD:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE_REWARD))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_PROFIT:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_PROFIT))->color('#3C87C9');
break;
case PlayerDeliveryRecord::TYPE_CANCELTRANSFER:
$tag = Tag::create(admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_CANCELTRANSFER))->color('#3C87C9');
break;
default:
$tag = '';
}
return Html::create()->content([
$tag
]);
})->align('center')->sortable();
$grid->column('amount', admin_trans('player_delivery_record.fields.amount'))->display(function ($val, PlayerDeliveryRecord $data) {
switch ($data->type) {
case PlayerDeliveryRecord::TYPE_WITHDRAWAL:
case PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT:
return Html::create()->content(['-' . $val])->style(['color' => '#cd201f']);
default:
return Html::create()->content(['+' . $val])->style(['color' => 'green']);
}
})->align('center');
$grid->column('amount_after', admin_trans('player_delivery_record.fields.amount_after'))->align('center');
$grid->column('amount_before', admin_trans('player_delivery_record.fields.amount_before'))->align('center');
$grid->column('user_name', admin_trans('player_delivery_record.fields.user_name'))->display(function ($val, PlayerDeliveryRecord $data) {
$name = '玩家';
if (in_array($data->type, [PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD, PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT])) {
$name = $data->user_name ?? '管理员';
}
return Html::create()->content([
Html::div()->content($name),
]);
});
$grid->column('created_at', admin_trans('player_delivery_record.fields.created_at'))->sortable()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->like()->text('search_source')->placeholder(admin_trans('player_delivery_record.fields.source'));
$filter->eq()->select('type')
->placeholder(admin_trans('player_delivery_record.fields.type'))
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->options([
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD),
PlayerDeliveryRecord::TYPE_RECHARGE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE),
PlayerDeliveryRecord::TYPE_WITHDRAWAL => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL),
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT),
PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK),
PlayerDeliveryRecord::TYPE_REGISTER_PRESENT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_REGISTER_PRESENT),
PlayerDeliveryRecord::TYPE_COMMISSION => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_COMMISSION),
PlayerDeliveryRecord::TYPE_SIGN => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_SIGN),
PlayerDeliveryRecord::TYPE_GAME_OUT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_OUT),
PlayerDeliveryRecord::TYPE_GAME_IN => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_GAME_IN),
PlayerDeliveryRecord::TYPE_BET_REBATE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_BET_REBATE),
PlayerDeliveryRecord::TYPE_DAMAGE_REBATE => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_DAMAGE_REBATE),
PlayerDeliveryRecord::TYPE_RECHARGE_REWARD => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_RECHARGE_REWARD),
PlayerDeliveryRecord::TYPE_PROFIT => admin_trans('player_delivery_record.type.' . PlayerDeliveryRecord::TYPE_PROFIT),
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->quickSearch();
});
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace addons\webman\controller;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\support\Request;
/**
* 岗位管理
*/
class PostController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.post_model');
}
/**
* 岗位
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model, function (Grid $grid) {
$grid->title(admin_trans('post.title'));
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->column('name', admin_trans('post.fields.name'));
$grid->column('status', admin_trans('post.fields.status'))->switch([[1 => ''], [0 => '']]);
$grid->sortInput('sort', admin_trans('post.fields.sort'));
$grid->column('created_at', admin_trans('post.fields.create_at'));
$grid->filter(function (Filter $filter) {
$filter->like()->text('name')->placeholder(admin_trans('post.fields.name'));
$filter->eq()->select('status')
->placeholder(admin_trans('post.fields.status'))
->options([
1 => admin_trans('post.normal'),
0 => admin_trans('post.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->setForm()->modal($this->form());
$grid->quickSearch();
});
}
/**
* 岗位
* @auth true
*/
public function form(): Form
{
return Form::create(new $this->model, function (Form $form) {
$form->title(admin_trans('post.title'));
$form->text('name', admin_trans('post.fields.name'))
->required();
$form->number('sort', admin_trans('post.fields.sort'))->default(0);
});
}
}

View File

@@ -0,0 +1,400 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\Player;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerTag;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\detail\Detail;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\response\Response;
use ExAdmin\ui\support\Request;
use Illuminate\Support\Str;
use support\Cache;
/**
* 充值记录
*/
class RechargeRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_recharge_record_model');
}
/**
* 充值
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_recharge_record.title'));
$grid->model()->with(['player', 'channel', 'channel_recharge_setting', 'player.player_extend'])->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
if (!empty($exAdminFilter['player']['uuid'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('uuid', 'like', '%' . $exAdminFilter['player']['uuid'] . '%');
});
}
if (!empty($exAdminFilter['player']['name'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('name', 'like', '%' . $exAdminFilter['player']['name'] . '%');
});
}
if (!empty($exAdminFilter['department_id'])) {
$grid->model()->where('department_id', $exAdminFilter['department_id']);
}
if (!empty($exAdminFilter['type'])) {
$grid->model()->where('type', $exAdminFilter['type']);
}
if (isset($exAdminFilter['status']) && (!empty($exAdminFilter['status']) || $exAdminFilter['status'] === 0)) {
$grid->model()->where('status', $exAdminFilter['status']);
}
if (!empty($exAdminFilter['tradeno'])) {
$grid->model()->where('tradeno', $exAdminFilter['tradeno']);
}
}
$query = clone $grid->model();
$totalData = $query->selectRaw(
"ifNull(sum(IF(type = 4, money,0)), 0) as total_artificial_money,
ifNull(sum(IF(type = 1, money,0)), 0) as total_espay_money,
ifNull(sum(IF(payment_method = 'DUITNOWP2P', money,0)), 0) as total_espay_duitnow_money,
ifNull(sum(IF(payment_method = 'P2PDEPOSIT', money,0)), 0) as total_espay_deposit_money,
ifNull(sum(IF(payment_method = 'duitnowqr', money,0)), 0) as total_onepay_duitnow_money,
ifNull(sum(IF(payment_method = 'online_banking', money,0)), 0) as total_onepay_deposit_money,
ifNull(sum(IF(payment_method = 'QR', money,0)), 0) as total_skl_duitnow_money,
ifNull(sum(IF(payment_method = 'P2P', money,0)), 0) as total_skl_deposit_money"
)->first();
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_artificial_money'))
->value(!empty($totalData['total_artificial_money']) ? floatval($totalData['total_artificial_money']) : 0)->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_espay_money'))
->value(!empty($totalData['total_espay_money']) ? floatval($totalData['total_espay_money']) : 0)->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_recharge_record.total_data.total_espay_inmoney'))
->value(bcadd(bcadd(
bcadd(bcmul($totalData['total_espay_duitnow_money'], 0.97, 3), bcmul($totalData['total_espay_deposit_money'], 0.985, 3), 3),
bcadd(bcmul($totalData['total_onepay_duitnow_money'], 0.984, 3), bcmul($totalData['total_onepay_deposit_money'], 0.986, 3), 3),
3), bcadd(bcmul($totalData['total_skl_duitnow_money'], 0.987, 3), bcmul($totalData['total_skl_deposit_money'], 0.989, 3), 3), 3))
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
})->style(['background' => '#fff']);
$grid->header($layout);
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('player_recharge_record.fields.id'))->align('center')->fixed(true);
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerRechargeRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
])->style(['cursor' => 'pointer'])->modal($this->playerDetail([
'phone' => $data->player->phone ?? '',
'name' => $data->player->name ?? '',
'address' => $data->player->player_extend->address ?? '',
'email' => $data->player->player_extend->email ?? '',
'line' => $data->player->player_extend->line ?? '',
'created_at' => $data->player->created_at ? date('Y-m-d H:i:s', strtotime($data->player->created_at)) : '',
]));
})->align('center')->fixed(true);
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->display(function ($val, PlayerRechargeRecord $data) {
return $data->player->uuid;
})->align('center')->fixed(true);
$grid->column('tradeno', admin_trans('player_recharge_record.fields.tradeno'))->copy();
$grid->column('channel.name', admin_trans('player_recharge_record.fields.department_id'))->align('center');
$grid->column('type', admin_trans('player_recharge_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerRechargeRecord::TYPE_REGULAR:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#55acee');
case PlayerRechargeRecord::TYPE_ACTIVITY:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#3b5999');
case PlayerRechargeRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_recharge_record.type.' . $val))
->color('#cd201f');
default:
return '';
}
})->align('center');
$grid->column('status', admin_trans('player_recharge_record.fields.status'))->display(function ($val, PlayerRechargeRecord $data) {
switch ($val) {
case PlayerRechargeRecord::STATUS_WAIT:
return Tag::create(admin_trans('player_recharge_record.status_wait'))
->color('#108ee9');
case PlayerRechargeRecord::STATUS_RECHARGING:
return Tag::create(admin_trans('player_recharge_record.status_examine'))
->color('#3b5999');
case PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS:
return Tag::create(admin_trans('player_recharge_record.status_success'))
->color('#87d068');
case PlayerRechargeRecord::STATUS_RECHARGED_FAIL:
return Tag::create(admin_trans('player_recharge_record.status_fail'))
->color('#f50');
case PlayerRechargeRecord::STATUS_RECHARGED_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_cancel'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_REJECT:
return Tag::create(admin_trans('player_recharge_record.status_reject'))
->color('#2db7f5');
case PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL:
return Tag::create(admin_trans('player_recharge_record.status_system_cancel'))
->color('#2db7f5');
default:
return '';
}
})->align('center');
$grid->column('money', admin_trans('player_recharge_record.fields.money'))->display(function ($val, PlayerRechargeRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
})->align('center');
$grid->column('inmoney', admin_trans('player_recharge_record.fields.inmoney'))->display(function ($val, PlayerRechargeRecord $data) {
if ($data->payment_method == 'DUITNOWP2P') {
$ratio = 0.97;
} elseif ($data->payment_method == 'P2PDEPOSIT') {
$ratio = 0.985;
} elseif ($data->payment_method == 'duitnowqr') {
$ratio = 0.984;
} elseif ($data->payment_method == 'online_banking') {
$ratio = 0.986;
} elseif ($data->payment_method == 'P2P') {
$ratio = 0.989;
} elseif ($data->payment_method == 'QR') {
$ratio = 0.987;
} else {
$ratio = 1;
}
if ($data->currency == 'USDT') {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
}
return $data->money * $ratio . ' ' . ($data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_recharge_record.fields.coins'))->align('center')->sortable();
$grid->column('player_tag', admin_trans('player_recharge_record.fields.player_tag'))
->display(function ($value) {
return $this->handleTagIds($value);
})
->editable(
Editable::checkboxTag()
->options($this->getPlayerTagOptionsFilter())
)->width('150px');
$grid->column('remark', admin_trans('player_recharge_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_recharge_record.fields.remark')])
)->width('150px')->align('center');
$grid->column('finish_time', admin_trans('player_recharge_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_recharge_record.fields.created_at'))->sortable()->align('center')->fixed('right');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.department_id'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.type'))
->options([
PlayerRechargeRecord::TYPE_REGULAR => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_REGULAR),
PlayerRechargeRecord::TYPE_ARTIFICIAL => admin_trans('player_recharge_record.type.' . PlayerRechargeRecord::TYPE_ARTIFICIAL),
]);
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_recharge_record.fields.status'))
->options([
PlayerRechargeRecord::STATUS_WAIT => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_WAIT),
PlayerRechargeRecord::STATUS_RECHARGING => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGING),
PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_SUCCESS),
PlayerRechargeRecord::STATUS_RECHARGED_FAIL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_FAIL),
PlayerRechargeRecord::STATUS_RECHARGED_CANCEL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_CANCEL),
PlayerRechargeRecord::STATUS_RECHARGED_REJECT => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_REJECT),
PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL => admin_trans('player_recharge_record.status.' . PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_recharge_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_recharge_record.fields.finish_time'), admin_trans('player_recharge_record.fields.finish_time')]);
});
});
}
/**
* 处理标签
* @param array $value
* @return Html
*/
public function handleTagIds(array $value): Html
{
$options = $this->getPlayerTagOptions($value);
$html = Html::create();
foreach ($options as $option) {
$html->content(
Tag::create($option)
->color('success')
);
}
return $html;
}
/**
* 获取玩家标签选项(筛选id)
* @param array $ids
* @return array
*/
public function getPlayerTagOptions(array $ids = []): array
{
$idsStr = json_encode($ids);
$cacheKey = md5("player_tag_options_ids_$idsStr");
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
if (!empty($ids)) {
$data = (new PlayerTag())->whereIn('id', $ids)->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
return [];
}
}
/**
* 获取玩家标签(筛选id)
* @return array
*/
public function getPlayerTagOptionsFilter(): array
{
$cacheKey = "doc_player_tag_options_filter";
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
$data = (new PlayerTag())->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
}
/**
* 筛选玩家下拉
* @return mixed
*/
public function getPlayerOptions()
{
$request = Request::input();
$player = Player::orderBy('created_at', 'desc')
->forPage(1, 20);
if (!empty($request['search'])) {
$player->where('phone', 'like', '%' . $request['search'] . '%');
}
$playerList = $player->get();
$data = [];
/** @var Player $player */
foreach ($playerList as $player) {
$data[] = [
'value' => $player->id,
'label' => $player->phone,
];
}
return Response::success($data);
}
/**
* 玩家详情
* @param array $data
* @return Detail
*/
public function playerDetail(array $data): Detail
{
return Detail::create($data, function (Detail $detail) {
$detail->item('name', admin_trans('player.fields.name'));
$detail->item('address', admin_trans('player_extend.fields.address'));
$detail->item('email', admin_trans('player_extend.fields.email'));
$detail->item('phone', admin_trans('player.fields.phone'));
$detail->item('line', admin_trans('player_extend.fields.line'));
$detail->item('created_at', admin_trans('player.fields.created_at'));
})->layout('vertical');
}
}

View File

@@ -0,0 +1,344 @@
<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\model\AdminDepartment;
use addons\webman\model\AdminRole;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tag\Tag;
/**
* 系统角色
*/
class RoleController
{
public function __construct()
{
$this->model = plugin()->webman->config('database.role_model');
}
/**
* 系统角色
* @auth true
* @return Grid
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('auth.title'));
$grid->autoHeight();
$grid->column('name', admin_trans('auth.fields.name'));
$grid->column('type', admin_trans('auth.fields.type'))
->display(function ($value) {
$tag = '';
switch ($value) {
case AdminDepartment::TYPE_DEPARTMENT:
$tag = Tag::create(admin_trans('auth.type.' . AdminDepartment::TYPE_DEPARTMENT))->color('#108ee9');
break;
case AdminDepartment::TYPE_CHANNEL:
$tag = Tag::create(admin_trans('auth.type.' . AdminDepartment::TYPE_CHANNEL))->color('#f50');
break;
}
return Html::create()->content([
$tag
]);
})->sortable();
$grid->hideSelection();
$grid->column('desc', admin_trans('auth.fields.desc'));
$grid->column('data_type', admin_trans('auth.fields.data_type'))
->display(function ($value, AdminRole $data) {
$tag = '';
switch ($value) {
case AdminRole::DATA_TYPE_ALL:
$tag = Tag::create(admin_trans('auth.options.data_type.full_data_rights'))->color('#f50');
break;
case AdminRole::DATA_TYPE_CUSTOM:
$tag = Tag::create(admin_trans('auth.options.data_type.custom_data_permissions'))->color('#2db7f5');
break;
case AdminRole::DATA_TYPE_DEPARTMENT_BELOW:
$tag = Tag::create(admin_trans('auth.options.data_type.this_department_and_the_following_data_permissions'))->color('#87d068');
if ($data->type == AdminDepartment::TYPE_CHANNEL) {
$tag = Tag::create(admin_trans('auth.options.data_type.channel_and_the_following_data_permissions'))->color('#87d068');
}
break;
case AdminRole::DATA_TYPE_DEPARTMENT:
$tag = Tag::create(admin_trans('auth.options.data_type.data_permissions_for_this_department'))->color('#108ee9');
break;
case AdminRole::DATA_TYPE_SELF:
$tag = Tag::create(admin_trans('auth.options.data_type.personal_data_rights'))->color('#108ee9');
break;
}
return Html::create()->content([
$tag
]);
})->sortable();
$grid->setForm()->modal($this->form());
$grid->quickSearch();
$grid->actions(function (Actions $actions, AdminRole $data) {
$dropdown = $actions->dropdown();
$dropdown->prepend(admin_trans('auth.auth_grant'), 'safety-certificate-filled')
->modal($this->auth($data['id'], $data['type']));
$dropdown->prepend(admin_trans('auth.menu_grant'), 'appstore-filled')
->modal($this->menu($data['id'], $data['type']));
$dropdown->prepend(admin_trans('auth.data_grant'), 'fas fa-database')
->modal($this->data($data['id'], $data['type']));
if ($data->id == AdminRole::ROLE_CHANNEL) {
$actions->hideDel();
}
});
});
}
/**
* 系统角色
* @auth true
* @return Form
*/
public function form(): Form
{
return Form::create(new $this->model(), function (Form $form) {
$form->title(admin_trans('auth.title'));
$form->text('name', admin_trans('auth.fields.name'))->required();
$form->textarea('desc', admin_trans('auth.fields.desc'))->rows(5)->required();
$form->radio('type', admin_trans('auth.fields.type'))
->default(AdminDepartment::TYPE_DEPARTMENT)
->options([
AdminDepartment::TYPE_DEPARTMENT => admin_trans('auth.type.' . AdminDepartment::TYPE_DEPARTMENT),
AdminDepartment::TYPE_CHANNEL => admin_trans('auth.type.' . AdminDepartment::TYPE_CHANNEL),
])->disabled($form->isEdit());
$form->number('sort', admin_trans('auth.fields.sort'))->default($this->model::max('sort') + 1);
$form->saving(function (Form $form) {
if (!$form->isEdit()) {
$type = $form->input('type');
switch ($type) {
case AdminDepartment::TYPE_DEPARTMENT:
$form->input('data_type', AdminRole::DATA_TYPE_ALL);
break;
case AdminDepartment::TYPE_CHANNEL:
$form->input('data_type', AdminRole::DATA_TYPE_DEPARTMENT_BELOW);
break;
default:
return message_error(admin_trans('auth.role_type_error'));
}
}
});
});
}
/**
* 数据权限
* @auth true
* @return Form
*/
public function data($id, $type)
{
return Form::create(new $this->model(), function (Form $form) use ($type) {
switch ($type) {
case AdminDepartment::TYPE_DEPARTMENT:
$options = [
0 => admin_trans('auth.options.data_type.full_data_rights'),
1 => admin_trans('auth.options.data_type.custom_data_permissions'),
2 => admin_trans('auth.options.data_type.this_department_and_the_following_data_permissions'),
3 => admin_trans('auth.options.data_type.data_permissions_for_this_department'),
4 => admin_trans('auth.options.data_type.personal_data_rights'),
];
break;
case AdminDepartment::TYPE_CHANNEL:
$options = [
2 => admin_trans('auth.options.data_type.channel_and_the_following_data_permissions'),
3 => admin_trans('auth.options.data_type.data_permissions_for_this_department'),
4 => admin_trans('auth.options.data_type.personal_data_rights'),
];
break;
default:
$options = [];
}
$form->title(admin_trans('auth.title'));
$form->desc('name', admin_trans('auth.fields.name'));
$form->desc('desc', admin_trans('auth.fields.desc'));
$form->select('data_type', admin_trans('auth.fields.data_type'))
->required()
->options($options)
->when(1, function (Form $form) {
$department = plugin()->webman->config('database.department_model');
$options = $department::where('status', 1)
->where('type', AdminDepartment::TYPE_DEPARTMENT)
->get()->toArray();
$tree = $form->tree('department')
->showIcon()
->content(Icon::create('FolderOutlined'), 'groupIcon')
->multiple()
->checkable()
->bindAttr('checkStrictly', $form->getModel() . '.check_strictly')
->options($options);
$form->popItem();
$form->switch('check_strictly', admin_trans('auth.fields.department'))
->default(false)
->checkedChildren(admin_trans('auth.father_son_linkage'))
->unCheckedChildren(admin_trans('auth.father_son_linkage'))
->checkedValue(false)
->unCheckedValue(true)
->getFormItem()->content($tree);
});
});
}
/**
* 菜单权限
* @auth true
* @param $id
* @param $type
* @return Form
*/
public function menu($id, $type): Form
{
$menuModel = plugin()->webman->config('database.menu_model');
$tree = $menuModel::select('id', 'pid', 'name')->where('type', $type)->get()->toArray();
$model = plugin()->webman->config('database.role_menu_model');
$field = 'menu_id';
$label = 'name';
$nodeTypeList = [];
foreach ($tree as $value) {
if (!empty($value['group'])) {
/** 全部菜单 */
if ($value['group'] == 'all') {
$nodeTypeList[] = $value;
}
/** 渠道菜单,总站菜单 */
if ($value['group'] == ($type == AdminDepartment::TYPE_CHANNEL ? 'channel' : 'department')) {
$nodeTypeList[] = $value;
}
} else {
$nodeTypeList[] = $value;
}
}
array_unshift($nodeTypeList, ['id' => 0, $label => admin_trans('auth.all'), 'pid' => -1]);
$auths = $model::where('role_id', $id)->pluck($field);
return Form::create(new $this->model(), function (Form $form) use ($id, $model, $nodeTypeList, $field, $auths, $label) {
$form->tree('auth')
->options($nodeTypeList, $label)
->default($auths)
->checkable();
$form->saving(function (Form $form) use ($id, $model, $field) {
$auths = $form->input('auth');
$form->removeInput('auth');
$auths = array_filter($auths);
$auths = array_map(function ($item) use ($id, $field) {
return ['role_id' => $id, $field => $item];
}, $auths);
$model::where('role_id', $id)->delete();
if ($auths) {
$authsArr = array_chunk($auths, 10, true);
foreach ($authsArr as $value) {
$model::insert($value);
}
}
});
});
}
/**
* 功能权限
* @auth true
* @param $id
* @param string $type
* @return Form
*/
public function auth($id, string $type = ''): Form
{
$tree = Admin::node()->all();
$model = plugin()->webman->config('database.role_permission_model');
$field = 'node_id';
$label = 'title';
$nodeTypeList = [];
foreach ($tree as $value) {
if (!empty($value['group'])) {
/** 全部菜单 */
if ($value['group'] == 'all') {
$nodeTypeList[] = $value;
}
/** 渠道菜单,总站菜单 */
if ($value['group'] == ($type == AdminDepartment::TYPE_CHANNEL ? 'channel' : 'department')) {
$nodeTypeList[] = $value;
}
} else {
$nodeTypeList[] = $value;
}
}
array_unshift($nodeTypeList, ['id' => 0, $label => admin_trans('auth.all'), 'pid' => -1]);
$auths = $model::where('role_id', $id)->pluck($field);
return Form::create(new $this->model(), function (Form $form) use ($id, $model, $nodeTypeList, $field, $auths, $label) {
$form->tree('auth')
->options($nodeTypeList, $label)
->default($auths)
->checkable();
$form->saving(function (Form $form) use ($id, $model, $field) {
$auths = $form->input('auth');
$form->removeInput('auth');
$auths = array_filter($auths);
$auths = array_map(function ($item) use ($id, $field) {
return ['role_id' => $id, $field => $item];
}, $auths);
$model::where('role_id', $id)->delete();
if ($auths) {
$authsArr = array_chunk($auths, 10, true);
foreach ($authsArr as $value) {
$model::insert($value);
}
}
});
});
}
public function commonAuthForm($id, $model, $tree, $type, $field, $label): Form
{
$nodeTypeList = [];
foreach ($tree as $value) {
if (!empty($value['group'])) {
/** 全部菜单 */
if ($value['group'] == 'all') {
$nodeTypeList[] = $value;
}
/** 渠道菜单,总站菜单 */
if ($value['group'] == ($type == AdminDepartment::TYPE_CHANNEL ? 'channel' : 'department')) {
$nodeTypeList[] = $value;
}
} else {
$nodeTypeList[] = $value;
}
}
array_unshift($nodeTypeList, ['id' => 0, $label => admin_trans('auth.all'), 'pid' => -1]);
$auths = $model::where('role_id', $id)->pluck($field);
return Form::create(new $this->model(), function (Form $form) use ($id, $model, $nodeTypeList, $field, $auths, $label) {
$form->tree('auth')
->options($nodeTypeList, $label)
->default($auths)
->checkable();
$form->saving(function (Form $form) use ($id, $model, $field) {
$auths = $form->input('auth');
$form->removeInput('auth');
$auths = array_filter($auths);
$auths = array_map(function ($item) use ($id, $field) {
return ['role_id' => $id, $field => $item];
}, $auths);
$model::where('role_id', $id)->delete();
if ($auths) {
$authsArr = array_chunk($auths,10,true);
foreach ($authsArr as $value) {
$model::insert($value);
}
}
});
});
}
}

View File

@@ -0,0 +1,135 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\Channel;
use addons\webman\model\SystemSetting;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tabs\Tabs;
use Illuminate\Support\Str;
/**
* 系统配置
*/
class SystemSettingController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.system_setting_model');
}
/**
* 配置列表
* @auth true
* @return Card
*/
public function index(): Card
{
$tabs = Tabs::create()->destroyInactiveTabPane()
->type('card')
->pane(admin_trans('system_setting.master'), $this->settingList());
$channelList = Channel::get();
/** @var Channel $channel */
foreach ($channelList as $channel) {
$tabs->pane($channel->name, $this->settingList($channel->department_id));
}
return Card::create($tabs);
}
/**
* 系统配置
* @param $id
* @return Grid
*/
public function settingList($id = 0): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) use ($id) {
$grid->title(admin_trans('system_setting.title'));
$grid->autoHeight();
$grid->bordered(true);
$grid->model()->where('department_id', $id)->whereNotIn('feature', ['sign_setting', 'commission_setting', 'first_recharge_setting']);
$grid->column('feature', admin_trans('system_setting.fields.feature'))->display(function ($value) {
return admin_trans('system_setting.fields.' . $value);
})->align('center');
$grid->column('setting', admin_trans('system_setting.fields.setting'))
->if(function ($value, SystemSetting $data) {
return $data->feature === 'marquee' || $data->feature === 'machine_marquee';
})->editable(
Editable::textarea('content')
->showCount()
->rows(6)
->rule(['max:100' => admin_trans('system_setting.marquee_max_len')])
)->display(function ($value, SystemSetting $data) {
return Str::of($data->content)->limit(35, ' (...)');
})->width('20%')->align('center')
->if(function ($value, SystemSetting $data) { // 条件2
return $data->feature === 'register_present';
})->editable(
(new Editable)->text('num')
->rule([
'integer' => admin_trans('validator.integer'),
'max:10000' => admin_trans('validator.max', null, ['{max}' => 10000]),
'min:1' => admin_trans('validator.min', null, ['{min}' => 1]),
])
)->display(function ($value, SystemSetting $data) {
return $data->num;
})->align('center')
->if(function ($value, SystemSetting $data) { // 条件2
return $data->feature === 'recharge_order_expiration';
})->editable(
(new Editable)->text('num')
->rule([
'integer' => admin_trans('validator.integer'),
'max:180' => admin_trans('validator.max', null, ['{max}' => 180]),
'min:15' => admin_trans('validator.min', null, ['{min}' => 15]),
])->addonAfter(admin_trans('system_setting.minutes'))
)->display(function ($val, SystemSetting $data) {
if (!empty($data->num)) {
return $data->num . ' ' . admin_trans('system_setting.minutes');
}
return '';
})->if(function ($value, SystemSetting $data) { // 条件2
return $data->feature === 'pending_minutes';
})->editable(
(new Editable)->number('num')
->rule([
'integer' => admin_trans('validator.integer'),
'max:240' => admin_trans('validator.max', null, ['{max}' => 240]),
'min:2' => admin_trans('validator.min', null, ['{min}' => 2]),
])->addonAfter(admin_trans('system_setting.minutes'))
)->display(function ($val, SystemSetting $data) {
if (!empty($data->num)) {
return $data->num . ' ' . admin_trans('system_setting.minutes');
}
return '';
});
$grid->column('status', admin_trans('system_setting.fields.status'))->switch()->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
});
}
/**
* 结算日期
* @return array
*/
public function getSettlementDate(): array
{
for ($i = 1; $i <= 28; $i++) {
$data[$i] = $i . admin_trans('player_promoter.date');
}
return $data;
}
}

View File

@@ -0,0 +1,383 @@
<?php
namespace addons\webman\controller;
use addons\webman\model\PlayerTag;
use addons\webman\model\PlayerWithdrawRecord;
use ExAdmin\ui\component\common\Html;
use ExAdmin\ui\component\common\Icon;
use ExAdmin\ui\component\detail\Detail;
use ExAdmin\ui\component\grid\avatar\Avatar;
use ExAdmin\ui\component\grid\badge\Badge;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Actions;
use ExAdmin\ui\component\grid\grid\Editable;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\image\Image;
use ExAdmin\ui\component\grid\statistic\Statistic;
use ExAdmin\ui\component\grid\tag\Tag;
use ExAdmin\ui\component\grid\ToolTip;
use ExAdmin\ui\component\layout\layout\Layout;
use ExAdmin\ui\component\layout\Row;
use ExAdmin\ui\support\Request;
use Illuminate\Support\Str;
use support\Cache;
/**
* 提现记录
*/
class WithdrawRecordController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.player_withdraw_record_model');
}
/**
* 提現
* @auth true
*/
public function index(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->title(admin_trans('player_withdraw_record.title'));
$grid->model()->with(['player', 'channel', 'player.player_extend'])->orderBy('created_at', 'desc');
$exAdminFilter = Request::input('ex_admin_filter', []);
if (!empty($exAdminFilter)) {
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->where('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->where('created_at', '<=', $exAdminFilter['created_at_end']);
}
if (isset($exAdminFilter['finish_time_start']) && !empty($exAdminFilter['finish_time_start'])) {
$grid->model()->where('finish_time', '>=', $exAdminFilter['finish_time_start']);
}
if (isset($exAdminFilter['finish_time_end']) && !empty($exAdminFilter['finish_time_end'])) {
$grid->model()->where('finish_time', '<=', $exAdminFilter['finish_time_end']);
}
if (!empty($exAdminFilter['player']['uuid'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('uuid', 'like', '%' . $exAdminFilter['player']['uuid'] . '%');
});
}
if (!empty($exAdminFilter['player']['name'])) {
$grid->model()->whereHas('player', function ($query) use ($exAdminFilter) {
$query->where('name', 'like', '%' . $exAdminFilter['player']['name'] . '%');
});
}
if (!empty($exAdminFilter['department_id'])) {
$grid->model()->where('department_id', $exAdminFilter['department_id']);
}
if (!empty($exAdminFilter['type'])) {
$grid->model()->where('type', $exAdminFilter['type']);
}
if (!empty($exAdminFilter['status'])) {
$grid->model()->where('status', $exAdminFilter['status']);
}
if (!empty($exAdminFilter['tradeno'])) {
$grid->model()->where('tradeno', $exAdminFilter['tradeno']);
}
}
$query = clone $grid->model();
$totalData = $query->selectRaw(
'ifNull(sum(money), 0) as total_money,
ifNull(sum(IF(type = 6, money,0)), 0) as total_skl_money'
)->first();
$layout = Layout::create();
$layout->row(function (Row $row) use ($totalData) {
$row->gutter([10, 0]);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_withdraw_record.total_money'))
->value($totalData['total_money'])
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
$row->column(
Card::create([
Row::create()->column(Statistic::create()->title(admin_trans('player_withdraw_record.total_inmoney'))
->value(bcadd(bcsub($totalData['total_money'], $totalData['total_skl_money'], 3), bcmul($totalData['total_skl_money'], 1.008, 3), 3))
->style([
'font-size' => '15px',
'text-align' => 'center'
])),
])->bodyStyle([
'display' => 'flex',
'align-items' => 'center',
'height' => '72px'
])->hoverable()->headStyle(['height' => '0px', 'border-bottom' => '0px', 'min-height' => '0px'])
, 8);
})->style(['background' => '#fff']);
$grid->header($layout);
$grid->bordered(true);
$grid->autoHeight();
$grid->column('id', admin_trans('player_withdraw_record.fields.id'))->align('center')->fixed(true);
$grid->column('player.name', admin_trans('player.fields.name'))->display(function ($val, PlayerWithdrawRecord $data) {
$image = (isset($data->player->avatar) && !empty($data->player->avatar)) ? Avatar::create()->src($data->player->avatar) : Avatar::create()->icon(Icon::create('UserOutlined'));
return Html::create()->content([
$image,
Html::div()->content($val)
])->style(['cursor' => 'pointer'])->modal($this->playerDetail([
'phone' => $data->player->phone ?? '',
'name' => $data->player->name ?? '',
'address' => $data->player->player_extend->address ?? '',
'email' => $data->player->player_extend->email ?? '',
'line' => $data->player->player_extend->line ?? '',
'created_at' => isset($data->player->created_at) && !empty($data->player->created_at) ? date('Y-m-d H:i:s', strtotime($data->player->created_at)) : '',
]));
})->align('center')->fixed(true);
$grid->column('player.uuid', admin_trans('player.fields.uuid'))->display(function ($val, PlayerWithdrawRecord $data) {
return $data->player->uuid;
})->align('center')->fixed(true);
$grid->column('tradeno', admin_trans('player_withdraw_record.fields.tradeno'))->copy()->align('center');
$grid->column('money', admin_trans('player_withdraw_record.fields.money'))->display(function ($val, PlayerWithdrawRecord $data) {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency == 'TALK' ? 'Q币' : $data->currency);
})->align('center')->sortable();
$grid->column('inmoney', admin_trans('player_recharge_record.fields.inmoney'))->display(function ($val, PlayerWithdrawRecord $data) {
if ($data->type == PlayerWithdrawRecord::TYPE_ESPAYOUT) {
$ratio = 1.005;
} elseif ($data->type == PlayerWithdrawRecord::TYPE_ONEPAYOUT){
$ratio = 1.008;
} elseif ($data->type == PlayerWithdrawRecord::TYPE_SKLPAYOUT){
$ratio = 1.008;
} else {
$ratio = 1;
}
if ($data->currency == 'USDT') {
return bcdiv($val,$data->rate, 2) . ' ' . ($data->currency);
}
return $data->money * $ratio . ' ' . ($data->currency);
})->align('center');
$grid->column('coins', admin_trans('player_withdraw_record.fields.coins'))->align('center');
$grid->column('type', admin_trans('player_withdraw_record.fields.type'))->display(function ($val) {
switch ($val) {
case PlayerWithdrawRecord::TYPE_SELF:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#3b5999');
case PlayerWithdrawRecord::TYPE_ARTIFICIAL:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#cd201f');
case PlayerWithdrawRecord::TYPE_USDT:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#2db7f5');
case PlayerWithdrawRecord::TYPE_SKLPAYOUT:
return Tag::create(admin_trans('player_withdraw_record.type.' . $val))
->color('#108ee9');
default:
return '';
}
})->align('center');
$grid->column('withdraw_setting_info',
admin_trans('player_withdraw_record.player_bank'))->display(function (
$val,
PlayerWithdrawRecord $data
) {
$info = [];
switch ($data->type) {
case PlayerWithdrawRecord::TYPE_USDT:
$info[] = Html::markdown('- ' . admin_trans('channel_recharge_setting.fields.wallet_address') . ': ' . $data->wallet_address);
$info[] = Html::div()->content(Image::create()
->width(40)
->src($data->qr_code));
break;
case PlayerWithdrawRecord::TYPE_SELF:
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account_name') . ': ' . $data->account_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.bank_name') . ': ' . $data->bank_name);
$info[] = Html::markdown('- ' . admin_trans('player_withdraw_record.fields.account') . ': ' . $data->account);
break;
}
return Html::create()->content($info);
})->align('left');
$grid->column('status', admin_trans('player_withdraw_record.fields.status'))
->display(function ($value, PlayerWithdrawRecord $data) {
$rejectReason = $data->reject_reason;
switch ($value) {
case PlayerWithdrawRecord::STATUS_SUCCESS:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS))->color('#87d068');
break;
case PlayerWithdrawRecord::STATUS_WAIT:
$tag = Tag::create(admin_trans('player_withdraw_record.status_wait'))->color('#108ee9');
break;
case PlayerWithdrawRecord::STATUS_FAIL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL))->color('#f50');
break;
case PlayerWithdrawRecord::STATUS_PENDING_REJECT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT))->color('#cd201f');
break;
case PlayerWithdrawRecord::STATUS_PENDING_PAYMENT:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT))->color('#3b5999');
break;
case PlayerWithdrawRecord::STATUS_CANCEL:
case PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL:
$tag = Tag::create(admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL))->color('#2db7f5');
break;
default:
$tag = '';
}
if (!empty($rejectReason)) {
return ToolTip::create(Badge::create(
$tag
)->count('!')->title(''))->title($rejectReason)->color('orange');
} else {
return $tag;
}
})->align('center')->sortable();
$grid->column('channel.name', admin_trans('player_withdraw_record.fields.department_id'))->align('center');
$grid->column('finish_time', admin_trans('player_withdraw_record.fields.finish_time'))->sortable()->align('center');
$grid->column('created_at', admin_trans('player_withdraw_record.fields.created_at'))->sortable()->align('center');
$grid->column('player_tag', admin_trans('player_withdraw_record.fields.player_tag'))
->display(function ($value) {
return $this->handleTagIds($value);
})
->editable(
Editable::checkboxTag()
->options($this->getPlayerTagOptionsFilter())
)->width('150px');
$grid->column('remark', admin_trans('player_withdraw_record.fields.remark'))->display(function ($value) {
return Str::of($value)->limit(20, ' (...)');
})->editable(
(new Editable)->textarea('remark')
->showCount()
->rows(5)
->rule(['max:255' => admin_trans('player_withdraw_record.fields.remark')])
)->width('150px')->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->expandFilter();
$grid->actions(function (Actions $actions) {
$actions->hideDel();
$actions->hideEdit();
});
$grid->filter(function (Filter $filter) {
$filter->like()->text('player.uuid')->placeholder(admin_trans('player.fields.uuid'));
$filter->like()->text('player.name')->placeholder(admin_trans('player.fields.name'));
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.department_id'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->eq()->select('type')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.type'))
->options([
PlayerWithdrawRecord::TYPE_USDT => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_USDT),
PlayerWithdrawRecord::TYPE_SELF => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_SELF),
PlayerWithdrawRecord::TYPE_ARTIFICIAL => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_ARTIFICIAL),
PlayerWithdrawRecord::TYPE_SKLPAYOUT => admin_trans('player_withdraw_record.type.' . PlayerWithdrawRecord::TYPE_SKLPAYOUT),
]);
$filter->eq()->select('status')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('player_withdraw_record.fields.status'))
->options([
PlayerWithdrawRecord::STATUS_WAIT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_WAIT),
PlayerWithdrawRecord::STATUS_SUCCESS => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SUCCESS),
PlayerWithdrawRecord::STATUS_FAIL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_FAIL),
PlayerWithdrawRecord::STATUS_PENDING_PAYMENT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_PAYMENT),
PlayerWithdrawRecord::STATUS_PENDING_REJECT => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_PENDING_REJECT),
PlayerWithdrawRecord::STATUS_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_CANCEL),
PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL => admin_trans('player_withdraw_record.status.' . PlayerWithdrawRecord::STATUS_SYSTEM_CANCEL),
]);
$filter->like()->text('tradeno')->placeholder(admin_trans('player_withdraw_record.fields.tradeno'));
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateTimeRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
$filter->form()->hidden('finish_time_start');
$filter->form()->hidden('finish_time_end');
$filter->form()->dateTimeRange('finish_time_start', 'finish_time_end', '')->placeholder([admin_trans('player_withdraw_record.fields.finish_time'), admin_trans('player_withdraw_record.fields.finish_time')]);
});
});
}
/**
* 处理标签
* @param array $value
* @return Html
*/
public function handleTagIds(array $value): Html
{
$options = $this->getPlayerTagOptions($value);
$html = Html::create();
foreach ($options as $option) {
$html->content(
Tag::create($option)
->color('success')
);
}
return $html;
}
/**
* 获取玩家标签选项(筛选id)
* @param array $ids
* @return array
*/
public function getPlayerTagOptions(array $ids = []): array
{
$idsStr = json_encode($ids);
$cacheKey = md5("player_tag_options_ids_$idsStr");
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
if (!empty($ids)) {
$data = (new PlayerTag())->whereIn('id', $ids)->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
return [];
}
}
/**
* 获取玩家标签(筛选id)
* @return array
*/
public function getPlayerTagOptionsFilter(): array
{
$cacheKey = "doc_player_tag_options_filter";
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
} else {
$data = (new PlayerTag())->select(['name', 'id'])->get()->toArray();
$data = $data ? array_column($data, 'name', 'id') : [];
Cache::set($cacheKey, $data, 24 * 60 * 60);
return $data;
}
}
/**
* 玩家详情
* @param array $data
* @return Detail
*/
public function playerDetail(array $data): Detail
{
return Detail::create($data, function (Detail $detail) {
$detail->item('name', admin_trans('player.fields.name'));
$detail->item('address', admin_trans('player_extend.fields.address'));
$detail->item('email', admin_trans('player_extend.fields.email'));
$detail->item('phone', admin_trans('player.fields.phone'));
$detail->item('line', admin_trans('player_extend.fields.line'));
$detail->item('created_at', admin_trans('player.fields.created_at'));
})->layout('vertical');
}
}