generated from liutk/owl-admin-base
admin 员工管理
parent
46fd4ce365
commit
c05cceda49
|
|
@ -1,3 +1,5 @@
|
|||
# 彩票门店管理
|
||||
|
||||
composer install
|
||||
php artisan g:k
|
||||
php artisan storage:link
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\EmployeeService;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use App\Enums\EmployeeStatus;
|
||||
|
||||
class EmployeeController extends AdminController
|
||||
{
|
||||
protected string $serviceName = EmployeeService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createButton(true),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amisMake()->TextControl()->name('name')->label(__('employee.name'))->columnRatio(3)->clearable(),
|
||||
amisMake()->TextControl()->name('phone')->label(__('employee.phone'))->columnRatio(3)->clearable(),
|
||||
amisMake()->SelectControl()->name('employee_status')->label(__('employee.employee_status'))->columnRatio(3)->clearable()->options(EmployeeStatus::options()),
|
||||
]),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('employee.id')),
|
||||
amisMake()->TableColumn()->name('name')->label(__('employee.name')),
|
||||
amisMake()->TableColumn()->name('phone')->label(__('employee.phone')),
|
||||
amisMake()->TableColumn()->name('employee_status_text')->label(__('employee.employee_status')),
|
||||
amisMake()->TableColumn()->name('created_at')->label(__('employee.created_at')),
|
||||
$this->rowActions([
|
||||
$this->rowShowButton(),
|
||||
$this->rowEditButton(true),
|
||||
$this->rowDeleteButton(),
|
||||
]),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form($edit): Form
|
||||
{
|
||||
return $this->baseForm()->title('')->body([
|
||||
amisMake()->TextControl()->name('name')->label(__('employee.name'))->required(),
|
||||
amisMake()->TextControl()->name('phone')->label(__('employee.phone'))->required(),
|
||||
|
||||
amisMake()->TextControl()->name('username')->label(__('admin.username'))->value('${admin_user.username}')->required(!$edit),
|
||||
amisMake()->TextControl()->name('password')->set('type', 'input-password')->label(__('admin.password'))->required(!$edit),
|
||||
amisMake()->TextControl()->name('confirm_password')->set('type', 'input-password')->label(__('admin.confirm_password'))->required(!$edit),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->title('')->body(amisMake()->Property()->items([
|
||||
['label' => __('employee.name'), 'content' => '${name}'],
|
||||
['label' => __('employee.phone'), 'content' => '${phone}'],
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
@ -40,4 +40,7 @@ Route::group([
|
|||
$router->post('start_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'startChunk']);
|
||||
$router->post('save_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'saveChunk']);
|
||||
$router->post('finish_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'finishChunk']);
|
||||
|
||||
// 员工管理
|
||||
$router->resource('employees', \App\Admin\Controllers\EmployeeController::class);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ModelFillable extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'model:fillable {table} {--connection}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'get model fillable ';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$table = $this->argument('table');
|
||||
$ignore = ['id', 'created_at', 'updated_at', 'deleted_at'];
|
||||
$connection = $this->option('connection');
|
||||
if (! $connection) {
|
||||
$connection = config('database.default');
|
||||
}
|
||||
|
||||
if (Schema::connection($connection)->hasTable($table)) {
|
||||
$list = Schema::connection($connection)->getColumnListing($table);
|
||||
$list = array_filter($list, function ($value) use ($ignore) {
|
||||
return ! in_array($value, $ignore);
|
||||
});
|
||||
$this->info("protected \$fillable = ['".implode('\', \'', $list)."'];");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum EmployeeStatus: int
|
||||
{
|
||||
case Online = 1;
|
||||
case Offline = 2;
|
||||
|
||||
public static function map()
|
||||
{
|
||||
return [
|
||||
self::Online->value => '在职',
|
||||
self::Offline->value => '离职',
|
||||
];
|
||||
}
|
||||
|
||||
public static function options()
|
||||
{
|
||||
$list = [];
|
||||
foreach (static::map() as $key => $value) {
|
||||
array_push($list, ['label' => $value, 'value' => $key]);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function text()
|
||||
{
|
||||
return data_get(self::map(), $this->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Enums\EmployeeStatus;
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 员工
|
||||
*/
|
||||
class Employee extends Model
|
||||
{
|
||||
use Filterable, HasDateTimeFormatter;
|
||||
|
||||
const JOB_KEY = 'job';
|
||||
|
||||
protected $fillable = ['name', 'phone', 'prize_images', 'skill_images', 'employee_status', 'admin_user_id'];
|
||||
|
||||
protected $casts = [
|
||||
'employee_status' => EmployeeStatus::class,
|
||||
'prize_images' => 'json',
|
||||
'skill_images' => 'json',
|
||||
];
|
||||
|
||||
protected $attributes = [
|
||||
'employee_status' => EmployeeStatus::Online,
|
||||
];
|
||||
|
||||
protected $appends = ['employee_status_text'];
|
||||
|
||||
// 拥有的职位
|
||||
public function jobs()
|
||||
{
|
||||
return $this->belongsToMany(Keyword::class, 'emplyee_jobs', 'employee_id', 'job');
|
||||
}
|
||||
|
||||
// 关联登录账户
|
||||
public function adminUser()
|
||||
{
|
||||
return $this->belongsTo(AdminUser::class, 'admin_user_id');
|
||||
}
|
||||
|
||||
protected function employeeStatusText(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => $this->employee_status ? $this->employee_status->text() : '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class EmployeeFilter extends ModelFilter
|
||||
{
|
||||
public function search($key)
|
||||
{
|
||||
$condition = '%'.$key.'%';
|
||||
$this->where(fn($q) => $q->where('name', 'like', $condition)->orWhere('phone', 'like', $condition));
|
||||
}
|
||||
|
||||
public function name($key)
|
||||
{
|
||||
$condition = '%'.$key.'%';
|
||||
$this->whereLike('name', $condition);
|
||||
}
|
||||
|
||||
public function phone($key)
|
||||
{
|
||||
$condition = '%'.$key.'%';
|
||||
$this->whereLike('phone', $condition);
|
||||
}
|
||||
|
||||
public function employeeStatus($key)
|
||||
{
|
||||
$this->whereIn('employee_status', is_array($key) ? $key : explode(',', $key));
|
||||
}
|
||||
}
|
||||
|
|
@ -55,4 +55,91 @@ class BaseService extends AdminService
|
|||
{
|
||||
return $this->query()->with($this->withRelationships)->find($id);
|
||||
}
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
$data = $this->resloveData($data);
|
||||
|
||||
$validate = $this->validate($data);
|
||||
if ($validate !== true) {
|
||||
$this->setError($validate);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->modelName::create($data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function update($primaryKey, $data): bool
|
||||
{
|
||||
$model = $this->query()->whereKey($primaryKey)->firstOrFail();
|
||||
$data = $this->resloveData($data, $model);
|
||||
$validate = $this->validate($data, $model);
|
||||
if ($validate !== true) {
|
||||
$this->setError($validate);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $model->update($data);
|
||||
}
|
||||
|
||||
public function delete(string $ids): mixed
|
||||
{
|
||||
$id = explode(',', $ids);
|
||||
$result = $this->preDelete($id);
|
||||
if ($result !== true) {
|
||||
$this->setError($result);
|
||||
return false;
|
||||
}
|
||||
return $this->query()->whereIn($this->primaryKey(), $id)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理表单数据
|
||||
*
|
||||
* @param array $data
|
||||
* @param Model $model 空 : 添加, 非空: 修改
|
||||
* @return array
|
||||
*/
|
||||
public function resloveData($data, $model = null)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单验证
|
||||
*
|
||||
* @param array $data
|
||||
* @param Model $model 空: 添加, 非空: 修改
|
||||
* @return mixed true: 验证通过, string: 错误提示
|
||||
*/
|
||||
public function validate($data, $model = null)
|
||||
{
|
||||
// $createRules = [
|
||||
// 'key' => ['required', Rule::unique('keywords', 'key')],
|
||||
// 'name' => ['required'],
|
||||
// ];
|
||||
// $updateRules = [
|
||||
// 'key' => [Rule::unique('keywords', 'key')->ignore($model->id)]
|
||||
// ];
|
||||
// $validator = Validator::make($data, $model ? $updateRules : $createRules, [
|
||||
// 'key.unique' => ':input 已经存在'
|
||||
// ]);
|
||||
// if ($validator->fails()) {
|
||||
// return $validator->errors()->first();
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除的前置方法
|
||||
*
|
||||
* @param array $ids 主键id
|
||||
* @return mixed true: 继续后续操作, string: 中断操作, 返回错误提示
|
||||
*/
|
||||
public function preDelete(array $ids)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\Employee;
|
||||
use App\Models\Filters\EmployeeFilter;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Slowlyo\OwlAdmin\Services\AdminUserService;
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class EmployeeService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = ['jobs', 'adminUser'];
|
||||
|
||||
protected string $modelName = Employee::class;
|
||||
|
||||
protected string $modelFilterName = EmployeeFilter::class;
|
||||
|
||||
public function getEditData($id): Model|\Illuminate\Database\Eloquent\Collection|Builder|array|null
|
||||
{
|
||||
$model = $this->getModel();
|
||||
|
||||
$hidden = collect([$model->getCreatedAtColumn(), $model->getUpdatedAtColumn()])
|
||||
->filter(fn($item) => $item !== null)
|
||||
->toArray();
|
||||
|
||||
return $this->query()->with(['adminUser'])->find($id)->makeHidden($hidden);
|
||||
}
|
||||
|
||||
public function resloveData($data, $model = null)
|
||||
{
|
||||
// 管理员信息
|
||||
$adminUserService = AdminUserService::make();
|
||||
if ($model) {
|
||||
// 修改管理员信息
|
||||
if (Arr::hasAny($data, ['username', 'password', 'confirm_password'])) {
|
||||
if (!$adminUserService->update($model->admin_user_id, Arr::only($data, ['username', 'password', 'confirm_password']))) {
|
||||
$this->setError($adminUserService->getError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 添加管理员信息
|
||||
if (!$adminUserService->store(Arr::only($data, ['username', 'password', 'confirm_password']))) {
|
||||
$this->setError($adminUserService->getError());
|
||||
return false;
|
||||
}
|
||||
$adminUser = AdminUser::where('username', $data['username'])->first();
|
||||
$data['admin_user_id'] = $adminUser->id;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function preDelete(array $ids)
|
||||
{
|
||||
// 删除管理员
|
||||
$adminUserIds = Employee::whereIn('id', $ids)->pluck('admin_user_id')->implode(',');
|
||||
$adminUserService = AdminUserService::make();
|
||||
if (!$adminUserService->delete($adminUserIds)) {
|
||||
$this->setError($adminUserService->getError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate($data, $model = null)
|
||||
{
|
||||
$createRules = [
|
||||
'name' => ['required'],
|
||||
'phone' => ['required'],
|
||||
];
|
||||
$updateRules = [];
|
||||
$validator = Validator::make($data, $model ? $updateRules : $createRules, [
|
||||
'name.required' => __('employee.name') . '必填',
|
||||
'phone.required' => __('employee.phone') . '必填',
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
return $validator->errors()->first();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
trait HasDateTimeFormatter
|
||||
{
|
||||
protected function serializeDate(\DateTimeInterface $date)
|
||||
{
|
||||
// protected $dateFormat = 'Y-m-d H:i:s';
|
||||
return $date->format($this->getDateFormat());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('employees', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('姓名');
|
||||
$table->string('phone')->comment('电话');
|
||||
$table->json('prize_images')->nullable()->comment('荣誉证书');
|
||||
$table->json('skill_images')->nullable()->comment('专业证书');
|
||||
$table->unsignedInteger('employee_status')->default(1)->comment('员工状态{1: 在职, 2: 离职}');
|
||||
$table->foreignId('admin_user_id')->comment('登录信息, 关联 admin_users.id');
|
||||
|
||||
$table->timestamps();
|
||||
|
||||
$table->comment('员工');
|
||||
});
|
||||
|
||||
Schema::create('emplyee_jobs', function (Blueprint $table) {
|
||||
$table->foreignId('employee_id');
|
||||
$table->string('job')->comment('职位, 字典表: keywords.job');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('employees');
|
||||
Schema::dropIfExists('emplyee_jobs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'created_at' => '创建时间',
|
||||
'updated_at' => '更新时间',
|
||||
|
||||
'name' => '姓名',
|
||||
'phone' => '电话',
|
||||
'prize_images' => '荣誉证书',
|
||||
'skill_images' => '专业证书',
|
||||
'employee_status' => '状态',
|
||||
'admin_user_id' => '关联账户',
|
||||
'jobs' => '职位',
|
||||
];
|
||||
|
|
@ -13,6 +13,4 @@ use Illuminate\Support\Facades\Route;
|
|||
|
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
Route::redirect('/', '/admin');
|
||||
|
|
|
|||
Loading…
Reference in New Issue