singlestatisticblock.html.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. * The product statistic block view file of block module of ZenTaoPMS.
  4. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  5. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  6. * @author Yuting Wang <wangyuting@easycorp.ltd>
  7. * @package block
  8. * @link https://www.zentao.net
  9. */
  10. namespace zin;
  11. $app->loadLang('execution');
  12. $isEn = $app->getClientLang() == 'en';
  13. $doneData = array();
  14. $openedData = array();
  15. foreach($product->monthFinish as $date => $count)
  16. {
  17. if($date == date('Y-m'))
  18. {
  19. $product->monthFinish[$lang->datepicker->dpText->TEXT_THIS_MONTH] = $count;
  20. unset($product->monthFinish[$date]);
  21. }
  22. $doneData[] = $count;
  23. }
  24. foreach($product->monthCreated as $date => $count)
  25. {
  26. if($date == date('Y-m'))
  27. {
  28. $product->monthCreated[$lang->datepicker->dpText->TEXT_THIS_MONTH] = $count;
  29. unset($product->monthCreated[$date]);
  30. }
  31. $openedData[] = $count;
  32. }
  33. panel
  34. (
  35. to::titleSuffix
  36. (
  37. icon
  38. (
  39. setClass('text-light text-sm cursor-pointer'),
  40. toggle::tooltip
  41. (
  42. array
  43. (
  44. 'title' => sprintf($lang->block->tooltips['metricTime'], $metricTime),
  45. 'placement' => $isEn ? 'bottom-end' : 'bottom',
  46. 'type' => 'white',
  47. 'className' => 'text-dark border border-light leading-5'
  48. )
  49. ),
  50. 'help'
  51. )
  52. ),
  53. setClass('singleproductstatistic-block ' . ($longBlock ? 'block-long' : 'block-sm')),
  54. set::headingClass('border-b'),
  55. set::title($block->title),
  56. div
  57. (
  58. setClass("flex h-full overflow-hidden " . ($longBlock ? '' : 'col')),
  59. cell
  60. (
  61. setClass('flex-1'),
  62. $longBlock ? set('width', '70%') : null,
  63. div
  64. (
  65. setClass('flex h-full ' . ($longBlock ? '' : 'col')),
  66. cell
  67. (
  68. $longBlock ? set::width('40%') : setClass('my-4'),
  69. setClass('flex items-center'),
  70. setClass($longBlock ? 'p-4' : 'px-4'),
  71. center
  72. (
  73. setClass('flex-1 gap-4'),
  74. progressCircle
  75. (
  76. set::percent($product->storyDeliveryRate),
  77. set::size($isEn ? 140 : 112),
  78. set::text(false),
  79. set::circleWidth(0.06),
  80. div(span(setClass('text-2xl font-bold'), $product->storyDeliveryRate), '%'),
  81. div
  82. (
  83. setClass('row text-sm text-gray items-center gap-1'),
  84. $lang->block->productstatistic->deliveryRate,
  85. icon
  86. (
  87. setClass('text-light text-sm'),
  88. toggle::tooltip
  89. (
  90. array
  91. (
  92. 'title' => $lang->block->tooltips['deliveryRate'],
  93. 'placement' => 'bottom-end',
  94. 'type' => 'white',
  95. 'className' => 'text-dark border border-light leading-5'
  96. )
  97. ),
  98. 'help'
  99. )
  100. )
  101. ),
  102. div
  103. (
  104. setClass('flex h-full story-num w-44'),
  105. cell
  106. (
  107. setClass('flex-1 text-center'),
  108. div
  109. (
  110. common::hasPriv('product', 'browse') && $product->totalStories ? a
  111. (
  112. set('href', helper::createLink('product', 'browse', "productID={$product->id}&branch=all&browseType=allStory&param=0&storyType=story")),
  113. $product->totalStories
  114. ) : span
  115. (
  116. $product->totalStories
  117. )
  118. ),
  119. div
  120. (
  121. span
  122. (
  123. setClass('text-sm text-gray'),
  124. $lang->block->productstatistic->effectiveStory
  125. )
  126. )
  127. ),
  128. cell
  129. (
  130. setClass('flex-1 text-center'),
  131. div
  132. (
  133. common::hasPriv('product', 'browse') && $product->closedStories ? a
  134. (
  135. set('href', helper::createLink('product', 'browse', "productID={$product->id}&branch=all&browseType=closedstory&param=0&storyType=story")),
  136. $product->closedStories
  137. ) : span
  138. (
  139. $product->closedStories
  140. )
  141. ),
  142. div
  143. (
  144. span
  145. (
  146. setClass('text-sm text-gray'),
  147. $lang->block->productstatistic->delivered
  148. )
  149. )
  150. ),
  151. cell
  152. (
  153. setClass('flex-1 text-center'),
  154. div
  155. (
  156. common::hasPriv('product', 'browse') && $product->unclosedStories ? a
  157. (
  158. set('href', helper::createLink('product', 'browse', "productID={$product->id}&branch=all&browseType=unclosed&param=0&storyType=story")),
  159. $product->unclosedStories
  160. ) : span
  161. (
  162. $product->unclosedStories
  163. )
  164. ),
  165. div
  166. (
  167. span
  168. (
  169. setClass('text-sm text-gray'),
  170. $lang->block->productstatistic->unclosed
  171. )
  172. )
  173. )
  174. )
  175. )
  176. ),
  177. cell
  178. (
  179. $longBlock ? set('width', '60%') : null,
  180. setClass('py-4'),
  181. div
  182. (
  183. setClass('border-r'),
  184. div
  185. (
  186. setClass('px-4 pb-2'),
  187. $lang->block->productstatistic->storyStatistics
  188. ),
  189. div
  190. (
  191. setClass('px-4'),
  192. span
  193. (
  194. setClass('border-r pr-2 text-sm text-gray'),
  195. html(sprintf($lang->block->productstatistic->monthDone, !empty($product->monthFinish[$lang->datepicker->dpText->TEXT_THIS_MONTH]) ? $product->monthFinish[$lang->datepicker->dpText->TEXT_THIS_MONTH] : 0))
  196. ),
  197. span
  198. (
  199. setClass('pl-2 text-sm text-gray'),
  200. html(sprintf($lang->block->productstatistic->monthOpened, !empty($product->monthCreated[$lang->datepicker->dpText->TEXT_THIS_MONTH]) ? $product->monthCreated[$lang->datepicker->dpText->TEXT_THIS_MONTH] : 0))
  201. )
  202. ),
  203. div
  204. (
  205. setClass('px-4 py-2 chart'),
  206. echarts
  207. (
  208. set::color(array('#2B80FF', '#17CE97')),
  209. set::width('100%'),
  210. set::height(170),
  211. set::grid(array('left' => '10px', 'top' => '30px', 'right' => '0', 'bottom' => '30px', 'containLabel' => true)),
  212. set::legend(array('show' => true, 'right' => '0')),
  213. set::xAxis(array('type' => 'category', 'data' => array_keys($product->monthFinish), 'splitLine' => array('show' => false), 'axisTick' => array('alignWithLabel' => true, 'interval' => '0'))),
  214. set::yAxis(array('type' => 'value', 'name' => '个', 'splitLine' => array('show' => false), 'axisLine' => array('show' => true, 'color' => '#DDD'))),
  215. set::series
  216. (
  217. array
  218. (
  219. array
  220. (
  221. 'type' => 'line',
  222. 'name' => $lang->block->productstatistic->opened,
  223. 'data' => $openedData,
  224. 'emphasis' => array('label' => array('show' => true))
  225. ),
  226. array
  227. (
  228. 'type' => 'line',
  229. 'name' => $lang->block->productstatistic->done,
  230. 'data' => $doneData,
  231. 'emphasis' => array('label' => array('show' => true))
  232. )
  233. )
  234. )
  235. )
  236. )
  237. )
  238. )
  239. )
  240. ),
  241. ($product->newPlan || $product->newExecution || $product->newRelease) ? cell
  242. (
  243. set('width', '30%'),
  244. setClass('p-4'),
  245. div
  246. (
  247. setClass('pb-2'),
  248. span($lang->block->productstatistic->news)
  249. ),
  250. $product->newPlan ? div
  251. (
  252. setClass('pb-4' . ($longBlock ? '' : 'flex')),
  253. div(span(setClass('text-sm text-gray'), $lang->block->productstatistic->newPlan)),
  254. div
  255. (
  256. setClass($longBlock ? 'py-1' : 'pl-2'),
  257. common::hasPriv('productplan', 'view') ? a
  258. (
  259. set('href', helper::createLink('productplan', 'view', "planID={$product->newPlan->id}")),
  260. $product->newPlan->title
  261. ) : span
  262. (
  263. $product->newPlan->title
  264. ),
  265. span
  266. (
  267. setClass('label gray-pale rounded-full ml-2 px-1'),
  268. zget($lang->productplan->statusList, $product->newPlan->status)
  269. )
  270. )
  271. ) : null,
  272. $product->newExecution ? div
  273. (
  274. setClass('pb-4 ' . ($longBlock ? '' : 'flex')),
  275. div(span(setClass('text-sm text-gray'), $lang->block->productstatistic->newExecution)),
  276. div
  277. (
  278. setClass($longBlock ? 'py-1' : 'pl-2'),
  279. common::hasPriv('execution', 'task') ? a
  280. (
  281. set('href', helper::createLink('execution', 'task', "executionID={$product->newExecution->id}")),
  282. $product->newExecution->name
  283. ) : span
  284. (
  285. $product->newExecution->name
  286. ),
  287. span
  288. (
  289. setClass('label important-pale rounded-full ml-2'),
  290. zget($lang->execution->statusList, $product->newExecution->status)
  291. )
  292. )
  293. ) : null,
  294. $product->newRelease ? div
  295. (
  296. setClass($longBlock ? '' : 'flex'),
  297. div(span(setClass('text-sm text-gray'), $lang->block->productstatistic->newRelease)),
  298. div
  299. (
  300. setClass($longBlock ? 'py-1' : 'pl-2'),
  301. common::hasPriv('release', 'view') ? a
  302. (
  303. set('href', helper::createLink('release', 'view', "releaseID={$product->newRelease->id}")),
  304. $product->newRelease->name
  305. ) : span
  306. (
  307. $product->newRelease->name
  308. ),
  309. span
  310. (
  311. setClass('label rounded-full ml-2 ' . ($product->newRelease->status == 'normal' ? 'success-pale' : 'gray-pale')),
  312. zget($lang->release->statusList, $product->newRelease->status)
  313. )
  314. )
  315. ) : null
  316. ) : null
  317. )
  318. );
  319. render();