master
parent
903fa344e8
commit
8f99902092
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Forms;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\Adverse;
|
||||
use App\Models\Orders;
|
||||
use Kris\LaravelFormBuilder\Form;
|
||||
use Kris\LaravelFormBuilder\Field;
|
||||
|
||||
class AdverseForm extends Form
|
||||
{
|
||||
public function buildForm()
|
||||
{
|
||||
$this->add("project_id", Field::SELECT, [
|
||||
"label" => "所属项目/医院",
|
||||
"empty_value" => "请选择",
|
||||
"choices" => (new Project())->get()->pluck("name", "id")->toArray(),
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add("order_id", Field::SELECT, [
|
||||
"label" => "相关订单",
|
||||
"empty_value" => "请选择",
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add("type", Field::SELECT, [
|
||||
"label" => "不良事件类型",
|
||||
"empty_value" => "请选择",
|
||||
"choices" => Adverse::getTypeList(),
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add("description", Field::TEXTAREA, [
|
||||
"label" => "事件描述",
|
||||
"attr" => [
|
||||
"class" => "form-control",
|
||||
"rows" => 4,
|
||||
"placeholder" => "请详细描述不良事件的具体情况..."
|
||||
]
|
||||
]);
|
||||
|
||||
$this->add("solved_status", Field::SELECT, [
|
||||
"label" => "解决状态",
|
||||
"empty_value" => "请选择",
|
||||
"choices" => Adverse::getStatusList(),
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add("solved_result", Field::TEXTAREA, [
|
||||
"label" => "解决结果描述",
|
||||
"attr" => [
|
||||
"class" => "form-control",
|
||||
"rows" => 3,
|
||||
"placeholder" => "请描述解决方案和结果..."
|
||||
]
|
||||
]);
|
||||
|
||||
$this->add("solved_at", Field::DATE, [
|
||||
"label" => "解决时间",
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add("solved_by", Field::TEXT, [
|
||||
"label" => "经办人",
|
||||
"attr" => ["class" => "form-control"]
|
||||
]);
|
||||
|
||||
$this->add('buttons', 'buttongroup', [
|
||||
"splitted" => true,
|
||||
"buttons" => [
|
||||
["label" => "保存", "attr" => ["class" => "btn btn-primary mr-1", "type" => "submit"]],
|
||||
["label" => "返回", "attr" => ["class" => "btn btn-light btn-back", "type" => "button"]]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Adverse extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'adverse';
|
||||
|
||||
protected $fillable = [
|
||||
'project_id',
|
||||
'order_id',
|
||||
'type',
|
||||
'description',
|
||||
'solved_at',
|
||||
'solved_by',
|
||||
'solved_status',
|
||||
'solved_result'
|
||||
];
|
||||
|
||||
protected $dates = [
|
||||
'solved_at',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at'
|
||||
];
|
||||
|
||||
// 状态常量
|
||||
const STATUS_PENDING = 'pending'; // 待处理
|
||||
const STATUS_PROCESSING = 'processing'; // 处理中
|
||||
const STATUS_SOLVED = 'solved'; // 已解决
|
||||
const STATUS_CLOSED = 'closed'; // 已关闭
|
||||
|
||||
// 类型常量
|
||||
const TYPE_SERVICE = 'service'; // 服务问题
|
||||
const TYPE_QUALITY = 'quality'; // 质量问题
|
||||
const TYPE_SAFETY = 'safety'; // 安全问题
|
||||
const TYPE_COMPLAINT = 'complaint'; // 投诉
|
||||
const TYPE_OTHER = 'other'; // 其他
|
||||
|
||||
/**
|
||||
* 获取状态列表
|
||||
*/
|
||||
public static function getStatusList()
|
||||
{
|
||||
return [
|
||||
self::STATUS_PENDING => '待处理',
|
||||
self::STATUS_PROCESSING => '处理中',
|
||||
self::STATUS_SOLVED => '已解决',
|
||||
self::STATUS_CLOSED => '已关闭'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型列表
|
||||
*/
|
||||
public static function getTypeList()
|
||||
{
|
||||
return [
|
||||
self::TYPE_SAFETY => '意外事件',
|
||||
self::TYPE_COMPLAINT => '沟通事件',
|
||||
self::TYPE_OTHER => '其他'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联项目
|
||||
*/
|
||||
public function project()
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联订单
|
||||
*/
|
||||
public function order()
|
||||
{
|
||||
return $this->belongsTo(Orders::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联解决人(管理员)
|
||||
*/
|
||||
public function solver()
|
||||
{
|
||||
return $this->belongsTo(\App\Admin::class, 'solved_by');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态文本
|
||||
*/
|
||||
public function getStatusTextAttribute()
|
||||
{
|
||||
$statusList = self::getStatusList();
|
||||
return $statusList[$this->solved_status] ?? '未知状态';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型文本
|
||||
*/
|
||||
public function getTypeTextAttribute()
|
||||
{
|
||||
$typeList = self::getTypeList();
|
||||
return $typeList[$this->type] ?? '未知类型';
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否已解决
|
||||
*/
|
||||
public function isSolved()
|
||||
{
|
||||
return in_array($this->solved_status, [self::STATUS_SOLVED, self::STATUS_CLOSED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否待处理
|
||||
*/
|
||||
public function isPending()
|
||||
{
|
||||
return $this->solved_status === self::STATUS_PENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理中
|
||||
*/
|
||||
public function isProcessing()
|
||||
{
|
||||
return $this->solved_status === self::STATUS_PROCESSING;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
|
||||
use App\Models\Adverse;
|
||||
use App\Models\Orders;
|
||||
use App\Models\Project;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class AdverseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// 获取项目列表
|
||||
$projects = Project::all();
|
||||
if ($projects->isEmpty()) {
|
||||
$this->command->info('没有找到项目数据,请先创建项目');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
$orders = Orders::all();
|
||||
if ($orders->isEmpty()) {
|
||||
$this->command->info('没有找到订单数据,请先创建订单');
|
||||
return;
|
||||
}
|
||||
|
||||
// 不良事件类型
|
||||
$types = [
|
||||
Adverse::TYPE_SAFETY,
|
||||
Adverse::TYPE_COMPLAINT,
|
||||
Adverse::TYPE_OTHER
|
||||
];
|
||||
|
||||
// 状态列表
|
||||
$statuses = [
|
||||
Adverse::STATUS_PENDING,
|
||||
Adverse::STATUS_PROCESSING,
|
||||
Adverse::STATUS_SOLVED,
|
||||
Adverse::STATUS_CLOSED
|
||||
];
|
||||
|
||||
// 事件描述模板
|
||||
$descriptions = [
|
||||
'患者反映护工服务态度不佳,存在沟通问题',
|
||||
'护工未按时到达,影响患者正常护理',
|
||||
'患者家属投诉护工专业技能不足',
|
||||
'护工在护理过程中出现操作失误',
|
||||
'患者反映护工个人卫生问题',
|
||||
'护工与患者家属发生言语冲突',
|
||||
'护工未按照医嘱执行护理操作',
|
||||
'患者反映护工工作态度消极',
|
||||
'护工在护理过程中造成患者轻微受伤',
|
||||
'患者家属对护工服务不满意',
|
||||
'护工未及时报告患者异常情况',
|
||||
'护工在护理过程中使用手机影响工作',
|
||||
'患者反映护工专业知识欠缺',
|
||||
'护工未按规定时间进行护理记录',
|
||||
'患者家属投诉护工服务态度恶劣'
|
||||
];
|
||||
|
||||
// 解决结果模板
|
||||
$solvedResults = [
|
||||
'已对护工进行批评教育,要求改进服务态度',
|
||||
'已安排经验丰富的护工接替,确保服务质量',
|
||||
'已对护工进行专业技能培训,提升护理水平',
|
||||
'已对护工进行安全教育,避免类似事件发生',
|
||||
'已要求护工严格遵守个人卫生规范',
|
||||
'已对护工进行沟通技巧培训,改善服务态度',
|
||||
'已对护工进行规范化操作培训',
|
||||
'已对护工进行职业道德教育',
|
||||
'已对护工进行安全操作培训,确保患者安全',
|
||||
'已安排护工与患者家属沟通,化解矛盾',
|
||||
'已建立护工定期报告制度,及时发现问题',
|
||||
'已制定护工工作纪律,禁止工作时间使用手机',
|
||||
'已对护工进行专业知识培训',
|
||||
'已建立护理记录检查制度,确保及时记录',
|
||||
'已对护工进行服务态度培训,提升服务质量'
|
||||
];
|
||||
|
||||
// 经办人列表
|
||||
$handlers = [
|
||||
'张主任',
|
||||
'李护士长',
|
||||
'王管理员',
|
||||
'刘主管',
|
||||
'陈经理'
|
||||
];
|
||||
|
||||
// 创建50条测试数据
|
||||
for ($i = 1; $i <= 50; $i++) {
|
||||
$project = $projects->random();
|
||||
$order = $orders->where('project_id', $project->id)->first();
|
||||
|
||||
$type = $types[array_rand($types)];
|
||||
$status = $statuses[array_rand($statuses)];
|
||||
$description = $descriptions[array_rand($descriptions)];
|
||||
|
||||
$data = [
|
||||
'project_id' => $project->id,
|
||||
'order_id' => $order ? $order->id : null,
|
||||
'type' => $type,
|
||||
'description' => $description,
|
||||
'solved_status' => $status,
|
||||
'solved_by' => $handlers[array_rand($handlers)],
|
||||
'created_at' => Carbon::now()->subDays(rand(1, 90)),
|
||||
'updated_at' => Carbon::now()->subDays(rand(1, 90))
|
||||
];
|
||||
|
||||
// 如果已解决,设置解决时间和结果
|
||||
if (in_array($status, [Adverse::STATUS_SOLVED, Adverse::STATUS_CLOSED])) {
|
||||
$data['solved_at'] = Carbon::now()->subDays(rand(1, 30));
|
||||
$data['solved_result'] = $solvedResults[array_rand($solvedResults)];
|
||||
}
|
||||
|
||||
Adverse::create($data);
|
||||
}
|
||||
|
||||
$this->command->info('成功创建50条不良事件测试数据');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
@extends("admin.layouts.layout")
|
||||
|
||||
@section("content")
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<a class="btn btn-primary" href="{{url($urlPrefix.'/create')}}">
|
||||
@lang("icons.action_create") @lang('actions.create'){{$modelName}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered" id="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>所属项目/医院</th>
|
||||
<th>相关订单</th>
|
||||
<th>类型</th>
|
||||
<th>事件描述</th>
|
||||
<th>解决状态</th>
|
||||
<th>解决日期</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($data as $row)
|
||||
<tr data-id="{{$row->id}}">
|
||||
<td>{{ $row->id }}</td>
|
||||
<td>{{ $row->project ? $row->project->name : '-' }}</td>
|
||||
<td>
|
||||
@if($row->order)
|
||||
订单号:{{ $row->order->serial }}<br>
|
||||
下单人:{{ $row->order->contact }}<br>
|
||||
电话:{{ $row->order->mobile }}
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $row->type_text ?? '-' }}</td>
|
||||
<td style="max-width: 300px;word-break: break-all;">{{ $row->description }}</td>
|
||||
<td>{{ $row->status_text ?? '-' }}</td>
|
||||
<td>{{ $row->solved_at ? date("Y-m-d", strtotime($row->solved_at)) : '-' }}</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-primary"
|
||||
href="{{url("{$urlPrefix}/edit?id={$row['id']}")}}">@lang("icons.action_edit") @lang("actions.edit")</a>
|
||||
<a class="btn btn-sm btn-danger btn-delete" data-id="{{$row['id']}}"
|
||||
href="javascript:;">@lang("icons.action_delete") @lang("actions.delete")</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@include("public._pages")
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include("public._delete")
|
||||
@endsection
|
||||
|
||||
@push("footer")
|
||||
<script>
|
||||
|
||||
</script>
|
||||
@endpush
|
||||
Loading…
Reference in new issue