| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- <?php
- class pivotZen extends pivot
- {
- /**
- * 获取分组里一个透视表的默认方法和参数。
- * Get default method name and parameters of a pivot in a group.
- *
- * @param int $dimension
- * @param int $group
- * @access protected
- * @return array
- * @param int $dimensionID
- * @param int $groupID
- */
- protected function getDefaultMethodAndParams($dimensionID, $groupID)
- {
- $currentGroup = $this->loadModel('tree')->getByID($groupID);
- if(empty($currentGroup) || $currentGroup->grade != 1) return array('', '');
- $groups = $this->pivot->getGroupsByDimensionAndPath($dimensionID, $currentGroup->path);
- if(!$groups) return array('', '');
- foreach($groups as $group)
- {
- if($this->config->edition == 'open' && $group->grade == 1) continue;
- $pivotID = $this->pivot->getPivotID($group->id);
- if($pivotID) return array('show', "groupID={$group->id}&pivotID={$pivotID}");
- }
- $firstDimension = $this->loadModel('dimension')->getFirst();
- if($dimensionID != $firstDimension->id) return array('', '');
- if(empty($this->lang->pivotList->{$currentGroup->collector}->lists)) return array('', '');
- foreach($this->lang->pivotList->{$currentGroup->collector}->lists as $item)
- {
- $items = explode('|', $item);
- if(count($items) != 3) continue;
- $method = $items[2];
- if(common::hasPriv('pivot', $method)) return array($method, '');
- }
- return array('', '');
- }
- /**
- * 获取菜单项。
- * Get menu items.
- *
- * @param array $menus
- * @access protected
- * @return array
- */
- protected function getMenuItems($menus)
- {
- $items = array();
- foreach($menus as $menu)
- {
- if(isset($menu->url)) $items[] = $menu;
- }
- return $items;
- }
- /**
- * 获取侧边栏菜单。
- * Get sidebar menus of pivot.
- *
- * @param int $dimensionID
- * @param int $groupID
- * @access protected
- * @return array
- */
- protected function getSidebarMenus($dimensionID, $groupID)
- {
- $currentGroup = $this->loadModel('tree')->getByID($groupID);
- if(empty($currentGroup) || $currentGroup->grade != 1) return array();
- $groups = $this->pivot->getGroupsByDimensionAndPath($dimensionID, $currentGroup->path);
- if(!$groups) return array();
- $this->loadModel('bi');
- /* $firstAction = $this->loadModel('action')->getAccountFirstAction($this->app->user->account);
- $builtins = array_column($this->config->bi->builtin->pivots, 'id', 'id');*/
- $menus = array();
- foreach($groups as $group)
- {
- if($this->config->edition == 'open' && $group->grade == 1) continue;
- $pivots = $this->pivot->getAllPivotByGroupID($group->id);
- $pivots = $this->pivot->filterInvisiblePivot($pivots);
- $pivots = $this->loadModel('mark')->getMarks($pivots, 'pivot', 'view');
- $pivots = $this->pivot->isVersionChange($pivots, false);
- if(empty($pivots)) continue;
- if($group->grade > 1) $menus[] = (object)array('id' => $group->id, 'parent' => 0, 'name' => $group->name);
- if($pivots) $pivots = $this->pivot->processPivot($pivots, false);
- foreach($pivots as $pivot)
- {
- /* $this->setNewMark($pivot, $firstAction, $builtins);*/
- $params = helper::safe64Encode("groupID={$group->id}&pivotID={$pivot->id}&mark=view");
- $url = inlink('preview', "dimension={$dimensionID}&group={$currentGroup->id}&method=show¶ms={$params}");
- $menus[] = (object)array('id' => $group->id . '_' . $pivot->id, 'parent' => $group->grade > 1 ? $group->id : 0, 'name' => $pivot->name, 'url' => $url);
- }
- }
- $firstDimension = $this->loadModel('dimension')->getFirst();
- if($dimensionID != $firstDimension->id) return $menus;
- $builtinMenus = $this->getBuiltinMenus($dimensionID, $currentGroup);
- return array_merge($menus, $builtinMenus);
- }
- /**
- * 设置 “新” 标签。
- * Set new mark.
- *
- * @param object $pivot
- * @param object $firstAction
- * @access protected
- * @return void
- * @param mixed[] $builtins
- */
- protected function setNewMark($pivot, $firstAction, $builtins)
- {
- /* 如果不是内置透视表,则不需要展示“新”标签。*/
- /* If the pivot is not built-in, no need to display the "new" tag. */
- if($pivot->builtin == 0) return;
- /* 版本没有改变,此时讨论是不是新透视表。*/
- /* The version has not changed, so it is judged whether it is a new pivot. */
- if(!$pivot->versionChange)
- {
- if(!isset($builtins[$pivot->id])) return;
- if(!$pivot->mark && $pivot->createdDate < $firstAction->date) $pivot->mark = true;
- $isMainVersion = filter_var($pivot->version, FILTER_VALIDATE_INT) !== false;
- if(!$pivot->mark && $isMainVersion) $pivot->name = array('text' => $pivot->name, 'html' => $pivot->name . ' <span class="label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full">' . $this->lang->pivot->new . '</span>');
- }
- else
- {
- $maxVersion = $this->pivot->getMaxVersion($pivot->id);
- if(!$this->loadModel('mark')->isMark('pivot', $pivot->id, $maxVersion, 'view'))
- {
- $pivot->name = array('text' => $pivot->name, 'html' => $pivot->name . ' <span class="label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full">' . $this->lang->pivot->newVersion . '</span>');
- }
- }
- }
- /**
- * 在第一个维度上显示内置透视表。
- * Display the built-in pivots in the first dimension.
- *
- * @param int $dimensionID
- * @param object $currengGroup
- * @access protected
- * @return array
- * @param object $currentGroup
- */
- protected function getBuiltinMenus($dimensionID, $currentGroup)
- {
- $collector = $currentGroup->collector;
- if(empty($this->lang->pivotList->$collector->lists)) return array();
- $menus = array();
- ksort($this->lang->pivotList->$collector->lists);
- foreach($this->lang->pivotList->$collector->lists as $item)
- {
- $items = explode('|', $item);
- if(count($items) != 3) continue;
- $label = $items[0];
- $method = $items[2];
- if(!common::hasPriv('pivot', $method)) continue;
- $url = inlink('preview', "dimension={$dimensionID}&group={$currentGroup->id}&method={$method}");
- $menus[] = (object)array('id' => $method, 'parent' => 0, 'name' => $label, 'url' => $url);
- }
- return $menus;
- }
- /**
- * Preview pivots of a group.
- *
- * @param int $groupID
- * @param int $pivotID
- * @param string $mark
- * @param string|null $version
- * @access public
- * @return void
- */
- public function show($groupID, $pivotID, $mark = '', $version = null)
- {
- $this->pivot->checkAccess($pivotID, 'preview');
- if(is_null($version))
- {
- $pivot = $this->pivot->getByID($pivotID, true);
- }
- else
- {
- $pivot = $this->pivot->getPivotSpec($pivotID, $version, true);
- }
- $driver = $pivot->driver;
- $this->pivot->isVersionChange($pivot);
- if($mark && $pivot->builtin == 1)
- {
- $markVersion = $pivot->versionChange ? $this->pivot->getMaxVersion($pivot->id) : $pivot->version;
- if(!$this->loadModel('mark')->isMark('pivot', $pivot->id, $markVersion, 'view'))
- {
- $this->loadModel('mark')->setMark(array($pivot->id), 'pivot', $markVersion, 'view');
- }
- }
- if(isset($_POST['filterValues']) and $_POST['filterValues'])
- {
- $filterValuesData = is_string($this->post->filterValues) ? explode(',', $this->post->filterValues) : $this->post->filterValues;
- foreach($filterValuesData as $key => $value) $pivot->filters[$key]['default'] = $value;
- }
- $showOrigin = false;
- if(isset($_POST['summary']) and $_POST['summary']) $showOrigin = $this->post->summary == 'notuse';
- list($sql, $filterFormat) = $this->pivot->getFilterFormat($pivot->sql, $pivot->filters);
- $fields = json_decode(json_encode($pivot->fieldSettings), true);
- $langs = json_decode($pivot->langs, true) ?? array();
- $settingShowOrigin = isset($pivot->settings['summary']) && $pivot->settings['summary'] == 'notuse';
- if($showOrigin || $settingShowOrigin)
- {
- list($data, $configs) = $this->pivot->genOriginSheet($fields, $pivot->settings, $sql, $filterFormat, $langs, $driver);
- }
- else
- {
- list($data, $configs) = $this->pivot->genSheet($fields, $pivot->settings, $sql, $filterFormat, $langs, $driver);
- }
- $this->view->hasVersionMark = $this->loadModel('mark')->hasMark('pivot', $pivotID, 'all', 'version');
- $this->view->pivotName = $pivot->name;
- $this->view->title = $pivot->name;
- $this->view->currentMenu = $groupID . '_' . $pivot->id;
- $this->view->currentGroup = $groupID;
- $this->view->pivot = $pivot;
- $this->view->showOrigin = $showOrigin;
- $this->view->data = $data;
- $this->view->configs = $configs;
- }
- /**
- * Bug create pivot.
- *
- * @param string $begin
- * @param string $end
- * @param int $product
- * @param int $execution
- * @access public
- * @return void
- */
- public function bugCreate($begin = '', $end = '', $product = 0, $execution = 0)
- {
- $this->app->loadLang('bug');
- $begin = $begin ? date('Y-m-d', strtotime($begin)) : date('Y-m-01', strtotime('last month'));
- $end = date('Y-m-d', strtotime($end ?: 'now'));
- $this->view->title = $this->lang->pivot->bugCreate;
- $this->view->pivotName = $this->lang->pivot->bugCreate;
- $this->view->bugs = $this->pivot->getBugs($begin, $end, $product ? $product : 0, $execution ? $execution : 0);
- $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->executions = $this->pivot->getProjectExecutions();
- $this->view->products = $this->loadModel('product')->getPairs('', 0, '', 'all');
- $this->view->begin = $begin;
- $this->view->end = $end;
- $this->view->execution = $execution;
- $this->view->product = $product;
- $this->view->currentMenu = 'bugcreate';
- }
- /**
- * Bug assign pivot.
- *
- * @access public
- * @return void
- */
- public function bugAssign()
- {
- $this->session->set('productList', $this->app->getURI(true), 'product');
- $this->view->title = $this->lang->pivot->bugAssign;
- $this->view->pivotName = $this->lang->pivot->bugAssign;
- $this->view->bugs = $this->pivot->getBugAssign();
- $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->currentMenu = 'bugassign';
- }
- /**
- * Product information pivot.
- *
- * @params string $conditions
- * @access public
- * @return void
- * @param int|string $productID
- * @param string $conditions
- * @param string $productStatus
- * @param string $productType
- */
- public function productSummary($conditions = '', $productID = 0, $productStatus = 'normal', $productType = 'normal')
- {
- $this->app->loadLang('story');
- $this->app->loadLang('product');
- $this->app->loadLang('productplan');
- $this->session->set('productList', $this->app->getURI(true), 'product');
- $filters = array('productID' => $productID, 'productStatus' => $productStatus, 'productType' => $productType);
- $products = $this->pivot->getProducts($conditions, 'story', $filters);
- $this->view->filters = $filters;
- $this->view->title = $this->lang->pivot->productSummary;
- $this->view->pivotName = $this->lang->pivot->productSummary;
- $this->view->products = $this->processProductsForProductSummary($products);
- $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->conditions = $conditions;
- $this->view->currentMenu = 'productsummary';
- }
- /**
- * 把计划数组展开为独立的产品对象并添加跨行合并属性。
- * Expand the plans property to single product objects and add rowspan property.
- *
- * @params array $products
- * @access public
- * @return array
- * @param mixed[] $products
- */
- public function processProductsForProductSummary($products)
- {
- $productList = array();
- foreach($products as $product)
- {
- if(!isset($product->plans))
- {
- $product->planTitle = '';
- $product->planBegin = '';
- $product->planEnd = '';
- $product->storyDraft = 0;
- $product->storyReviewing = 0;
- $product->storyActive = 0;
- $product->storyChanging = 0;
- $product->storyClosed = 0;
- $product->storyTotal = 0;
- $productList[] = $product;
- continue;
- }
- $first = true;
- foreach($product->plans as $plan)
- {
- $newProduct = clone $product;
- $newProduct->planTitle = $plan->title;
- $newProduct->planBegin = $plan->begin == '2030-01-01' ? $this->lang->productplan->future : $plan->begin;
- $newProduct->planEnd = $plan->end == '2030-01-01' ? $this->lang->productplan->future : $plan->end;
- $newProduct->storyDraft = isset($plan->status['draft']) ? $plan->status['draft'] : 0;
- $newProduct->storyReviewing = isset($plan->status['reviewing']) ? $plan->status['reviewing'] : 0;
- $newProduct->storyActive = isset($plan->status['active']) ? $plan->status['active'] : 0;
- $newProduct->storyChanging = isset($plan->status['changing']) ? $plan->status['changing'] : 0;
- $newProduct->storyClosed = isset($plan->status['closed']) ? $plan->status['closed'] : 0;
- $newProduct->storyTotal = $newProduct->storyDraft + $newProduct->storyReviewing + $newProduct->storyActive + $newProduct->storyChanging + $newProduct->storyClosed;
- if($first) $newProduct->rowspan = count($newProduct->plans);
- $productList[] = $newProduct;
- $first = false;
- }
- }
- return $productList;
- }
- /**
- * Project deviation pivot.
- *
- * @param string $begin
- * @param string $end
- * @access public
- * @return void
- */
- public function projectDeviation($begin = '', $end = '')
- {
- $this->session->set('executionList', $this->app->getURI(true), 'execution');
- $begin = $begin ? date('Y-m-d', strtotime($begin)) : date('Y-m-01');
- $end = $end ? date('Y-m-d', strtotime($end)) : date('Y-m-d', strtotime(date('Y-m-01', strtotime('next month')) . ' -1 day'));
- $this->view->title = $this->lang->pivot->projectDeviation;
- $this->view->pivotName = $this->lang->pivot->projectDeviation;
- $this->view->executions = $this->pivot->getExecutions($begin, $end);
- $this->view->begin = $begin;
- $this->view->end = $end;
- $this->view->currentMenu = 'projectdeviation';
- }
- /**
- * 组织透视表。
- * Workload pivot.
- *
- * @param string $begin
- * @param string $end
- * @param int $days
- * @param float $workhour
- * @param int $dept
- * @param string $assign
- * @access public
- * @return void
- */
- public function workload($begin = '', $end = '', $days = 0, $workhour= 0, $dept = 0, $assign = 'assign')
- {
- $this->app->loadConfig('execution');
- $this->session->set('executionList', $this->app->getURI(true), 'execution');
- $begin = $begin ? strtotime($begin) : time();
- $end = $end ? strtotime($end) : time() + (7 * 24 * 3600);
- $end += 24 * 3600;
- $beginWeekDay = date('w', $begin);
- $begin = date('Y-m-d', $begin);
- $end = date('Y-m-d', $end);
- if(empty($workhour)) $workhour = $this->config->execution->defaultWorkhours;
- $diffDays = helper::diffDate($end, $begin);
- if($days > $diffDays) $days = $diffDays;
- if(empty($days))
- {
- $weekDay = $beginWeekDay;
- $days = $diffDays;
- for($i = 0; $i < $diffDays; $i++, $weekDay++)
- {
- $weekDay = $weekDay % 7;
- if(($this->config->execution->weekend == 2 && $weekDay == 6) || $weekDay == 0) $days--;
- }
- }
- $allHour = $workhour * $days;
- $users = $this->loadModel('user')->getPairs('noletter|noclosed');
- $this->view->title = $this->lang->pivot->workload;
- $this->view->pivotName = $this->lang->pivot->workload;
- $this->view->workload = $this->pivot->getWorkload($dept, $assign, $users, $allHour);
- $this->view->depts = $this->loadModel('dept')->getOptionMenu();
- $this->view->users = $users;
- $this->view->dept = $dept;
- $this->view->begin = $begin;
- $this->view->end = date('Y-m-d', strtotime($end) - 24 * 3600);
- $this->view->days = $days;
- $this->view->workhour = $workhour;
- $this->view->assign = $assign;
- $this->view->currentMenu = 'workload';
- }
- /**
- * 获取下钻列配置。
- * Get drill.
- *
- * @param int $pivotID
- * @param string $colName
- * @param string $status
- * @access public
- * @return object
- * @param string $version
- */
- public function getDrill($pivotID, $version, $colName, $status = 'published')
- {
- if($status == 'published')
- {
- $drills = $this->pivot->fetchPivotDrills($pivotID, $version, $colName);
- return reset($drills);
- }
- $cache = $this->getCache($pivotID);
- $drills = json_decode(json_encode($cache->drills), true);
- foreach($drills as $drill)
- {
- $drill = (object)$drill;
- $drill->condition = (array)$drill->condition;
- if($drill->field == $colName) return $drill;
- }
- return new stdclass();
- }
- /**
- * 获取筛选器的下拉选项 URL。
- * Get filter options url.
- *
- * @param array $filter
- * @access public
- * @return string
- * @param string $sql
- * @param mixed[] $fieldSettings
- */
- public function getFilterOptionUrl($filter, $sql = '', $fieldSettings = array())
- {
- $field = $filter['field'];
- $from = zget($filter, 'from', 'result');
- $value = zget($filter, 'default', '');
- $values = is_array($value) ? implode(',', $value) : $value;
- $url = helper::createLink('pivot', 'ajaxGetSysOptions', "search={search:base64}");
- $data = array();
- $data['values'] = $values;
- if($from == 'query')
- {
- $data['type'] = $filter['typeOption'];
- }
- else
- {
- $fieldSetting = $fieldSettings[$field];
- $fieldSetting = (array)$fieldSetting;
- $fieldType = $fieldSetting['type'];
- $data['type'] = $fieldType;
- $data['object'] = $fieldSetting['object'];
- $data['field'] = $fieldType != 'options' && $fieldType != 'object' ? $field : $fieldSetting['field'];
- $data['saveAs'] = zget($filter, 'saveAs', $field);
- $data['sql'] = $sql;
- $data['originalField'] = zget($fieldSetting, 'field', $data['field']);
- }
- return (object)array('url' => $url, 'method' => 'post', 'data' => $data);
- }
- }
|