From 04c090ca421111c75896468dae32d73e2ef326b2 Mon Sep 17 00:00:00 2001 From: "iVampireSP.com" Date: Mon, 31 Oct 2022 19:03:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=BC=81=E4=B8=9A?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E9=80=9A=E7=9F=A5=20=E4=BB=A5=E5=8F=8A=20?= =?UTF-8?q?=E5=B7=A5=E5=8D=95=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Broadcasting/WeComRobotChannel.php | 33 + .../User/WorkOrder/ReplyController.php | 2 +- .../User/WorkOrder/WorkOrderController.php | 2 +- app/Jobs/Remote/WorkOrder/Reply.php | 12 +- app/Jobs/Remote/WorkOrder/WorkOrder.php | 5 +- app/Models/Module/Module.php | 3 +- app/Notifications/WorkOrderNotification.php | 98 +++ app/Observers/WorkOrder/ReplyObserver.php | 66 ++ app/Observers/WorkOrder/WorkOrderObserver.php | 71 ++ app/Providers/AppServiceProvider.php | 8 +- app/Providers/EventServiceProvider.php | 13 +- bootstrap/app.php | 1 + composer.json | 1 + composer.lock | 784 +++++++++++++++++- config/settings.php | 11 + ...10_31_161617_add_wecom_hook_to_modules.php | 38 + .../work_order/created.blade.php | 71 ++ .../notifications/work_order/reply.blade.php | 15 + 18 files changed, 1218 insertions(+), 16 deletions(-) create mode 100644 app/Broadcasting/WeComRobotChannel.php create mode 100644 app/Notifications/WorkOrderNotification.php create mode 100644 app/Observers/WorkOrder/ReplyObserver.php create mode 100644 app/Observers/WorkOrder/WorkOrderObserver.php create mode 100644 config/settings.php create mode 100644 database/migrations/2022_10_31_161617_add_wecom_hook_to_modules.php create mode 100644 resources/views/notifications/work_order/created.blade.php create mode 100644 resources/views/notifications/work_order/reply.blade.php diff --git a/app/Broadcasting/WeComRobotChannel.php b/app/Broadcasting/WeComRobotChannel.php new file mode 100644 index 0000000..a9f8cf7 --- /dev/null +++ b/app/Broadcasting/WeComRobotChannel.php @@ -0,0 +1,33 @@ +toVoice($notifiable); + + // 向 $notifiable 实例发送通知... + } +} diff --git a/app/Http/Controllers/User/WorkOrder/ReplyController.php b/app/Http/Controllers/User/WorkOrder/ReplyController.php index d68be36..6413a48 100644 --- a/app/Http/Controllers/User/WorkOrder/ReplyController.php +++ b/app/Http/Controllers/User/WorkOrder/ReplyController.php @@ -20,7 +20,7 @@ public function index(WorkOrder $workOrder) return $this->notFound('无法找到对应的工单。'); } - $replies = Reply::workOrderId($workOrder->id)->simplePaginate(10); + $replies = Reply::workOrderId($workOrder->id)->simplePaginate(100); return $this->success($replies); } diff --git a/app/Http/Controllers/User/WorkOrder/WorkOrderController.php b/app/Http/Controllers/User/WorkOrder/WorkOrderController.php index 6b6c9dd..a8faed8 100644 --- a/app/Http/Controllers/User/WorkOrder/WorkOrderController.php +++ b/app/Http/Controllers/User/WorkOrder/WorkOrderController.php @@ -12,7 +12,7 @@ class WorkOrderController extends Controller public function index(WorkOrder $workOrder) { - $workOrder = $workOrder->thisUser()->with(['user', 'module', 'host'])->simplePaginate(10); + $workOrder = $workOrder->thisUser()->with(['user', 'module', 'host'])->simplePaginate(100); return $this->success($workOrder); } diff --git a/app/Jobs/Remote/WorkOrder/Reply.php b/app/Jobs/Remote/WorkOrder/Reply.php index 9de723c..6aad009 100644 --- a/app/Jobs/Remote/WorkOrder/Reply.php +++ b/app/Jobs/Remote/WorkOrder/Reply.php @@ -47,16 +47,16 @@ public function handle() $response = $http->post('work-orders/' . $this->reply->workOrder->id . '/replies', $reply); if ($response->successful()) { - $this->reply->is_pending = false; + $this->reply->update([ + 'is_pending' => false + ]); broadcast(new UserEvent($this->reply->workOrder->user_id, 'work-order.replied', $this->reply)); } else { - $this->reply->is_pending = true; + $this->reply->update([ + 'is_pending' => true + ]); } - - $this->reply->save(); - - } } diff --git a/app/Jobs/Remote/WorkOrder/WorkOrder.php b/app/Jobs/Remote/WorkOrder/WorkOrder.php index 9753e99..d1d2d4a 100644 --- a/app/Jobs/Remote/WorkOrder/WorkOrder.php +++ b/app/Jobs/Remote/WorkOrder/WorkOrder.php @@ -46,11 +46,12 @@ public function handle() } if (!$response->successful()) { - $this->workOrder->status = 'error'; + $this->workOrder->update([ + 'status' => 'error' + ]); } else { broadcast(new UserEvent($this->workOrder->user_id, 'work-order.updated', $this->workOrder)); } - $this->workOrder->save(); } } diff --git a/app/Models/Module/Module.php b/app/Models/Module/Module.php index e8f3d52..7876aef 100644 --- a/app/Models/Module/Module.php +++ b/app/Models/Module/Module.php @@ -33,7 +33,8 @@ class Module extends Model implements AuthenticatableContract, AuthorizableContr protected $hidden = [ 'api_token', - 'url' + 'url', + 'wecom_key' ]; diff --git a/app/Notifications/WorkOrderNotification.php b/app/Notifications/WorkOrderNotification.php new file mode 100644 index 0000000..a83ce46 --- /dev/null +++ b/app/Notifications/WorkOrderNotification.php @@ -0,0 +1,98 @@ +load(['module', 'user']); + + $module = $workOrder->module; + } elseif ($notifiable instanceof Reply) { + + $view = 'notifications.work_order.reply'; + + + $workOrder->load(['workOrder', 'user']); + $workOrder->workOrder->load('module'); + + $reply = $workOrder; + $workOrder = $workOrder->workOrder; + + $module = $workOrder->module; + } else { + return; + } + + // 取消隐藏字段 + $module->makeVisible(['wecom_key']); + + if ($module->wecom_key == null) { + return; + } + + $wecom_key = $module->wecom_key; + // 隐藏字段 + $module->makeHidden(['wecom_key']); + + + $body = Http::post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' . $wecom_key, [ + 'msgtype' => 'markdown', + 'markdown' => [ + 'content' => view($view, [ + 'workOrder' => $workOrder, + 'user' => $workOrder->user, + 'reply' => $reply, + 'module' => $module, + ])->render(), + ], + ]); + + Log::info('企业微信机器人发送消息', [ + 'body' => $body->body(), + 'status' => $body->status(), + ]); + } +} diff --git a/app/Observers/WorkOrder/ReplyObserver.php b/app/Observers/WorkOrder/ReplyObserver.php new file mode 100644 index 0000000..ffbd8b7 --- /dev/null +++ b/app/Observers/WorkOrder/ReplyObserver.php @@ -0,0 +1,66 @@ +toGroup($reply); + } + + /** + * Handle the Reply "updated" event. + * + * @param \App\Models\WorkOrder\Reply $reply + * @return void + */ + public function updated(Reply $reply) + { + // + } + + /** + * Handle the Reply "deleted" event. + * + * @param \App\Models\WorkOrder\Reply $reply + * @return void + */ + public function deleted(Reply $reply) + { + // + } + + /** + * Handle the Reply "restored" event. + * + * @param \App\Models\WorkOrder\Reply $reply + * @return void + */ + public function restored(Reply $reply) + { + // + } + + /** + * Handle the Reply "force deleted" event. + * + * @param \App\Models\WorkOrder\Reply $reply + * @return void + */ + public function forceDeleted(Reply $reply) + { + // + } +} diff --git a/app/Observers/WorkOrder/WorkOrderObserver.php b/app/Observers/WorkOrder/WorkOrderObserver.php new file mode 100644 index 0000000..7cfd9ff --- /dev/null +++ b/app/Observers/WorkOrder/WorkOrderObserver.php @@ -0,0 +1,71 @@ +toGroup($workOrder); + } + + /** + * Handle the WorkOrder "updated" event. + * + * @param \App\Models\WorkOrder\WorkOrder $workOrder + * @return void + */ + public function updated(WorkOrder $workOrder) + { + + Log::debug('workOrder updated', ['workOrder' => $workOrder]); + // + return (new WorkOrderNotification()) + ->toGroup($workOrder); + } + + /** + * Handle the WorkOrder "deleted" event. + * + * @param \App\Models\WorkOrder\WorkOrder $workOrder + * @return void + */ + public function deleted(WorkOrder $workOrder) + { + // + } + + /** + * Handle the WorkOrder "restored" event. + * + * @param \App\Models\WorkOrder\WorkOrder $workOrder + * @return void + */ + public function restored(WorkOrder $workOrder) + { + // + } + + /** + * Handle the WorkOrder "force deleted" event. + * + * @param \App\Models\WorkOrder\WorkOrder $workOrder + * @return void + */ + public function forceDeleted(WorkOrder $workOrder) + { + // + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 70192ea..bc4909a 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,7 +3,7 @@ namespace App\Providers; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Storage; +// use Illuminate\Support\Facades\Storage; use Illuminate\Support\ServiceProvider; @@ -24,6 +24,12 @@ public function register() public function boot() { $this->generateInstanceId(); + + + // $this->app->make(\Illuminate\Notifications\ChannelManager::class)->extend('your-channel', function () { + // return $this->app->make(App\Channels\YourChannel::class); + // }); + // // header('server: Cluster Ready!'); diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index b116d3c..fbc2ab3 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -12,9 +12,9 @@ class EventServiceProvider extends ServiceProvider * @var array */ protected $listen = [ - \App\Events\ExampleEvent::class => [ - \App\Listeners\ExampleListener::class, - ], + // \App\Events\WorkOrderProcessed::class => [ + // \App\Listeners\SendWorkOrderNotification::class, + // ], ]; /** @@ -26,4 +26,11 @@ public function shouldDiscoverEvents() { return false; } + + public function boot() { + parent::boot(); + + \App\Models\WorkOrder\WorkOrder::observe(\App\Observers\WorkOrder\WorkOrderObserver::class); + \App\Models\WorkOrder\Reply::observe(\App\Observers\WorkOrder\ReplyObserver::class); + } } diff --git a/bootstrap/app.php b/bootstrap/app.php index a9b5baf..ad29601 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -134,6 +134,7 @@ $app->register(App\Providers\EventServiceProvider::class); $app->register(\Anik\Form\FormRequestServiceProvider::class); $app->register(App\Providers\RouteBindingServiceProvider::class); +$app->register(Illuminate\Notifications\NotificationServiceProvider::class); // broadcast $app->register(App\Providers\BroadcastServiceProvider::class); diff --git a/composer.json b/composer.json index 527192b..26fb915 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "freyo/flysystem-qcloud-cos-v5": "^2.0", "guzzlehttp/guzzle": "^7.5", "hhxsv5/laravel-s": "~3.7.0", + "illuminate/notifications": "^9.34", "illuminate/redis": "^9.28", "jenssegers/mongodb": "^3.9", "laravel/lumen-framework": "^9.0", diff --git a/composer.lock b/composer.lock index 1f5b0b4..c930fd5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4eea65d15fe3433d2e3ac710207e819a", + "content-hash": "348fafe400e5a446c6c7d832810b8a01", "packages": [ { "name": "adbario/php-dot-notation", @@ -437,6 +437,87 @@ ], "time": "2021-08-28T21:56:17+00:00" }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "0992cc19268b259a39e86f296da5f0677841f42c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/0992cc19268b259a39e86f296da5f0677841f42c", + "reference": "0992cc19268b259a39e86f296da5f0677841f42c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^3.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.1" + }, + "time": "2021-08-13T13:06:58+00:00" + }, { "name": "doctrine/cache", "version": "2.2.0", @@ -3197,6 +3278,138 @@ }, "time": "2022-08-09T13:29:29+00:00" }, + { + "name": "illuminate/mail", + "version": "v9.34.0", + "source": { + "type": "git", + "url": "https://github.com/illuminate/mail.git", + "reference": "de6b2b493654c33b5336d35755973911bcfa14b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/mail/zipball/de6b2b493654c33b5336d35755973911bcfa14b7", + "reference": "de6b2b493654c33b5336d35755973911bcfa14b7", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "illuminate/collections": "^9.0", + "illuminate/container": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "illuminate/support": "^9.0", + "league/commonmark": "^2.2", + "php": "^8.0.2", + "psr/log": "^1.0|^2.0|^3.0", + "symfony/mailer": "^6.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.2" + }, + "suggest": { + "aws/aws-sdk-php": "Required to use the SES mail driver (^3.198.1).", + "symfony/http-client": "Required to use the Symfony API mail transports (^6.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Mail\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Mail package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-09-14T13:13:44+00:00" + }, + { + "name": "illuminate/notifications", + "version": "v9.34.0", + "source": { + "type": "git", + "url": "https://github.com/illuminate/notifications.git", + "reference": "98d1e4e7966d267a3b59198a537eea05b074e028" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/notifications/zipball/98d1e4e7966d267a3b59198a537eea05b074e028", + "reference": "98d1e4e7966d267a3b59198a537eea05b074e028", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "illuminate/broadcasting": "^9.0", + "illuminate/bus": "^9.0", + "illuminate/collections": "^9.0", + "illuminate/container": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/filesystem": "^9.0", + "illuminate/mail": "^9.0", + "illuminate/queue": "^9.0", + "illuminate/support": "^9.0", + "php": "^8.0.2" + }, + "suggest": { + "illuminate/database": "Required to use the database transport (^9.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Notifications\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Notifications package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-09-12T13:48:14+00:00" + }, { "name": "illuminate/pagination", "version": "v9.33.0", @@ -4146,6 +4359,206 @@ }, "time": "2022-09-08T13:45:54+00:00" }, + { + "name": "league/commonmark", + "version": "2.3.6", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "857afc47ce113454bd629037213378ba3219dd40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/857afc47ce113454bd629037213378ba3219dd40", + "reference": "857afc47ce113454bd629037213378ba3219dd40", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.30.0", + "commonmark/commonmark.js": "0.30.0", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2022-10-30T16:45:38+00:00" + }, + { + "name": "league/config", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e", + "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.90", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2021-08-14T12:15:32+00:00" + }, { "name": "league/flysystem", "version": "3.5.2", @@ -4658,6 +5071,165 @@ ], "time": "2022-09-02T07:48:13+00:00" }, + { + "name": "nette/schema", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/9a39cef03a5b34c7de64f551538cbba05c2be5df", + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": ">=7.1 <8.2" + }, + "require-dev": { + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^0.12", + "tracy/tracy": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.2.2" + }, + "time": "2021-10-15T11:40:02+00:00" + }, + { + "name": "nette/utils", + "version": "v3.2.8", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "a6784d523c0e67409b5c64c3d951e9871ef64241" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/a6784d523c0e67409b5c64c3d951e9871ef64241", + "reference": "a6784d523c0e67409b5c64c3d951e9871ef64241", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2 <8.3" + }, + "conflict": { + "nette/di": "<3.0.6" + }, + "require-dev": { + "nette/tester": "~2.0", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v3.2.8" + }, + "time": "2022-09-06T00:55:00+00:00" + }, { "name": "nikic/fast-route", "version": "v1.3.0", @@ -6714,6 +7286,77 @@ ], "time": "2022-10-26T21:42:49+00:00" }, + { + "name": "symfony/css-selector", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T17:24:16+00:00" + }, { "name": "symfony/deprecation-contracts", "version": "v3.1.1", @@ -7482,6 +8125,86 @@ ], "time": "2022-10-28T18:06:36+00:00" }, + { + "name": "symfony/mailer", + "version": "v6.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "7e19813c0b43387c55665780c4caea505cc48391" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/7e19813c0b43387c55665780c4caea505cc48391", + "reference": "7e19813c0b43387c55665780c4caea505cc48391", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "egulias/email-validator": "^2.1.10|^3", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<5.4" + }, + "require-dev": { + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/messenger": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-28T16:23:08+00:00" + }, { "name": "symfony/mime", "version": "v6.1.6", @@ -9034,6 +9757,65 @@ }, "time": "2022-09-25T08:09:36+00:00" }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "2.2.5", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/4348a3a06651827a27d989ad1d13efec6bb49b19", + "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^5.5 || ^7.0 || ^8.0", + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.5" + }, + "time": "2022-09-12T13:28:28+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.4.1", diff --git a/config/settings.php b/config/settings.php new file mode 100644 index 0000000..3ba83ed --- /dev/null +++ b/config/settings.php @@ -0,0 +1,11 @@ + [ + 'robot_hook' => [ + 'default' => '4727b740-57dc-448c-a89a-840e28fb48dc', + 'billing' => '50aa88b6-febe-4cf5-a18f-c714b3752548', + 'cluster_ready' => '7de76311-280e-40eb-bfd0-c17c0e053e90', + ], + ] +]; diff --git a/database/migrations/2022_10_31_161617_add_wecom_hook_to_modules.php b/database/migrations/2022_10_31_161617_add_wecom_hook_to_modules.php new file mode 100644 index 0000000..eaa1c9d --- /dev/null +++ b/database/migrations/2022_10_31_161617_add_wecom_hook_to_modules.php @@ -0,0 +1,38 @@ +string('wecom_key')->nullable()->comment('企业微信机器人 key'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('modules', function (Blueprint $table) { + // + + // drop if exists + if (Schema::hasColumn('modules', 'wecom_key')) { + $table->dropColumn('wecom_key'); + } + }); + } +}; diff --git a/resources/views/notifications/work_order/created.blade.php b/resources/views/notifications/work_order/created.blade.php new file mode 100644 index 0000000..641cb98 --- /dev/null +++ b/resources/views/notifications/work_order/created.blade.php @@ -0,0 +1,71 @@ +@php + $title = ''; +@endphp + +@switch ($workOrder->status) + @case('pending') + @php + $title = '工单挂起'; + @endphp + @break + + @case('open') + @php + $title = '工单投递成功,并且已开启'; + @endphp + @break + + @case('user_replied') + @php + $title = '工单挂起'; + @endphp + @break + + @case('closed') + @php + $title = '已结单'; + @endphp + @break + + @case('replied') + @php + $title = '工作人员已回复'; + @endphp + @break + + @case('on_hold') + @php + $title = '挂起'; + @endphp + @break + + @case('in_progress') + @php + $title = '正在处理中'; + @endphp + @break + + @case('error') + @php + $title = '投递失败'; + @endphp + @break + + @default + @php + $title = '状态更新'; + @endphp + @break +@endswitch + +## {{ $title }} + +# {{ $module->name }} + +## 客户 {{ $user->name }} +##### 邮箱 {{ $user->email }} +##### 余额 {{ $user->balance }} 元 + +# {{ $workOrder->id }}#{{ $workOrder->title }} + +{{ $workOrder->content }} diff --git a/resources/views/notifications/work_order/reply.blade.php b/resources/views/notifications/work_order/reply.blade.php new file mode 100644 index 0000000..ce3f180 --- /dev/null +++ b/resources/views/notifications/work_order/reply.blade.php @@ -0,0 +1,15 @@ +## @if ($workOrder->is_pending) + 回复投递中 +@else + 回复已投递 +@endif + +# {{ $module->name }} + +## 客户 {{ $user->name }} +##### 邮箱 {{ $user->email }} +##### 余额 {{ $user->balance }} 元 + +# {{ $workOrder->id }}#{{ $workOrder->title }} + +{{ $reply->content }}