admin 员工管理

main
panliang 2024-03-22 12:28:58 +08:00
parent 46fd4ce365
commit c05cceda49
13 changed files with 481 additions and 3 deletions

View File

@ -1,3 +1,5 @@
# 彩票门店管理
composer install
php artisan g:k
php artisan storage:link

View File

@ -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}'],
]));
}
}

View File

@ -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);
});

View File

@ -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)."'];");
}
}
}

View File

@ -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);
}
}

View File

@ -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() : '',
);
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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');
}
};

View File

@ -0,0 +1,15 @@
<?php
return [
'id' => 'ID',
'created_at' => '创建时间',
'updated_at' => '更新时间',
'name' => '姓名',
'phone' => '电话',
'prize_images' => '荣誉证书',
'skill_images' => '专业证书',
'employee_status' => '状态',
'admin_user_id' => '关联账户',
'jobs' => '职位',
];

View File

@ -13,6 +13,4 @@ use Illuminate\Support\Facades\Route;
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::redirect('/', '/admin');