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 * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @throws \think\db\exception\DataNotFoundException */ public function storeBy(array $data) { $parentId = $data['parent_id'] ?? 0; $this->checkMenuNum($parentId); $data['parent_id'] = $parentId; $data['key'] = $data['type'] . '_' . rand(10000, 999999); $data['created_at'] = $data['updated_at'] = time(); 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) { $data['updated_at'] = time(); 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('只支持五个二级菜单'); } } } }