From a232f555c3dec1f072601ed8e9da686dd9345804 Mon Sep 17 00:00:00 2001 From: JaguarJack Date: Fri, 26 Jun 2020 16:27:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- catch/wechat/controller/Material.php | 10 + catch/wechat/controller/Menus.php | 86 +++++++ .../20200625042417_wechat_material.php | 42 ++++ .../20200626025445_wechat_menus.php | 46 ++++ catch/wechat/library/events/Click.php | 10 + catch/wechat/library/events/Location.php | 10 + catch/wechat/library/events/Scan.php | 10 + catch/wechat/library/events/Subscribe.php | 10 + catch/wechat/library/events/Unsubscribe.php | 10 + catch/wechat/library/events/View.php | 10 + catch/wechat/model/WechatMenus.php | 39 +++ .../repository/WechatMenusRepository.php | 227 ++++++++++++++++++ catch/wechat/route.php | 5 + extend/catcher/event/LoadModuleRoutes.php | 3 - 14 files changed, 515 insertions(+), 3 deletions(-) create mode 100644 catch/wechat/controller/Material.php create mode 100644 catch/wechat/controller/Menus.php create mode 100644 catch/wechat/database/migrations/20200625042417_wechat_material.php create mode 100644 catch/wechat/database/migrations/20200626025445_wechat_menus.php create mode 100644 catch/wechat/library/events/Click.php create mode 100644 catch/wechat/library/events/Location.php create mode 100644 catch/wechat/library/events/Scan.php create mode 100644 catch/wechat/library/events/Subscribe.php create mode 100644 catch/wechat/library/events/Unsubscribe.php create mode 100644 catch/wechat/library/events/View.php create mode 100644 catch/wechat/model/WechatMenus.php create mode 100644 catch/wechat/repository/WechatMenusRepository.php diff --git a/catch/wechat/controller/Material.php b/catch/wechat/controller/Material.php new file mode 100644 index 0000000..ef90e0a --- /dev/null +++ b/catch/wechat/controller/Material.php @@ -0,0 +1,10 @@ +menus = $repository; + } + + public function index() + { + return CatchResponse::success($this->menus->all()); + } + + /** + * 保存 + * + * @time 2020年06月26日 + * @param CatchRequest $request + * @return \think\response\Json + */ + public function save(CatchRequest $request) + { + return CatchResponse::success($this->menus->storeBy($request->param())); + } + + /** + * 更新 + * + * @time 2020年06月26日 + * @param $id + * @param CatchRequest $request + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return \think\response\Json + */ + public function update($id, CatchRequest $request) + { + return CatchResponse::success($this->menus->updateBy($id, $request->param())); + } + + /** + * 删除 + * + * @time 2020年06月26日 + * @param $id + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return \think\response\Json + */ + public function delete($id) + { + return CatchResponse::success($this->menus->deleteBy($id)); + } + + /** + * 同步 + * + * @time 2020年06月26日 + * @return \think\response\Json + * @throws \Exception + */ + public function sync() + { + return CatchResponse::success($this->menus->sync()); + } +} \ No newline at end of file diff --git a/catch/wechat/database/migrations/20200625042417_wechat_material.php b/catch/wechat/database/migrations/20200625042417_wechat_material.php new file mode 100644 index 0000000..d6461c8 --- /dev/null +++ b/catch/wechat/database/migrations/20200625042417_wechat_material.php @@ -0,0 +1,42 @@ +table('wechat_material', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => '微信素材' ,'id' => 'id','signed' => true ,'primary_key' => ['id']]); + $table->addColumn('tag_id', 'integer', ['limit' => MysqlAdapter::INT_SMALL,'null' => true,'signed' => false,'comment' => '微信 tagId',]) + ->addColumn('name', 'string', ['limit' => 30,'null' => true,'comment' => '标签名称',]) + ->addColumn('fans_amount', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '粉丝数量',]) + ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建时间',]) + ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '更新时间',]) + ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '软删除',]) + ->addIndex(['tag_id'], ['unique' => true,'name' => 'unique_tag_id']) + ->create(); + } +} diff --git a/catch/wechat/database/migrations/20200626025445_wechat_menus.php b/catch/wechat/database/migrations/20200626025445_wechat_menus.php new file mode 100644 index 0000000..ad45bd0 --- /dev/null +++ b/catch/wechat/database/migrations/20200626025445_wechat_menus.php @@ -0,0 +1,46 @@ +table('wechat_menus', ['engine' => 'InnoDB', 'collation' => 'utf8mb4_general_ci', 'comment' => '微信菜单' ,'id' => 'id','signed' => true ,'primary_key' => ['id']]); + $table->addColumn('name', 'string', ['limit' => 30,'null' => true,'comment' => '菜单名称',]) + ->addColumn('parent_id', 'integer', ['limit' => MysqlAdapter::INT_SMALL,'null' => false,'default' => 0,'signed' => true,'comment' => '父级ID',]) + ->addColumn('type', 'string', ['null' => false, 'limit' => 100, 'comment' => '类型',]) + ->addColumn('key', 'string', ['null' => false, 'limit' => 30, 'comment' => 'key',]) + ->addColumn('url', 'string', ['default' => '', 'limit' => 255, 'comment' => 'view 类型 url 链接',]) + ->addColumn('appid', 'string', ['default' => '', 'limit' => 100, 'comment' => '小程序 appid',]) + ->addColumn('pagepath', 'string', ['default' => '', 'limit' => 255, 'comment' => '小程序页面',]) + ->addColumn('media_id', 'string', ['default' => '', 'limit' => 100, 'comment' => '调用新增永久素材接口返回的合法media_id']) + ->addColumn('created_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '创建时间',]) + ->addColumn('updated_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '更新时间',]) + ->addColumn('deleted_at', 'integer', ['limit' => MysqlAdapter::INT_REGULAR,'null' => false,'default' => 0,'signed' => true,'comment' => '软删除',]) + ->create(); + } +} diff --git a/catch/wechat/library/events/Click.php b/catch/wechat/library/events/Click.php new file mode 100644 index 0000000..ef90e0a --- /dev/null +++ b/catch/wechat/library/events/Click.php @@ -0,0 +1,10 @@ +menus = $menus; + } + + protected function model() + { + return $this->menus; + } + + public function all() + { + $menus = $this->menus->select(); + + return Tree::done($menus->toArray()); + } + + /** + * 新增 + * + * @time 2020年06月26日 + * @param array $data + * @return mixed + */ + public function storeBy(array $data) + { + $parentId = $data['parent_id'] ?? 0; + + $this->checkMenuNum($parentId); + + $data['parent_id'] = $parentId; + $data['key'] = $data['type'] . '_' . rand(10000, 999999); + + if (parent::storeBy($data)) { + return $this->syncToWechat(); + }// TODO: Change the autogenerated stub + + throw new FailedException('新增失败'); + } + + /** + * 更新 + * + * @time 2020年06月26日 + * @param int $id + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return bool + */ + public function updateBy(int $id, array $data) + { + if (parent::updateBy($id, $data)) { + return $this->syncToWechat(); + } + + throw new FailedException('更新失败'); + } + + /** + * 删除失败 + * + * @time 2020年06月26日 + * @param int $id + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return bool + */ + public function deleteBy(int $id) + { + $menu = $this->findBy($id); + + // 父级菜单 + if (!$menu->parent_id) { + if ($this->menus->where('parent_id', $id)->count()) { + throw new FailedException('请先删除子级菜单'); + } + } + + if (parent::deleteBy($id)) { + return $this->syncToWechat(); + } + + throw new FailedException('删除失败'); + } + + /** + * 同步 + * + * @time 2020年06月26日 + * @throws \Exception + * @return bool + */ + public function sync() + { + // 同步前先删除 + $this->menus->where('id', '>', 0)->delete(); + + $menus = WeChat::officialAccount()->menu->list()['menu']['button']; + + foreach ($menus as $menu) { + $id = $this->menus->createBy($this->menuToLocal($menu)); + + if (!empty($menu['sub_button'])) { + foreach ($menu['sub_button'] as $button) { + $button['parent_id'] = $id; + $this->menus->createBy($this->menuToLocal($button)); + } + } + } + + return true; + } + + /** + * 同步到表 + * + * @time 2020年06月26日 + * @param $menu + * @return array + */ + protected function menuToLocal($menu) + { + $data = [ + 'parent_id' => $menu['parent_id'] ?? 0, + 'type' => $menu['type'] ?? '', + 'name' => $menu['name'], + 'key' => $menu['key'] ?? '', + 'created_at' => \time(), + 'updated_at' => \time(), + ]; + + if (isset($menu['type'])) { + if ($menu['type'] == 'view') { + $data['url'] = $menu['url']; + return $data; + } elseif ($menu['type'] == 'miniprogram') { + $data['url'] = $menu['url'] ?? ''; + $data['appid'] = $menu['appid']; + $data['pagepath'] = $menu['pagepath']; + return $data; + } + } + + return $data; + } + + + /** + * 同步到微信 + * + * @time 2020年06月26日 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return bool + */ + protected function syncToWechat() + { + $menus = $this->menus->field([ + 'id', 'parent_id', 'key', 'name', 'type', 'url', 'appid', 'pagepath', 'media_id' + ])->select()->toArray(); + + foreach ($menus as &$menu) { + if ($menu['type'] == 'view') { + unset($menu['appid'], $menu['media_id'], $menu['pagepath']); + } elseif ($menu['type'] == 'miniprogram') { + unset($menu['media_id']); + } else { + unset($menu['url'], $menu['appid'], $menu['pagepath'], $menu['media_id']); + } + } + + $wechatMenus = Tree::done($menus, 0, 'parent_id', 'sub_button'); + + WeChat::throw(WeChat::officialAccount()->menu->create($wechatMenus)); + + return true; + } + + /** + * check menus number + * + * @time 2020年06月26日 + * @param $parentId + * @return void + */ + protected function checkMenuNum($parentId) + { + // 父级别分类 + if (!$parentId) { + if ($this->menus->where('parent_id', 0)->count() >= 3) { + throw new FailedException('只支持三个一级菜单'); + } + } else { + if ($this->menus->where('parent_id', $parentId)->count() >= 5) { + throw new FailedException('只支持五个二级菜单'); + } + } + } +} \ No newline at end of file diff --git a/catch/wechat/route.php b/catch/wechat/route.php index 96612cb..c4afb8e 100644 --- a/catch/wechat/route.php +++ b/catch/wechat/route.php @@ -25,5 +25,10 @@ $router->group('wechat', function () use ($router){ }); // 消息 $router->rule('message', '\catchAdmin\wechat\controller\Message@done', 'GET|POST'); + // 微信菜单 + $router->group('official/menus', function () use ($router){ + $router->resource('', '\catchAdmin\wechat\controller\Menus'); + $router->post('sync', '\catchAdmin\wechat\controller\Menus@sync'); + }); })->middleware('auth'); diff --git a/extend/catcher/event/LoadModuleRoutes.php b/extend/catcher/event/LoadModuleRoutes.php index 047556e..818b592 100644 --- a/extend/catcher/event/LoadModuleRoutes.php +++ b/extend/catcher/event/LoadModuleRoutes.php @@ -3,9 +3,6 @@ declare (strict_types = 1); namespace catcher\event; -use catchAdmin\permissions\PermissionsMiddleware; -use catchAdmin\user\AuthTokenMiddleware; -use catcher\CatchAdmin; use think\App; use think\Route;