From 0feed34baaa5df5fa842f1ddfb9de13e6698fcab Mon Sep 17 00:00:00 2001 From: leiyong <1549684884@qq.com> Date: Tue, 21 Jun 2022 09:54:50 +0000 Subject: [PATCH] * Finish task#57901. --- lib/feishuapi/feishuapi.class.php | 141 +++++++++++++++++++--- module/webhook/control.php | 34 ++++-- module/webhook/css/choosedept.css | 2 + module/webhook/lang/en.php | 7 +- module/webhook/lang/zh-cn.php | 8 +- module/webhook/view/choosedept.html.php | 149 +++++++++++++++++++++--- 6 files changed, 299 insertions(+), 42 deletions(-) create mode 100644 module/webhook/css/choosedept.css diff --git a/lib/feishuapi/feishuapi.class.php b/lib/feishuapi/feishuapi.class.php index 3749eb5a99..2cfb53db53 100644 --- a/lib/feishuapi/feishuapi.class.php +++ b/lib/feishuapi/feishuapi.class.php @@ -150,30 +150,24 @@ class feishuapi * @access public * @return array */ - public function getDeptTree() + public function getChildDeptTree($departmentID) { - $depts = array('result' => 'success', 'data' => array()); - - /* Gets the enterprise name. */ - $response = $this->queryAPI($this->apiUrl . "tenant/v2/tenant/query", '', array(CURLOPT_CUSTOMREQUEST => "GET")); - $company = array('id' => '1', 'pId' => '0', 'name' => $response->data->tenant->name, 'open' => 1); - $data = array($company); - /* Get depts by parent dept. */ + $depts = array(); $pageToken = ''; $index = 0; while(true) { - $response = $this->queryAPI($this->apiUrl . "contact/v3/departments?parent_department_id=0" . ($pageToken ? "&page_token={$pageToken}" : '') . "&fetch_child=true&page_size=50", '', array(CURLOPT_CUSTOMREQUEST => "GET")); + $response = $this->queryAPI($this->apiUrl . "contact/v3/departments?parent_department_id={$departmentID}" . ($pageToken ? "&page_token={$pageToken}" : '') . "&fetch_child=true&page_size=50", '', array(CURLOPT_CUSTOMREQUEST => "GET")); if(isset($response->data->items)) { foreach($response->data->items as $key => $dept) { + $depts[$index]['id'] = $dept->open_department_id; + $depts[$index]['pId'] = empty($dept->parent_department_id) ? 1 : $dept->parent_department_id; + $depts[$index]['name'] = $dept->name; + $depts[$index]['open'] = 1; $index++; - $data[$index]['id'] = $dept->open_department_id; - $data[$index]['pId'] = empty($dept->parent_department_id) ? 1 : $dept->parent_department_id; - $data[$index]['name'] = $dept->name; - $data[$index]['open'] = 1; } } @@ -181,10 +175,129 @@ class feishuapi $pageToken = $response->data->page_token; } - $depts['data'] = $data; return $depts; } + /** + * Get the first tier department. + * + * @access public + * @return array + */ + public function getDeptTree() + { + $depts = array('data' => array()); + + /* Gets the enterprise name. */ + $response = $this->queryAPI($this->apiUrl . "tenant/v2/tenant/query", '', array(CURLOPT_CUSTOMREQUEST => "GET")); + $company = array('id' => '1', 'pId' => '0', 'name' => $response->data->tenant->name, 'open' => 1); + $depts = array($company); + + $departmentIdList = $this->getScopes(); + + $urls = array(); + foreach($departmentIdList as $departmentID) $urls[] = $this->apiUrl . "contact/v3/departments/{$departmentID}"; + $datas = $this->multiRequest($urls); + + foreach($datas as $index => $dept) + { + $index += 1; + $dept = json_decode($dept); + + $memberCount = $dept->data->department->member_count; + $status = $dept->data->department->status->is_deleted; + + $depts[$index]['id'] = $dept->data->department->open_department_id; + $depts[$index]['pId'] = empty($dept->data->department->parent_department_id) ? 1 : $dept->data->department->parent_department_id; + $depts[$index]['name'] = $dept->data->department->name; + $depts[$index]['open'] = 1; + } + + return $depts; + } + + /** + * Get the visible range of the application. + * + * @access public + * @return array + */ + public function getScopes() + { + $pageToken = ''; + $departmentIdList = array(); + + while(true) + { + $response = $this->queryAPI($this->apiUrl . "contact/v3/scopes" . "?user_id_type=open_id&department_id_type=open_department_id&page_token={$pageToken}&page_size=100", '', array(CURLOPT_CUSTOMREQUEST => "GET")); + $departmentIds = isset($response->data->department_ids) ? $response->data->department_ids : array(); + foreach($departmentIds as $id) $departmentIdList[] = $id; + + if(!isset($response->data->page_token)) break; + $pageToken = $response->data->page_token; + } + + return $departmentIdList; + } + + /** + * Handle the concurrency of requests. + * + * @access public + * @return array + */ + public function multiRequest($urls) + { + $curl = curl_multi_init(); + $urlHandlers = array(); + $urlData = array(); + + /* Set request header information. */ + $headers = array(); + $headers[] = "Content-Type: application/json"; + if($this->token) $headers[] = "Authorization:Bearer {$this->token}"; + + /* Initialize multiple request handles to one. */ + foreach($urls as $url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $urlHandlers[] = $ch; + curl_multi_add_handle($curl, $ch); + } + + $active = null; + do + { + $mrc = curl_multi_exec($curl, $active); + } + while($mrc == CURLM_CALL_MULTI_PERFORM); + + while($active && $mrc == CURLM_OK) + { + usleep(50000); + if(curl_multi_select($curl) != -1) + { + do + { + $mrc = curl_multi_exec($curl, $active); + } + while($mrc == CURLM_CALL_MULTI_PERFORM); + } + } + + foreach($urlHandlers as $index => $ch) + { + $urlData[$index] = curl_multi_getcontent($ch); + curl_multi_remove_handle($curl, $ch); + } + curl_multi_close($curl); + return $urlData; + } + /** * Send message * diff --git a/module/webhook/control.php b/module/webhook/control.php index fa44af7ae7..26be1ed104 100644 --- a/module/webhook/control.php +++ b/module/webhook/control.php @@ -291,12 +291,7 @@ class webhook extends control $response = $dingapi->getDeptTree(); } - if($webhook->type == 'feishuuser') - { - $this->app->loadClass('feishuapi', true); - $feishuApi = new feishuapi($webhook->secret->appId, $webhook->secret->appSecret); - $response = $feishuApi->getDeptTree(); - } + if($webhook->type == 'feishuuser') $response = array('result' => 'success', 'data' => array()); if($response['result'] == 'fail') { @@ -315,11 +310,34 @@ class webhook extends control $this->view->title = $this->lang->webhook->chooseDept; $this->view->position[] = $this->lang->webhook->chooseDept; - $this->view->deptTree = $response['data']; - $this->view->webhookID = $id; + $this->view->webhookType = $webhook->type; + $this->view->deptTree = $response['data']; + $this->view->webhookID = $id; $this->display(); } + public function ajaxGetFeishuDeptList($webhookID) + { + $webhook = $this->webhook->getById($webhookID); + $webhook->secret = json_decode($webhook->secret); + + if($_POST) + { + $this->app->loadClass('feishuapi', true); + $feishuApi = new feishuapi($webhook->secret->appId, $webhook->secret->appSecret); + $departmentID = $_POST['departmentID'] ? $_POST['departmentID'] : ''; + $depts = $feishuApi->getChildDeptTree($departmentID); + echo json_encode($depts, true); + } + else + { + $this->app->loadClass('feishuapi', true); + $feishuApi = new feishuapi($webhook->secret->appId, $webhook->secret->appSecret); + $depts = $feishuApi->getDeptTree(); + echo json_encode($depts, true); + } + } + /** * Send data by async. * diff --git a/module/webhook/css/choosedept.css b/module/webhook/css/choosedept.css new file mode 100644 index 0000000000..0ce961be3a --- /dev/null +++ b/module/webhook/css/choosedept.css @@ -0,0 +1,2 @@ +#notice {margin-bottom: 0px;} +#deptList {padding: 15px 0px;} diff --git a/module/webhook/lang/en.php b/module/webhook/lang/en.php index 0600471597..6dd9aefcce 100644 --- a/module/webhook/lang/en.php +++ b/module/webhook/lang/en.php @@ -104,6 +104,7 @@ $lang->webhook->note->typeList['dingding'] = 'Add a customized bot in dingding $lang->webhook->note->typeList['weixin'] = 'Add a customized bot in WeChat and get the webhook url.'; $lang->webhook->note->typeList['default'] = 'Get a webhook url from others'; -$lang->webhook->error = new stdclass(); -$lang->webhook->error->curl = 'Load php-curl in php.ini.'; -$lang->webhook->error->noDept = 'There is no department selected. Please choose department first.'; +$lang->webhook->error = new stdclass(); +$lang->webhook->error->curl = 'Load php-curl in php.ini.'; +$lang->webhook->error->noDept = 'There is no department selected. Please choose department first.'; +$lang->webhook->error->requestError = 'Request error!'; diff --git a/module/webhook/lang/zh-cn.php b/module/webhook/lang/zh-cn.php index af4d6920fc..d2341c9fe3 100644 --- a/module/webhook/lang/zh-cn.php +++ b/module/webhook/lang/zh-cn.php @@ -87,6 +87,7 @@ $lang->webhook->paramsList['comment'] = '备注'; $lang->webhook->paramsList['text'] = '操作内容'; $lang->webhook->confirmDelete = '您确认要删除该webhook吗?'; +$lang->webhook->loadPrompt = '友情提示:当部门数据较多时,数据加载可能需要较多时间;本列表优先展示一级部门数据,您可以通过点击一级部门标题,自动加载出该部门下的子部门数。'; $lang->webhook->trimWords = '了'; @@ -104,6 +105,7 @@ $lang->webhook->note->typeList['dingding'] = '请在钉钉中添加一个自定 $lang->webhook->note->typeList['weixin'] = '请在企业微信中添加一个自定义机器人,并将其webhook填写到此处。'; $lang->webhook->note->typeList['default'] = '从第三方系统获取webhook并填写到此处。'; -$lang->webhook->error = new stdclass(); -$lang->webhook->error->curl = '需要加载php-curl扩展。'; -$lang->webhook->error->noDept = '没有选择部门,请先选择同步部门。'; +$lang->webhook->error = new stdclass(); +$lang->webhook->error->curl = '需要加载php-curl扩展。'; +$lang->webhook->error->noDept = '没有选择部门,请先选择同步部门。'; +$lang->webhook->error->requestError = '请求错误!'; diff --git a/module/webhook/view/choosedept.html.php b/module/webhook/view/choosedept.html.php index b962c1ee2a..64f37acb81 100644 --- a/module/webhook/view/choosedept.html.php +++ b/module/webhook/view/choosedept.html.php @@ -17,6 +17,11 @@