generated from liutk/owl-admin-base
admin 审核流程配置
parent
e32dd104f3
commit
afaa14d58d
|
|
@ -4,7 +4,7 @@ namespace App\Admin\Controllers\Store;
|
||||||
|
|
||||||
use App\Models\{Store, Employee};
|
use App\Models\{Store, Employee};
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Enums\{BusinessStatus, StoreRole};
|
use App\Enums\{BusinessStatus, StoreRole, EmployeeStatus};
|
||||||
use App\Admin\Services\StoreService;
|
use App\Admin\Services\StoreService;
|
||||||
use Slowlyo\OwlAdmin\Admin;
|
use Slowlyo\OwlAdmin\Admin;
|
||||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||||
|
|
@ -81,9 +81,10 @@ class StoreController extends AdminController
|
||||||
return $this->baseForm()->title('')->body([
|
return $this->baseForm()->title('')->body([
|
||||||
amisMake()->TextControl()->name('title')->label(__('store.title'))->required(),
|
amisMake()->TextControl()->name('title')->label(__('store.title'))->required(),
|
||||||
amisMake()->SelectControl()->name('master_id')->label(__('store.master_id'))
|
amisMake()->SelectControl()->name('master_id')->label(__('store.master_id'))
|
||||||
->source(admin_url('hr/employees?_action=getData'))
|
->source(admin_url('hr/employees?_action=getData&_all=1&employee_status=' . EmployeeStatus::Online->value))
|
||||||
->labelField('name')
|
->labelField('name')
|
||||||
->valueField('id')
|
->valueField('id')
|
||||||
|
->searchable()
|
||||||
->required(),
|
->required(),
|
||||||
amisMake()->TreeSelectControl()->name('category_id')->label(__('store.category_id'))
|
amisMake()->TreeSelectControl()->name('category_id')->label(__('store.category_id'))
|
||||||
->source(admin_url('api/keywords/tree-list?parent_key=store_category'))
|
->source(admin_url('api/keywords/tree-list?parent_key=store_category'))
|
||||||
|
|
@ -121,40 +122,4 @@ class StoreController extends AdminController
|
||||||
]);
|
]);
|
||||||
return $this->baseDetail()->title('')->body([$detail]);
|
return $this->baseDetail()->title('')->body([$detail]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function employees($id)
|
|
||||||
{
|
|
||||||
$store = Store::findOrFail($id);
|
|
||||||
$list = $store->employees()->wherePivot('role', StoreRole::Employee)->get();
|
|
||||||
return $this->response()->success($list);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function employeeAdd($id, Request $request)
|
|
||||||
{
|
|
||||||
$employees = $request->input('employees');
|
|
||||||
$store = Store::findOrFail($id);
|
|
||||||
$service = $this->service;
|
|
||||||
if ($service->attachEmployee($store, $employees)) {
|
|
||||||
return $this->response()->success();
|
|
||||||
}
|
|
||||||
return $this->response()->fail($service->getError());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function employeeDestroy($id, Request $request)
|
|
||||||
{
|
|
||||||
$employees = $request->input('employees');
|
|
||||||
$store = Store::findOrFail($id);
|
|
||||||
$service = $this->service;
|
|
||||||
if ($service->destroyEmployee($store, is_array($employees) ? $employees : explode(',', $employees))) {
|
|
||||||
return $this->response()->success();
|
|
||||||
}
|
|
||||||
return $this->response()->fail($service->getError());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function employeeOptions()
|
|
||||||
{
|
|
||||||
$ignore = DB::table('store_employees')->pluck('employee_id');
|
|
||||||
$list = Employee::select(['name as label', 'id as value', 'phone'])->whereNotIn('id', $ignore)->get();
|
|
||||||
return $this->response()->success($list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Admin\Controllers\System;
|
||||||
|
|
||||||
|
use Slowlyo\OwlAdmin\Admin;
|
||||||
|
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||||
|
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||||
|
use App\Admin\Controllers\AdminController;
|
||||||
|
use App\Admin\Services\WorkFlowService;
|
||||||
|
use App\Enums\CheckType;
|
||||||
|
use App\Models\{Keyword, Employee};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核流程管理
|
||||||
|
*/
|
||||||
|
class WorkflowController extends AdminController
|
||||||
|
{
|
||||||
|
protected string $serviceName = WorkFlowService::class;
|
||||||
|
|
||||||
|
protected $jobOptions;
|
||||||
|
protected $employeeOptions;
|
||||||
|
|
||||||
|
public function list(): Page
|
||||||
|
{
|
||||||
|
$crud = $this->baseCRUD()
|
||||||
|
->tableLayout('fixed')
|
||||||
|
->headerToolbar([
|
||||||
|
$this->createButton(),
|
||||||
|
...$this->baseHeaderToolBar(),
|
||||||
|
])
|
||||||
|
->bulkActions([])
|
||||||
|
->filter($this->baseFilter()->body([
|
||||||
|
amis()->GroupControl()->mode('horizontal')->body([
|
||||||
|
amisMake()->TextControl()->name('search')->label(__('admin.keyword'))->placeholder(__('workflow.key') . '/' . __('workflow.name'))->columnRatio(3)->clearable(),
|
||||||
|
])
|
||||||
|
]))
|
||||||
|
->columns([
|
||||||
|
amisMake()->TableColumn()->name('id')->label(__('workflow.id')),
|
||||||
|
amisMake()->TableColumn()->name('key')->label(__('workflow.key')),
|
||||||
|
amisMake()->TableColumn()->name('name')->label(__('workflow.name')),
|
||||||
|
$this->rowActions([
|
||||||
|
$this->rowShowButton(),
|
||||||
|
$this->rowEditButton(),
|
||||||
|
$this->rowDeleteButton(),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->baseList($crud);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form($edit): Form
|
||||||
|
{
|
||||||
|
return $this->baseForm()->title('')->body([
|
||||||
|
amisMake()->TextControl()->name('key')->label(__('workflow.key'))->required(),
|
||||||
|
amisMake()->TextControl()->name('name')->label(__('workflow.name'))->required(),
|
||||||
|
amisMake()->ArrayControl()->name('config')->label(__('workflow.config'))->items(amisMake()->ComboControl()->items([
|
||||||
|
amisMake()->SelectControl()->options(CheckType::options())->name('type')->label(__('workflow.type')),
|
||||||
|
amisMake()->SelectControl()
|
||||||
|
->options($this->getJobOptions())
|
||||||
|
->labelField('name')
|
||||||
|
->valueField('key')
|
||||||
|
->name('job')
|
||||||
|
// ->visibleOn('${config.type == '.CheckType::Job->value.'}')
|
||||||
|
->label(CheckType::Job->text()),
|
||||||
|
amisMake()->SelectControl()
|
||||||
|
->options($this->getEmployeeOptions())
|
||||||
|
->labelField('name')
|
||||||
|
->valueField('id')
|
||||||
|
->searchable()
|
||||||
|
->name('user')
|
||||||
|
// ->visibleOn('${config.type == '.CheckType::User->value.'}')
|
||||||
|
->label(CheckType::User->text()),
|
||||||
|
])),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function detail(): Form
|
||||||
|
{
|
||||||
|
$detail = amisMake()->Property()->items([
|
||||||
|
['label' => __('workflow.key'), 'content' => '${key}'],
|
||||||
|
['label' => __('workflow.name'), 'content' => '${name}'],
|
||||||
|
['label' => __('workflow.config'), 'content' => amisMake()->Steps()->labelPlacement('horizontal')->source('${config}'), 'span' => 3],
|
||||||
|
]);
|
||||||
|
return $this->baseDetail()->title('')->body($detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJobOptions()
|
||||||
|
{
|
||||||
|
if (!$this->jobOptions) {
|
||||||
|
$this->jobOptions = Keyword::where('parent_key', 'job')->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->jobOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmployeeOptions()
|
||||||
|
{
|
||||||
|
if (!$this->employeeOptions) {
|
||||||
|
$this->employeeOptions = Employee::enable()->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->employeeOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Admin\Services;
|
||||||
|
|
||||||
|
use App\Enums\CheckType;
|
||||||
|
use App\Models\{Workflow, Keyword, Employee};
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class WorkFlowService extends BaseService
|
||||||
|
{
|
||||||
|
protected array $withRelationships = [];
|
||||||
|
|
||||||
|
protected string $modelName = Workflow::class;
|
||||||
|
|
||||||
|
protected string $modelFilterName = '';
|
||||||
|
|
||||||
|
public function resloveData($data, $model = null)
|
||||||
|
{
|
||||||
|
if (isset($data['config'])) {
|
||||||
|
foreach($data['config'] as $key => &$item) {
|
||||||
|
$item['title'] = match($item['type']) {
|
||||||
|
CheckType::Job->value => CheckType::Job->text(),
|
||||||
|
CheckType::User->value => CheckType::User->text(),
|
||||||
|
};
|
||||||
|
$item['subTitle'] = match($item['type']) {
|
||||||
|
CheckType::Job->value => Keyword::where('key', $item['job'])->value('name'),
|
||||||
|
CheckType::User->value => Employee::where('id', $item['user'])->value('name'),
|
||||||
|
};
|
||||||
|
$item['value'] = match($item['type']) {
|
||||||
|
CheckType::Job->value => $item['job'],
|
||||||
|
CheckType::User->value => $item['user'],
|
||||||
|
};
|
||||||
|
$item['sort'] = $key + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate($data, $model = null)
|
||||||
|
{
|
||||||
|
$createRules = [
|
||||||
|
'key' => ['required', Rule::unique('workflows', 'key')],
|
||||||
|
'name' => ['required'],
|
||||||
|
];
|
||||||
|
$updateRules = [
|
||||||
|
'key' => [Rule::unique('workflows', 'key')->ignore($model?->id)]
|
||||||
|
];
|
||||||
|
$validator = Validator::make($data, $model ? $updateRules : $createRules, [
|
||||||
|
'key.unique' => ':input 已经存在'
|
||||||
|
]);
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return $validator->errors()->first();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ use App\Admin\Controllers\System\AdminRoleController;
|
||||||
use App\Admin\Controllers\System\AdminUserController;
|
use App\Admin\Controllers\System\AdminUserController;
|
||||||
use App\Admin\Controllers\BaseKeywordController;
|
use App\Admin\Controllers\BaseKeywordController;
|
||||||
use App\Admin\Controllers\System\KeywordController;
|
use App\Admin\Controllers\System\KeywordController;
|
||||||
|
use App\Admin\Controllers\System\WorkflowController;
|
||||||
use Illuminate\Routing\Router;
|
use Illuminate\Routing\Router;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
@ -98,6 +99,8 @@ Route::group([
|
||||||
$router->resource('settings', \App\Admin\Controllers\SettingController::class);
|
$router->resource('settings', \App\Admin\Controllers\SettingController::class);
|
||||||
// 数据字典
|
// 数据字典
|
||||||
$router->resource('keywords', KeywordController::class);
|
$router->resource('keywords', KeywordController::class);
|
||||||
|
|
||||||
|
$router->resource('workflows', WorkflowController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
$router->resource('articles', \App\Admin\Controllers\ArticleController::class);
|
$router->resource('articles', \App\Admin\Controllers\ArticleController::class);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Contracts;
|
||||||
|
|
||||||
|
interface Checkable
|
||||||
|
{
|
||||||
|
public function checkApply();
|
||||||
|
|
||||||
|
public function checkSuccess();
|
||||||
|
|
||||||
|
public function checkFail();
|
||||||
|
|
||||||
|
public function checkCancel();
|
||||||
|
|
||||||
|
public function getCheckKey();
|
||||||
|
|
||||||
|
public function workflows();
|
||||||
|
|
||||||
|
public function checkApplyPre();
|
||||||
|
|
||||||
|
public function checkSuccessPre();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
use Dcat\Admin\Admin;
|
||||||
|
|
||||||
|
enum CheckStatus: int
|
||||||
|
{
|
||||||
|
case None = 0;
|
||||||
|
case Processing = 1;
|
||||||
|
case Success = 2;
|
||||||
|
case Fail = 3;
|
||||||
|
case Cancel = 4;
|
||||||
|
|
||||||
|
public static function options(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
static::None->value => '未审核',
|
||||||
|
static::Processing->value => '审核中',
|
||||||
|
static::Success->value => '审核通过',
|
||||||
|
static::Fail->value => '审核不通过',
|
||||||
|
static::Cancel->value => '已取消',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function text()
|
||||||
|
{
|
||||||
|
return data_get(self::options(), $this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function coplorMap()
|
||||||
|
{
|
||||||
|
// 'active' | 'inactive' | 'error' | 'success' | 'processing' | 'warning' |
|
||||||
|
return [
|
||||||
|
static::None->value => 'active',
|
||||||
|
static::Processing->value => 'processing',
|
||||||
|
static::Success->value => 'success',
|
||||||
|
static::Fail->value => 'error',
|
||||||
|
static::Cancel->value => 'inactive',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function color()
|
||||||
|
{
|
||||||
|
return data_get(self::coplorMap(), $this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum CheckType: string
|
||||||
|
{
|
||||||
|
case Job = 'job';
|
||||||
|
case User = 'user';
|
||||||
|
|
||||||
|
public static function options()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
self::Job->value => '职务',
|
||||||
|
self::User->value => '员工',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function text()
|
||||||
|
{
|
||||||
|
return data_get(self::options(), $this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,6 +61,11 @@ class Employee extends Model
|
||||||
return $this->belongsToMany(Store::class, 'store_employees', 'employee_id', 'store_id')->withPivot(['role']);
|
return $this->belongsToMany(Store::class, 'store_employees', 'employee_id', 'store_id')->withPivot(['role']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeEnable($q)
|
||||||
|
{
|
||||||
|
return $q->where('employee_status', EmployeeStatus::Online);
|
||||||
|
}
|
||||||
|
|
||||||
protected function employeeStatusText(): Attribute
|
protected function employeeStatusText(): Attribute
|
||||||
{
|
{
|
||||||
return new Attribute(
|
return new Attribute(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核流程
|
||||||
|
*/
|
||||||
|
class Workflow extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['key', 'name', 'config'];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'config' => 'array'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class WorkflowLog extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['batch_id', 'check_type', 'check_value', 'check_name', 'user_id', 'subject_type', 'subject_id', 'subject_data', 'is_enable', 'check_user_id', 'checked_at', 'remarks', 'check_status', 'sort'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?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('workflows', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('key')->unique();
|
||||||
|
$table->string('name')->comment('名称');
|
||||||
|
$table->json('config')->nullable()->comment('流程配置{type,value,sort}');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->comment('审核流程');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('workflow_logs', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('batch_id')->comment('批次号(为同一批审核流程设置一个ID)');
|
||||||
|
$table->string('check_type')->comment('审核类型{job, user}');
|
||||||
|
$table->string('check_value')->comment('审核类型值');
|
||||||
|
$table->string('check_name')->comment('审核名称(展示用)');
|
||||||
|
$table->unsignedBigInteger('user_id')->comment('申请人(employees.id)');
|
||||||
|
$table->nullableMorphs('subject');
|
||||||
|
$table->json('subject_data')->nullable('审核内容');
|
||||||
|
$table->unsignedTinyInteger('is_enable')->default(0)->comment('操作状态(0: 不可操作, 1: 可操作)');
|
||||||
|
$table->unsignedBigInteger('check_user_id')->nullable()->comment('实际审核人(admin_users.id)');
|
||||||
|
$table->timestamp('checked_at')->nullable()->comment('审核时间');
|
||||||
|
$table->string('remarks')->nullable()->comment('审核备注');
|
||||||
|
$table->unsignedTinyInteger('check_status')->default(0)->comment('审核状态(0: 待审核, 1: 审核通过, 2: 审核不通过)');
|
||||||
|
$table->unsignedInteger('sort')->default(0)->comment('顺序(asc)');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->comment('审核流水');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('workflows');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -15,8 +15,8 @@ class AdminPermissionSeeder extends Seeder
|
||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
// AdminMenu::truncate();
|
AdminMenu::truncate();
|
||||||
// AdminPermission::truncate();
|
AdminPermission::truncate();
|
||||||
$data = [
|
$data = [
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
@ -168,6 +168,12 @@ class AdminPermissionSeeder extends Seeder
|
||||||
'resource' => ['list', 'create', 'update', 'delete'],
|
'resource' => ['list', 'create', 'update', 'delete'],
|
||||||
'children' => [],
|
'children' => [],
|
||||||
],
|
],
|
||||||
|
'workflows' => [
|
||||||
|
'name' => '审核流程',
|
||||||
|
'icon' => '',
|
||||||
|
'uri' => '/system/workflows',
|
||||||
|
'resource' => true,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\Workflow;
|
||||||
|
|
||||||
|
class WorkflowSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
Workflow::truncate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => 'ID',
|
||||||
|
'created_at' => '创建时间',
|
||||||
|
'updated_at' => '更新时间',
|
||||||
|
'key' => 'KEY',
|
||||||
|
'name' => '名称',
|
||||||
|
'config' => '流程配置',
|
||||||
|
'type' => '审核类型',
|
||||||
|
'value' => '审核人',
|
||||||
|
];
|
||||||
Loading…
Reference in New Issue