1
0
Fork 0
master
panliang 2023-08-30 13:46:32 +08:00
parent 87a073b070
commit 1a2b30c0a4
20 changed files with 1013 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,17 @@
<?php
return [
'id' => 'ID',
'name' => '名称',
'key' => 'KEY',
'value' => '值',
'parent_id' => '上级',
'type_key' => '上级',
'path' => '上级',
'sort' => '排序(倒序)',
'level' => '层级',
'data' => '扩展',
'image' => '图片',
'description' => '描述',
'content' => '内容',
];

View File

@ -0,0 +1,17 @@
<?php
return [
'id' => 'ID',
'keyword' => '关键字',
'name' => '姓名',
'sex' => '性别',
'phone' => '联系方式',
'address' => '地址',
'birthday' => '出生年月',
'treat_at' => '初诊时间',
'illness' => '病情描述',
'doctor_id' => '坐诊医生',
'age' => '年龄',
'remarks' => '备注',
'created_at' => '录入时间',
];

View File

@ -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' => '录入时间',
];