diff --git a/app/Admin/Controllers/CategoryController.php b/app/Admin/Controllers/CategoryController.php index 26e3291..7f87afd 100644 --- a/app/Admin/Controllers/CategoryController.php +++ b/app/Admin/Controllers/CategoryController.php @@ -9,6 +9,7 @@ use Illuminate\Http\Request; use Slowlyo\OwlAdmin\Controllers\AdminController; use Slowlyo\OwlAdmin\Renderers\Form; use Slowlyo\OwlAdmin\Renderers\Page; +use Slowlyo\OwlAdmin\Renderers\AjaxAction; /** * 分类管理 @@ -100,4 +101,14 @@ class CategoryController extends AdminController 'content' => $content ]); } + + protected function rowDeleteButton(): AjaxAction + { + return AjaxAction::make() + ->label(__('admin.delete')) + ->icon('fa-regular fa-trash-can') + ->level('link') + ->confirmText(__('admin.confirm_delete') . '同时删除关联的病历记录?') + ->api($this->getDeletePath()); + } } diff --git a/app/Admin/Controllers/PatientRecordController.php b/app/Admin/Controllers/PatientRecordController.php index c0d8171..1672983 100644 --- a/app/Admin/Controllers/PatientRecordController.php +++ b/app/Admin/Controllers/PatientRecordController.php @@ -38,6 +38,7 @@ class PatientRecordController extends AdminController 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()->SelectControl()->options($this->getAdminUserOptions())->searchable()->name('doctor_id')->label(__('patient-record.doctor_id'))->clearable()->size('md'), // amisMake()->Button()->label(__('admin.reset'))->actionType('clear-and-submit'), amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'), ])) @@ -46,9 +47,16 @@ class PatientRecordController extends AdminController 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('origin_price')->label(__('patient-record.origin_price')), + amisMake()->TableColumn()->name('sell_price')->label(__('patient-record.sell_price')), amisMake()->TableColumn()->name('next_treat_at')->label(__('patient-record.next_treat_at')), amisMake()->TableColumn()->name('doctor.name')->label(__('patient-record.doctor_id')), $this->rowActions(), + ])->affixRowClassName('text-info-dk')->affixRow([ + ['type' => 'text', 'text' => '总计', 'colSpan' => 4], + ['type' => 'text', 'text' => __('total-record.origin_price') . ': ${origin_price}'], + ['type' => 'text', 'text' => __('total-record.sell_price') . ': ${sell_price}'], + ['type' => 'text', 'text' => '', 'colSpan' => 3] ]); return $this->baseList($crud); @@ -83,9 +91,9 @@ class PatientRecordController extends AdminController ->body(Components::make()->fuEditorControl()->name('content')->label(__('patient-record.content'))), amisMake()->DateTimeControl()->name('next_treat_at')->label(__('patient-record.next_treat_at')), amisMake()->SelectControl()->options($this->getAdminUserOptions())->searchable()->name('notify_user_id')->label(__('patient-record.notify_user_id')), - amisMake()->DateTimeControl()->name('notify_at')->label(__('patient-record.notify_at')), + amisMake()->DateControl()->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(), + amisMake()->TextControl()->label(__('patient-record.creator_id'))->value($this->user()->name)->readonly(), ]); } @@ -103,7 +111,7 @@ class PatientRecordController extends AdminController Components::make()->fuEditorControl()->name('content')->label(__('patient-record.content'))->static(), amisMake()->DateTimeControl()->name('next_treat_at')->label(__('patient-record.next_treat_at'))->static(), amisMake()->TextControl()->name('notify_user.name')->label(__('patient-record.notify_user_id'))->static(), - amisMake()->DateTimeControl()->name('notify_at')->label(__('patient-record.notify_at'))->static(), + amisMake()->DateControl()->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(), diff --git a/app/Admin/Services/KeywordService.php b/app/Admin/Services/KeywordService.php index 07b7e34..4dc58f8 100644 --- a/app/Admin/Services/KeywordService.php +++ b/app/Admin/Services/KeywordService.php @@ -31,14 +31,23 @@ class KeywordService extends BaseService return ['items' => $this->getTree(request()->all())]; } - public function delete(string $ids): mixed + /** + * 删除的前置方法 + * + * @param array $ids 主键id + * @return mixed true: 继续后续操作, string: 中断操作, 返回错误提示 + */ + public function preDelete(array $ids) { - $ids = explode(',', $ids); - if (count($ids) == 1) { - $this->query()->where('path', 'like', '%-'.$ids[0].'-%')->delete(); - } + // 删除子级 + $this->query()->where(function ($q) use ($ids) { + foreach ($ids as $id) { + $q->orWhere('path', 'like', '%-'.$id.'-%'); + } + })->delete(); - return $this->query()->whereIn('id', $ids)->delete(); + // 删除病历记录 + return true; } public function validate($data, $id = null) diff --git a/app/Admin/Services/PatientRecordService.php b/app/Admin/Services/PatientRecordService.php index 3f064fe..d4b8c52 100644 --- a/app/Admin/Services/PatientRecordService.php +++ b/app/Admin/Services/PatientRecordService.php @@ -32,6 +32,19 @@ class PatientRecordService extends BaseService return $query->sort(); } + public function list() + { + $query = $this->listQuery(); + + $list = $query->clone()->paginate(request()->input('perPage', 20)); + $items = $list->items(); + $total = $list->total(); + $origin_price = floatval($query->clone()->sum('origin_price')); + $sell_price = floatval($query->clone()->sum('sell_price')); + + return compact('items', 'total', 'sell_price', 'origin_price'); + } + public function resloveData($data) { $creator_id = data_get($data, 'creator_id'); diff --git a/app/Admin/Services/TotalRecordService.php b/app/Admin/Services/TotalRecordService.php index 256987f..65cefd4 100644 --- a/app/Admin/Services/TotalRecordService.php +++ b/app/Admin/Services/TotalRecordService.php @@ -64,8 +64,8 @@ class TotalRecordService extends BaseService $list = (clone $query)->paginate(request()->input('perPage', 20)); $items = $list->items(); $total = $list->total(); - $origin_price = (new PatientRecordService())->listQuery()->sum('origin_price'); - $sell_price = (new PatientRecordService())->listQuery()->sum('sell_price'); + $origin_price = floatval((new PatientRecordService())->listQuery()->sum('origin_price')); + $sell_price = floatval((new PatientRecordService())->listQuery()->sum('sell_price')); return compact('items', 'total', 'sell_price', 'origin_price'); } diff --git a/app/Console/Commands/PatientRecordNotify.php b/app/Console/Commands/PatientRecordNotify.php new file mode 100644 index 0000000..5d95181 --- /dev/null +++ b/app/Console/Commands/PatientRecordNotify.php @@ -0,0 +1,40 @@ +whereNotNul('notify_user_id')->whereNotNul('notify_at')->get(); + $app = EasyWeChat::officialAccount(); + $app->setAccessToken(new \App\Services\WechatOfficialAccessToken( + appId: $this->getAccount()->getAppId(), + secret: $this->getAccount()->getSecret(), + cache: $this->getCache(), + httpClient: $this->getHttpClient(), + stable: $this->config->get('use_stable_access_token', false), + )); + } +} diff --git a/app/Http/Controllers/WechatController.php b/app/Http/Controllers/WechatController.php index e3d0055..e73f815 100644 --- a/app/Http/Controllers/WechatController.php +++ b/app/Http/Controllers/WechatController.php @@ -6,6 +6,7 @@ use Illuminate\Http\Request; use App\Models\UserSocialite; use App\Enums\SocialiteType; use Slowlyo\OwlAdmin\Admin; +use Overtrue\LaravelWeChat\EasyWeChat; class WechatController extends Controller { @@ -31,8 +32,16 @@ class WechatController extends Controller return redirect(url('/h5/pages/index/welcome') . '?token=' . $token); } - protected function response() + public function officialAccessToken() { - return Admin::response(); + $app = EasyWeChat::officialAccount(); + $token = $app->getAccessToken(); + return response()->json([ + 'code' => 200, + 'data' => [ + 'token' => $token->getToken(), + ], + 'message' => '' + ]); } } diff --git a/app/ModelFilters/PatientRecordFilter.php b/app/ModelFilters/PatientRecordFilter.php index 8f17617..0b33f1d 100644 --- a/app/ModelFilters/PatientRecordFilter.php +++ b/app/ModelFilters/PatientRecordFilter.php @@ -24,6 +24,11 @@ class PatientRecordFilter extends ModelFilter { $this->where('type_id', $key); } + + public function doctor($key) + { + $this->where('doctor_id', $key); + } public function treatRange($key) { diff --git a/app/Models/PatientRecord.php b/app/Models/PatientRecord.php index ff9bfc9..f069a30 100644 --- a/app/Models/PatientRecord.php +++ b/app/Models/PatientRecord.php @@ -20,7 +20,7 @@ class PatientRecord extends Model protected $casts = [ 'order_status' => OrderStatus::class, - 'notify_at' => 'datetime', + 'notify_at' => 'date', 'treat_at' => 'datetime', 'next_treat_at' => 'datetime', 'origin_price' => 'float', diff --git a/app/Services/WechatOfficialAccessToken.php b/app/Services/WechatOfficialAccessToken.php new file mode 100644 index 0000000..e12698a --- /dev/null +++ b/app/Services/WechatOfficialAccessToken.php @@ -0,0 +1,25 @@ +successful()) { + $token = data_get($response->json(), 'data.token'); + return $token; + } + } + + return parent::getToken(); + } +} diff --git a/config/easywechat.php b/config/easywechat.php index 379d5a7..a7df7f2 100644 --- a/config/easywechat.php +++ b/config/easywechat.php @@ -14,6 +14,7 @@ return [ * 公众号 */ 'official_account' => [ + 'access_token_url' => env('WECHAT_OFFICIAL_ACCOUNT_ACCESS_TOKEN_URL', ''), 'default' => [ 'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', ''), // AppID 'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', ''), // AppSecret diff --git a/database/factories/AdminUserFactory.php b/database/factories/AdminUserFactory.php index 2860ac3..d193a19 100644 --- a/database/factories/AdminUserFactory.php +++ b/database/factories/AdminUserFactory.php @@ -22,7 +22,7 @@ class AdminUserFactory extends Factory $name = $this->faker->name; return [ 'username' => $this->faker->username, - 'name' => $this->faker->name, + 'name' => $name, 'avatar' => 'https://ui-avatars.com/api/?name=' . $name, 'password' => '$2y$10$MXFSBvoV02d.nMg/5//5ru/os27JgSJhsePidDr/uiIw6UQ.MigP2', ]; diff --git a/database/factories/PatientRecordFactory.php b/database/factories/PatientRecordFactory.php index 6356618..7257b53 100644 --- a/database/factories/PatientRecordFactory.php +++ b/database/factories/PatientRecordFactory.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\Factory; use App\Models\{PatientRecord, Patient, Keyword}; use Slowlyo\OwlAdmin\Models\AdminUser; use App\Enums\OrderStatus; +use Slowlyo\OwlAdmin\Models\AdminUser; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\PatientRecord> @@ -26,7 +27,7 @@ class PatientRecordFactory extends Factory '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, + 'doctor_id' => AdminUser::inRandomOrder()->value('id'), 'content' => '逐渐恢复', 'origin_price' => $faker->numberBetween(200, 300), 'sell_price' => $faker->numberBetween(100, 200), diff --git a/database/seeders/KeywordSeeder.php b/database/seeders/KeywordSeeder.php index a59b573..9158118 100644 --- a/database/seeders/KeywordSeeder.php +++ b/database/seeders/KeywordSeeder.php @@ -8,7 +8,6 @@ use Illuminate\Support\Arr; class KeywordSeeder extends Seeder { - public $id = 1; /** * Run the database seeds. * @@ -19,7 +18,7 @@ class KeywordSeeder extends Seeder Keyword::truncate(); $list = [ ['key' => 'treat_type', 'name' => '诊疗类别', 'children' => [ - ['key' => 'treat_head', 'name' => '头疗', 'content' => '按摩意见:服务意见:效果意见:'], + ['key' => 'treat_head', 'name' => '头疗', 'content' => '

按摩意见:

服务意见:

效果意见:

'], ['key' => 'treat_normal', 'name' => '看病', 'content' => ''], ]] ]; @@ -38,7 +37,6 @@ class KeywordSeeder extends Seeder $key = $parent->key.'_'.($index + 1); } $attributes = [ - 'id' => data_get($item, 'id', $this->id), 'key' => $key, 'parent_id' => data_get($parent, 'id', 0), 'path' => ($parent ? $parent->path.$parent->id : '').'-', @@ -46,9 +44,11 @@ class KeywordSeeder extends Seeder 'level' => data_get($parent, 'level', 0) + 1, 'sort' => $count - $index, ]; + if ($id) { + $attributes['id'] = $id; + } $model = Keyword::create(array_merge($attributes, Arr::except($item, ['children']))); - $this->id++; if ($children = data_get($item, 'children')) { $this->createByTree($children, $model); } diff --git a/routes/api.php b/routes/api.php index fa84410..a8aa48c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -13,3 +13,4 @@ use Illuminate\Support\Facades\Route; | be assigned to the "api" middleware group. Make something great! | */ +Route::post('wechant/official-access-token', [\App\Http\Controllers\WechatController::class, 'officialAccessToken']); \ No newline at end of file