patient
parent
87a073b070
commit
1a2b30c0a4
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Admin\Components;
|
||||
use App\Admin\Services\KeywordService;
|
||||
use App\Models\Keyword;
|
||||
use Illuminate\Http\Request;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
|
||||
/**
|
||||
* 分类管理
|
||||
*/
|
||||
class CategoryController extends AdminController
|
||||
{
|
||||
protected string $serviceName = KeywordService::class;
|
||||
|
||||
protected string $typeKey = 'treat_type';
|
||||
|
||||
protected $parentId;
|
||||
|
||||
public function index()
|
||||
{
|
||||
if ($this->actionOfGetData()) {
|
||||
$list = Keyword::where('parent_id', $this->getParentId())->filter(request()->all(), $this->service->getModelFilter())->sort()->get();
|
||||
return $this->response()->success(['items' => $list]);
|
||||
}
|
||||
|
||||
if ($this->actionOfExport()) {
|
||||
return $this->export();
|
||||
}
|
||||
|
||||
return $this->response()->success($this->list());
|
||||
}
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->filterTogglable(false)
|
||||
->columnsTogglable(false)
|
||||
->loadDataOnce(true)
|
||||
->autoFillHeight(true)
|
||||
->footerToolbar([])
|
||||
->headerToolbar([
|
||||
$this->createButton(true),
|
||||
amis('reload')->align('right'),
|
||||
])
|
||||
->filter($this->baseFilter()->actions()->body([
|
||||
amisMake()->TextControl()->name('name')->label(__('category.name'))->size('md')->clearable(),
|
||||
// amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'),
|
||||
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('category.id')),
|
||||
amisMake()->TableColumn()->name('key')->label(__('category.key')),
|
||||
amisMake()->TableColumn()->name('name')->label(__('category.name')),
|
||||
// amisMake()->TableColumn()->name('content')->label(__('category.content')),
|
||||
amisMake()->TextareaControl()->static()->name('content')->label(__('category.content')),
|
||||
$this->rowActions(true),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->body([
|
||||
amisMake()->HiddenControl()->name('parent_id')->value($this->getParentId()),
|
||||
amisMake()->TextControl()->name('key')->label(__('category.key'))->required(true),
|
||||
amisMake()->TextControl()->name('name')->label(__('category.name'))->required(true),
|
||||
amisMake()->TextareaControl()->name('content')->label(__('category.content')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail()
|
||||
{
|
||||
return $this->baseDetail()->body([
|
||||
amisMake()->TextControl()->name('key')->label(__('category.key'))->static(true),
|
||||
amisMake()->TextControl()->name('name')->label(__('category.name'))->static(true),
|
||||
amisMake()->TextareaControl()->name('content')->label(__('category.content'))->static(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getParentId()
|
||||
{
|
||||
if (!$this->parentId) {
|
||||
$this->parentId = Keyword::where('key', $this->typeKey)->value('id');
|
||||
}
|
||||
return $this->parentId;
|
||||
}
|
||||
|
||||
public function getContent(Request $request)
|
||||
{
|
||||
$id = $request->input('id');
|
||||
$info = Keyword::find($id);
|
||||
$content = data_get($info, 'content');
|
||||
return $this->response()->success([
|
||||
'content' => $content
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Enums\Gender;
|
||||
use App\Admin\Components;
|
||||
use App\Admin\Services\PatientService;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use App\Models\Keyword;
|
||||
|
||||
/**
|
||||
* 病人管理
|
||||
*/
|
||||
class PatientController extends AdminController
|
||||
{
|
||||
protected string $serviceName = PatientService::class;
|
||||
|
||||
protected $typeOptions;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->filterTogglable(false)
|
||||
->columnsTogglable(false)
|
||||
->headerToolbar([
|
||||
$this->createButton(true, 'lg'),
|
||||
amis('reload')->align('right'),
|
||||
])
|
||||
->filter($this->baseFilter()->actions()->body([
|
||||
amisMake()->TextControl()->name('keyword')->label(__('patient.keyword'))->placeholder(__('patient.name') . '/' . __('patient.phone'))->size('md')->clearable(),
|
||||
// amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'),
|
||||
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('patient.id')),
|
||||
amisMake()->TableColumn()->name('name')->label(__('patient.name')),
|
||||
amisMake()->TableColumn()->name('sex_text')->label(__('patient.sex')),
|
||||
amisMake()->TableColumn()->name('phone')->label(__('patient.phone')),
|
||||
amisMake()->TableColumn()->name('age')->label(__('patient.age')),
|
||||
amisMake()->TableColumn()->name('treat_format')->label(__('patient.treat_at')),
|
||||
$this->rowActions(),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->body([
|
||||
amisMake()->TextControl()->name('name')->label(__('patient.name'))->required(true),
|
||||
amisMake()->SelectControl()->options(Gender::options())->name('sex')->label(__('patient.sex')),
|
||||
amisMake()->TextControl()->name('phone')->label(__('patient.phone')),
|
||||
amisMake()->TextControl()->name('address')->label(__('patient.address')),
|
||||
amisMake()->DateControl()->name('birthday')->label(__('patient.birthday')),
|
||||
amisMake()->DateControl()->name('treat_at')->label(__('patient.treat_at')),
|
||||
Components::make()->adminUserSelectControl()->name('doctor_id')->label(__('patient.doctor_id')),
|
||||
amisMake()->TextareaControl()->name('illness')->label(__('patient.illness')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
if ($this->actionOfGetData()) {
|
||||
return $this->response()->success($this->service->getDetail($id));
|
||||
}
|
||||
|
||||
$record = new PatientRecordController();
|
||||
$detail = amisMake()
|
||||
->Card()
|
||||
->className('base-form')
|
||||
->header(['title' => __('admin.detail')])
|
||||
->body($this->detail($id))
|
||||
->toolbar([
|
||||
amisMake()->Button()->label('修改基础信息')
|
||||
->level('primary')
|
||||
->className('mr-1')
|
||||
->actionType('dialog')
|
||||
->dialog(amisMake()->Dialog()->size('lg')->title('修改基础信息')->body(
|
||||
$this->form(true)->api($this->getUpdatePath())->initApi($this->getEditGetDataPath())->onEvent([
|
||||
'submitSucc' => [
|
||||
'actions' => [
|
||||
['actionType' => 'custom', 'script' => 'window.$owl.refreshAmisPage()',]
|
||||
]
|
||||
]
|
||||
])
|
||||
)),
|
||||
amisMake()->Button()->label('添加病历记录')
|
||||
->level('warning')
|
||||
->className('mr-1')
|
||||
->actionType('dialog')
|
||||
->dialog(amisMake()->Dialog()->size('lg')->title('修改基础信息')->body(
|
||||
$record->form(false, $id)->api('post:' . admin_url('/record'))->onEvent([
|
||||
'submitSucc' => [
|
||||
'actions' => [
|
||||
['actionType' => 'custom', 'script' => 'window.$owl.refreshAmisPage()',]
|
||||
]
|
||||
]
|
||||
])
|
||||
)),
|
||||
$this->backButton()
|
||||
]);
|
||||
|
||||
$page = $this->basePage()->body($detail);
|
||||
|
||||
return $this->response()->success($page);
|
||||
}
|
||||
|
||||
public function detail($id)
|
||||
{
|
||||
return $this->baseDetail()->body(amisMake()->Tabs()->tabs([
|
||||
amisMake()->Tab()->title('基础信息')->body([
|
||||
amisMake()->TextControl()->name('name')->label(__('patient.name'))->static(),
|
||||
amisMake()->SelectControl()->options(Gender::options())->name('sex')->label(__('patient.sex'))->static(),
|
||||
amisMake()->TextControl()->name('phone')->label(__('patient.phone'))->static(),
|
||||
amisMake()->TextControl()->name('address')->label(__('patient.address'))->static(),
|
||||
amisMake()->DateControl()->name('birthday')->label(__('patient.birthday'))->static(),
|
||||
amisMake()->DateControl()->name('treat_format')->label(__('patient.treat_at'))->static(),
|
||||
amisMake()->TextControl()->name('doctor.name')->label(__('patient.doctor_id'))->static(),
|
||||
amisMake()->TextareaControl()->name('illness')->label(__('patient.illness'))->static(),
|
||||
amisMake()->TextControl()->name('created_at')->label(__('patient.created_at'))->static(),
|
||||
]),
|
||||
amisMake()->Tab()->title('病历记录')->body(amisMake()->Service()
|
||||
->api(admin_url('/record?_action=getData&page=1&patient_id='.$id.'&perPage=20'))
|
||||
->body(amisMake()->Table()->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('patient_record.id')),
|
||||
amisMake()->Mapping()->map($this->getTypeOptions()->pluck('label', 'value'))->name('type_id')->label(__('patient_record.type_id')),
|
||||
amisMake()->TableColumn()->name('treat_at')->label(__('patient_record.treat_at')),
|
||||
amisMake()->TableColumn()->name('next_treat_at')->label(__('patient_record.next_treat_at')),
|
||||
amisMake()->TableColumn()->name('doctor.name')->label(__('patient_record.doctor_id')),
|
||||
])->affixRow([
|
||||
amisMake()->Button()->level('link')->label('查看更多')->colSpan(5)->actionType('link')->link(admin_url('/record?patient_id=' . $id)),
|
||||
])
|
||||
)
|
||||
)
|
||||
]));
|
||||
}
|
||||
|
||||
public function getTypeOptions()
|
||||
{
|
||||
if (!$this->typeOptions) {
|
||||
$this->typeOptions = Keyword::where('type_key', 'treat_type')->select(['id as value', 'name as label'])->get();
|
||||
}
|
||||
|
||||
return $this->typeOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Enums\OrderStatus;
|
||||
use App\Admin\Components;
|
||||
use App\Models\{Keyword, Patient};
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use App\Admin\Services\PatientRecordService;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
|
||||
/**
|
||||
* 病历管理
|
||||
*/
|
||||
class PatientRecordController extends AdminController
|
||||
{
|
||||
protected string $serviceName = PatientRecordService::class;
|
||||
|
||||
protected $typeOptions;
|
||||
|
||||
protected $patientOptions;
|
||||
|
||||
protected $adminUserOptions;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->filterTogglable(false)
|
||||
->columnsTogglable(false)
|
||||
->headerToolbar([
|
||||
$this->createButton(true, 'lg'),
|
||||
amis('reload')->align('right'),
|
||||
])
|
||||
->filter($this->baseFilter()->actions()->body([
|
||||
amisMake()->SelectControl()->options($this->getPatientOptions())->searchable()->name('patient_id')->label(__('patient_record.patient_id'))->size('md')->clearable(),
|
||||
amisMake()->SelectControl()->options($this->getTypeOptions())->name('type_id')->label(__('patient_record.type_id'))->size('md')->clearable(),
|
||||
amisMake()->DateRangeControl()->name('treat_range')->label(__('patient_record.treat_at'))->size('md')->clearable(),
|
||||
// amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'),
|
||||
amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('id')->label(__('patient_record.id')),
|
||||
amisMake()->TableColumn()->name('patient.name')->label(__('patient_record.patient_id')),
|
||||
amisMake()->Mapping()->map($this->getTypeOptions()->pluck('label', 'value'))->name('type_id')->label(__('patient_record.type_id')),
|
||||
amisMake()->TableColumn()->name('treat_at')->label(__('patient_record.treat_at')),
|
||||
amisMake()->TableColumn()->name('next_treat_at')->label(__('patient_record.next_treat_at')),
|
||||
amisMake()->TableColumn()->name('doctor.name')->label(__('patient_record.doctor_id')),
|
||||
$this->rowActions(),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form($isEdit, $patient_id = null): Form
|
||||
{
|
||||
$patient_element = amisMake()->SelectControl()->options($this->getPatientOptions())->searchable()->name('patient_id')->label(__('patient_record.patient_id'))->required();
|
||||
if ($patient_id) {
|
||||
$patient_element->value($patient_id)->static();
|
||||
}
|
||||
return $this->baseForm()->body([
|
||||
$patient_element,
|
||||
amisMake()->SelectControl()->options($this->getTypeOptions())->name('type_id')->label(__('patient_record.type_id'))->required()->onEvent([
|
||||
'change' => [
|
||||
'actions' => [
|
||||
['actionType' => 'reload', 'componentId' => 'patient_record_form_content_service', 'args' => ['select_type_id' => '${type_id}']]
|
||||
]
|
||||
]
|
||||
]),
|
||||
amisMake()->DateTimeControl()->name('treat_at')->label(__('patient_record.treat_at'))->value(now())->required(),
|
||||
amisMake()->SelectControl()->options($this->getAdminUserOptions())->name('doctor_id')->label(__('patient_record.doctor_id'))->required(),
|
||||
amisMake()->NumberControl()->name('origin_price')->label(__('patient_record.origin_price'))->required(),
|
||||
amisMake()->NumberControl()->name('sell_price')->label(__('patient_record.sell_price'))->required(),
|
||||
amisMake()->SelectControl()->options(OrderStatus::options())->name('order_status')->label(__('patient_record.order_status'))->default(OrderStatus::Success->value)->required(),
|
||||
amisMake()->Service()
|
||||
->className('cxd-Form-item')
|
||||
->id('patient_record_form_content_service')
|
||||
->api(amisMake()->BaseApi()->method('get')->url(admin_url('api/category/content?id=${select_type_id}')))
|
||||
->initFetch(false)
|
||||
->body(amisMake()->TextareaControl()->name('content')->label(__('patient_record.content'))),
|
||||
amisMake()->DateTimeControl()->name('next_treat_at')->label(__('patient_record.next_treat_at')),
|
||||
amisMake()->SelectControl()->options($this->getAdminUserOptions())->name('notify_user_id')->label(__('patient_record.notify_user_id')),
|
||||
amisMake()->DateTimeControl()->name('notify_at')->label(__('patient_record.notify_at')),
|
||||
amisMake()->TextControl()->name('notify_remarks')->label(__('patient_record.notify_remarks')),
|
||||
amisMake()->TextControl()->label(__('patient_record.creator_id'))->value($this->user()->name)->staitc(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail()
|
||||
{
|
||||
return $this->baseDetail()->body([
|
||||
amisMake()->TextControl()->name('patient_id')->label(__('patient_record.patient_id'))->static(),
|
||||
amisMake()->TextControl()->name('type_id')->label(__('patient_record.type_id'))->static(),
|
||||
amisMake()->DateTimeControl()->name('treat_at')->label(__('patient_record.treat_at'))->static(),
|
||||
amisMake()->SelectControl()->options($this->getAdminUserOptions())->name('doctor_id')->label(__('patient_record.doctor_id'))->static(),
|
||||
amisMake()->TextControl()->name('origin_price')->label(__('patient_record.origin_price'))->static(),
|
||||
amisMake()->TextControl()->name('sell_price')->label(__('patient_record.sell_price'))->static(),
|
||||
amisMake()->SelectControl()->options(OrderStatus::options())->name('order_status')->label(__('patient_record.order_status'))->static(),
|
||||
amisMake()->TextareaControl()->name('content')->label(__('patient_record.content'))->static(),
|
||||
amisMake()->DateTimeControl()->name('next_treat_at')->label(__('patient_record.next_treat_at'))->static(),
|
||||
amisMake()->SelectControl()->options($this->getAdminUserOptions())->name('notify_user_id')->label(__('patient_record.notify_user_id'))->placeholder('')->static(),
|
||||
amisMake()->DateTimeControl()->name('notify_at')->label(__('patient_record.notify_at'))->static(),
|
||||
amisMake()->TextControl()->name('notify_remarks')->label(__('patient_record.notify_remarks'))->static(),
|
||||
amisMake()->SelectControl()->options($this->getAdminUserOptions())->name('creator_id')->label(__('patient_record.creator_id'))->static(),
|
||||
amisMake()->DateTimeControl()->name('created_at')->label(__('patient.created_at'))->static(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getTypeOptions()
|
||||
{
|
||||
if (!$this->typeOptions) {
|
||||
$this->typeOptions = Keyword::where('type_key', 'treat_type')->select(['id as value', 'name as label'])->get();
|
||||
}
|
||||
|
||||
return $this->typeOptions;
|
||||
}
|
||||
|
||||
public function getPatientOptions()
|
||||
{
|
||||
if (!$this->patientOptions) {
|
||||
$this->patientOptions = Patient::select(['id as value', 'name as label'])->get();
|
||||
}
|
||||
|
||||
return $this->patientOptions;
|
||||
}
|
||||
|
||||
public function getAdminUserOptions()
|
||||
{
|
||||
if (!$this->adminUserOptions) {
|
||||
$this->adminUserOptions = AdminUser::select(['id as value', 'name as label'])->get();
|
||||
}
|
||||
|
||||
return $this->adminUserOptions;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services;
|
||||
|
||||
use App\ModelFilters\PatienRecordFilter;
|
||||
use App\Models\PatientRecord;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
|
||||
class PatientRecordService extends BaseService
|
||||
{
|
||||
protected string $modelName = PatientRecord::class;
|
||||
|
||||
protected array $withRelationships = ['doctor', 'patient'];
|
||||
|
||||
protected string $modelFilterName = PatienRecordFilter::class;
|
||||
|
||||
public function listQuery()
|
||||
{
|
||||
$model = $this->getModel();
|
||||
$filter = $this->getModelFilter();
|
||||
|
||||
$query = $this->query();
|
||||
if ($this->withRelationships) {
|
||||
$query->with($this->withRelationships);
|
||||
}
|
||||
|
||||
if ($filter) {
|
||||
$query->filter(request()->input(), $filter);
|
||||
}
|
||||
|
||||
return $query->sort();
|
||||
}
|
||||
|
||||
public function resloveData($data)
|
||||
{
|
||||
$creator_id = data_get($data, 'creator_id');
|
||||
if (!$creator_id) {
|
||||
$data['creator_id'] = data_get(Admin::user(), 'id');
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services;
|
||||
|
||||
use App\ModelFilters\PatientFilter;
|
||||
use App\Models\Patient;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class PatientService extends BaseService
|
||||
{
|
||||
protected string $modelName = Patient::class;
|
||||
|
||||
protected array $withRelationships = ['doctor'];
|
||||
|
||||
protected string $modelFilterName = PatientFilter::class;
|
||||
|
||||
/**
|
||||
* 处理表单数据
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function resloveData($data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单验证
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $id 空: 添加, 非空: 修改
|
||||
* @return mixed true: 验证通过, string: 错误提示
|
||||
*/
|
||||
public function validate($data, $id = null)
|
||||
{
|
||||
if (!$id) {
|
||||
$validator = Validator::make($data, [
|
||||
'name' => ['required'],
|
||||
]);
|
||||
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,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,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum Gender: int
|
||||
{
|
||||
case None = 0;
|
||||
case Male = 1;
|
||||
case Female = 2;
|
||||
|
||||
public static function map()
|
||||
{
|
||||
return [
|
||||
self::None->value => '未知',
|
||||
self::Male->value => '男',
|
||||
self::Female->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,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum OrderStatus: int
|
||||
{
|
||||
case None = 0;
|
||||
case Success = 1;
|
||||
|
||||
public static function map()
|
||||
{
|
||||
return [
|
||||
self::None->value => '未收',
|
||||
self::Success->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,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\ModelFilters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class PatienRecordFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* Related Models that have ModelFilters as well as the method on the ModelFilter
|
||||
* As [relationMethod => [input_key1, input_key2]].
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $relations = [];
|
||||
|
||||
public function patient($key)
|
||||
{
|
||||
$this->where('patient_id', $key);
|
||||
}
|
||||
|
||||
public function type($key)
|
||||
{
|
||||
$this->where('type_id', $key);
|
||||
}
|
||||
|
||||
public function treatRange($key)
|
||||
{
|
||||
$arr = explode(',', $key);
|
||||
$start = Carbon::createFromTimestamp(data_get($arr, 0, time()))->startOfDay();
|
||||
$end = Carbon::createFromTimestamp(data_get($arr, 1, time()))->endOfDay();
|
||||
$this->whereBetween('treat_at', [$start, $end]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\ModelFilters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class PatientFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* Related Models that have ModelFilters as well as the method on the ModelFilter
|
||||
* As [relationMethod => [input_key1, input_key2]].
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $relations = [];
|
||||
|
||||
public function keyword($key)
|
||||
{
|
||||
$this->where(fn ($q) => $q->where('name', 'like', '%'.$key.'%')->orWhere('phone', 'like', '%'.$key.'%'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Gender;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
/**
|
||||
* 病人
|
||||
*/
|
||||
class Patient extends Model
|
||||
{
|
||||
use HasDateTimeFormatter, Filterable;
|
||||
|
||||
protected $fillable = ['name', 'sex', 'phone', 'address', 'birthday', 'treat_at', 'illness', 'doctor_id', 'remarks'];
|
||||
|
||||
protected $appends = ['age', 'sex_text', 'treat_format', 'birthday_format'];
|
||||
|
||||
protected $casts = [
|
||||
'sex' => Gender::class,
|
||||
'treat_at' => 'date',
|
||||
'birthday' => 'date',
|
||||
];
|
||||
|
||||
protected function age(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => $this->birthday ? $this->birthday->diffInYears() : '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function sexText(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => $this->sex ? $this->sex->text() : '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function treatFormat(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => $this->treat_at ? $this->treat_at->format('Y-m-d') : '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function birthdayFormat(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => $this->birthday ? $this->birthday->format('Y-m-d') : '',
|
||||
);
|
||||
}
|
||||
|
||||
public function doctor()
|
||||
{
|
||||
return $this->belongsTo(AdminUser::class, 'doctor_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\OrderStatus;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
/**
|
||||
* 病历记录
|
||||
*/
|
||||
class PatientRecord extends Model
|
||||
{
|
||||
use HasDateTimeFormatter, Filterable;
|
||||
|
||||
protected $fillable = ['patient_id', 'type_id', 'treat_at', 'doctor_id', 'content', 'origin_price', 'sell_price', 'order_status', 'notify_at', 'notify_user_id', 'notify_remarks', 'is_notified', 'next_treat_at', 'creator_id'];
|
||||
|
||||
protected $casts = [
|
||||
'order_status' => OrderStatus::class,
|
||||
'notify_at' => 'datetime',
|
||||
'treat_at' => 'datetime',
|
||||
'next_treat_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function patient()
|
||||
{
|
||||
return $this->belongsTo(Patient::class, 'patient_id');
|
||||
}
|
||||
|
||||
public function type()
|
||||
{
|
||||
return $this->belongsTo(Keyword::class, 'type_id');
|
||||
}
|
||||
|
||||
public function doctor()
|
||||
{
|
||||
return $this->belongsTo(AdminUser::class, 'doctor_id');
|
||||
}
|
||||
|
||||
public function notifyUser()
|
||||
{
|
||||
return $this->belongsTo(AdminUser::class, 'notify_user_id');
|
||||
}
|
||||
|
||||
public function creator()
|
||||
{
|
||||
return $this->belongsTo(AdminUser::class, 'creator_id');
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
return $q->orderBy('treat_at', 'desc');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\Patient;
|
||||
use App\Enums\Gender;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Patient>
|
||||
*/
|
||||
class PatientFactory extends Factory
|
||||
{
|
||||
protected $model = Patient::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$faker = $this->faker;
|
||||
return [
|
||||
'name' => $faker->name,
|
||||
'sex' => $faker->randomElement(array_keys(Gender::map())),
|
||||
'phone' => $faker->phoneNumber,
|
||||
'address' => $faker->address,
|
||||
'birthday' => $faker->dateTimeBetween('-30 years', '-10 years'),
|
||||
'treat_at' => $faker->dateTimeBetween('-7 days'),
|
||||
'illness' => '基本稳定',
|
||||
'doctor_id' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\{PatientRecord, Patient, Keyword};
|
||||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||||
use App\Enums\OrderStatus;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\PatientRecord>
|
||||
*/
|
||||
class PatientRecordFactory extends Factory
|
||||
{
|
||||
protected $model = PatientRecord::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$faker = $this->faker;
|
||||
return [
|
||||
'patient_id' => Patient::inRandomOrder()->value('id'),
|
||||
'type_id' => Keyword::where('type_key', 'treat_type')->inRandomOrder()->value('id'),
|
||||
'treat_at' => $faker->dateTimeBetween('-7 days'),
|
||||
'doctor_id' => 1,
|
||||
'content' => '逐渐恢复',
|
||||
'origin_price' => $faker->numberBetween(200, 300),
|
||||
'sell_price' => $faker->numberBetween(100, 200),
|
||||
'order_status' => OrderStatus::Success->value,
|
||||
'notify_at' => $faker->dateTimeBetween('now', '+7 days'),
|
||||
'notify_user_id' => 1,
|
||||
'notify_remarks' => '带上医保卡',
|
||||
'is_notified' => 0,
|
||||
'next_treat_at' => $faker->dateTimeBetween('now', '+7 days'),
|
||||
'creator_id' => 1
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Enums\Gender;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('patients', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('姓名');
|
||||
$table->string('sex')->default(Gender::None->value)->comment('性别');
|
||||
$table->string('phone')->nullable()->comment('联系方式');
|
||||
$table->string('address')->nullable()->comment('地址');
|
||||
$table->date('birthday')->nullable()->comment('出生年月');
|
||||
$table->dateTime('treat_at')->nullable()->comment('初诊时间');
|
||||
$table->text('illness')->nullable()->comment('病情描述');
|
||||
$table->unsignedBigInteger('doctor_id')->nullable()->comment('坐诊医生, admin_users.id');
|
||||
$table->string('remarks')->nullable()->comment('备注');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('patients');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?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('patient_records', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('patient_id')->comment('病人, patients.id');
|
||||
$table->unsignedBigInteger('type_id')->comment('类别, keywords.id');
|
||||
$table->timestamp('treat_at')->comment('就诊时间');
|
||||
$table->unsignedBigInteger('doctor_id')->comment('医生, admin_users.id');
|
||||
$table->text('content')->comment('就诊情况');
|
||||
$table->decimal('origin_price')->default(0)->comment('划线价');
|
||||
$table->decimal('sell_price')->default(0)->comment('实收价');
|
||||
$table->unsignedTinyInteger('order_status')->default(0)->comment('状态(0: 未收, 1: 已收)');
|
||||
|
||||
$table->timestamp('notify_at')->nullable()->comment('提醒时间');
|
||||
$table->unsignedBigInteger('notify_user_id')->nullable()->comment('提醒人, admin_users.id');
|
||||
$table->string('notify_remarks')->nullable()->comment('提醒备注');
|
||||
$table->unsignedTinyInteger('is_notified')->default(0)->comment('是否已经提醒');
|
||||
$table->timestamp('next_treat_at')->nullable()->comment('下次就诊时间');
|
||||
|
||||
$table->unsignedBigInteger('creator_id')->comment('操作人, admin_users.id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('patient_records');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Database\Factories\{PatientFactory, PatientRecordFactory};
|
||||
use App\Models\{Patient, PatientRecord};
|
||||
|
||||
class PatientSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
Patient::truncate();
|
||||
PatientRecord::truncate();
|
||||
(new PatientFactory())->count(10)->create();
|
||||
(new PatientRecordFactory())->count(100)->create();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'name' => '名称',
|
||||
'key' => 'KEY',
|
||||
'value' => '值',
|
||||
'parent_id' => '上级',
|
||||
'type_key' => '上级',
|
||||
'path' => '上级',
|
||||
'sort' => '排序(倒序)',
|
||||
'level' => '层级',
|
||||
'data' => '扩展',
|
||||
'image' => '图片',
|
||||
'description' => '描述',
|
||||
'content' => '内容',
|
||||
];
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'keyword' => '关键字',
|
||||
'name' => '姓名',
|
||||
'sex' => '性别',
|
||||
'phone' => '联系方式',
|
||||
'address' => '地址',
|
||||
'birthday' => '出生年月',
|
||||
'treat_at' => '初诊时间',
|
||||
'illness' => '病情描述',
|
||||
'doctor_id' => '坐诊医生',
|
||||
'age' => '年龄',
|
||||
'remarks' => '备注',
|
||||
'created_at' => '录入时间',
|
||||
];
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'patient_id' => '姓名',
|
||||
'type_id' => '类别',
|
||||
'treat_at' => '诊疗时间',
|
||||
'doctor_id' => '就诊医生',
|
||||
'content' => '诊疗情况',
|
||||
'origin_price' => '划线价',
|
||||
'sell_price' => '实收价',
|
||||
'order_status' => '收费情况',
|
||||
'notify_at' => '通知时间',
|
||||
'notify_user_id' => '通知人',
|
||||
'notify_remarks' => '通知备注',
|
||||
'is_notified' => '是否已经通知',
|
||||
'next_treat_at' => '下次就诊时间',
|
||||
'creator_id' => '操作人',
|
||||
'created_at' => '录入时间',
|
||||
];
|
||||
Loading…
Reference in New Issue