statisticsSection.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <template>
  2. <div class="drawer-statistics" :class="{'drawer-padding': !show}">
  3. <transition name="fade-drawer">
  4. <div v-show="show" class="statistics">
  5. <div class="statistics-data">
  6. <h2>{{ title }}统计</h2>
  7. <div class="data-main">
  8. <div v-for="(item,index) in statisticsList" :key="title+'-statistics-'+index" class="data-item" :class="{'active': clickItem === index }" @click="changeData(item.idList,item.label);clickItem=index">
  9. <label>
  10. {{ item.label }}
  11. <template v-if="(title === '需求' || title ==='任务') && index<7">
  12. <el-tooltip class="item" effect="dark" :content="tips[title][index]" placement="top">
  13. <i class="el-icon-info" />
  14. </el-tooltip>
  15. </template>
  16. </label>
  17. <div
  18. class="number"
  19. :class="{'color-red': (index === 0 || index === 1) && item.total>0}"
  20. >
  21. {{ item.total }}
  22. </div>
  23. </div>
  24. </div>
  25. </div>
  26. <div v-if="title !=='缺陷'" class="statistics-chart">
  27. <!-- <h2>未上线{{ title }}状态分布</h2> -->
  28. <el-radio-group v-model="itemType" @change="onChangeTagRadio">
  29. <el-radio-button label="0">未上线{{ title }}状态分布</el-radio-button>
  30. <el-radio-button label="1">本周{{ title }}状态流入图</el-radio-button>
  31. </el-radio-group>
  32. <h3 @click="getAll()">总数:<span>{{ totalTask }}</span></h3>
  33. <div class="chart-contain">
  34. <status-stay-chart :chart-data="echartsOption" @onClick="chartChange" />
  35. <!-- <normal-echart v-if="echartsOption" :chart-id="type+title" :option="echartsOption" @onClick="chartChange" /> -->
  36. </div>
  37. </div>
  38. <div v-if="title ==='缺陷'" class="statistics-chart">
  39. <div class="two-title">
  40. <h2 v-if="type === 'person'">我提报的-未完成缺陷状态分布</h2>
  41. <h2 v-if="type === 'person'">提给我的-未完成缺陷状态分布</h2>
  42. <h2 v-if="type === 'team'">团队提报的-未完成缺陷状态分布</h2>
  43. <h2 v-if="type === 'team'">提给团队的-未完成缺陷状态分布</h2>
  44. </div>
  45. <div class="two-chart-contain">
  46. <div class="chart-contain">
  47. <normal-echart v-if="echartsOption" :chart-id="type+title+'1'" :option="echartsOption" @onClick="chartChange" />
  48. </div>
  49. <div class="chart-contain">
  50. <normal-echart v-if="echartsOption2" :chart-id="type+title+'2'" :option="echartsOption2" @onClick="chartChange" />
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </transition>
  56. <div class="drawer" @click="show = !show">
  57. <i v-show="show" class="el-icon-arrow-up" />
  58. <i v-show="!show" class="el-icon-arrow-down" />
  59. </div>
  60. </div>
  61. </template>
  62. <script>
  63. import normalEchart from '@/components/chart/normalEchart'
  64. import statusStayChart from '@/components/chart/statusStayChart'
  65. export default {
  66. name: 'StatisticsSectionVue',
  67. components: {
  68. normalEchart,
  69. statusStayChart
  70. },
  71. props: {
  72. searchForm: { // 搜索项的信息
  73. type: Object,
  74. default: () => {
  75. return {
  76. teamId: null,
  77. bizId: null
  78. }
  79. },
  80. required: true
  81. },
  82. type: { // 个人还是团队
  83. type: String,
  84. default: 'team',
  85. required: false
  86. },
  87. title: {
  88. type: String,
  89. default: '需求',
  90. required: false
  91. },
  92. requestObj: { // 请求的接口
  93. type: Object,
  94. default: () => null,
  95. required: false
  96. }
  97. },
  98. data() {
  99. return {
  100. show: true,
  101. statisticsList: [],
  102. echartsOption: null,
  103. echartsOption2: null,
  104. totalTask: 0, // 所有总数
  105. totalIdList: 0, // 所有总数的idList
  106. itemType: '0', // 0: 未上线的需求分布 1: 本周状态流入图
  107. tips: {
  108. '需求': [
  109. '交付日期为今天,且状态仍未变更为“已上线”的需求数量(不包含当前状态为hold的需求)。',
  110. '已过交付日期,状态仍未变更为“已上线”的需求数量(不包含当前状态为hold的需求)。',
  111. '交付日期在本周内的需求数量(不包含当前状态为hold的需求)。',
  112. '交付日期在本周,且状态仍未变更为“已上线”的需求数量(不包含当前状态为hold的需求)。',
  113. '最近一次变更状态为“已上线”是在本周,且当前状态为“已上线”或“已完成”的需求',
  114. '交付日期在下周的需求数量(不包含当前状态为hold的需求)。',
  115. '当前状态为“已上线”及后续状态的需求'
  116. ],
  117. '任务': [
  118. '交付日期为今天,且状态仍未变更为“已上线”的任务数量(不包含当前状态为hold的任务)。',
  119. '已过交付日期,状态仍未变更为“已上线”的任务数量(不包含当前状态为hold的任务)。',
  120. '交付日期在本周内的任务数量(不包含当前状态为hold的任务)。',
  121. '交付日期在本周,且状态仍未变更为“已上线”的任务数量(不包含当前状态为hold的任务)。',
  122. '最近一次变更状态为“已上线”是在本周,且当前状态为“已上线”的任务',
  123. '交付日期在下周任务数量(不包含当前状态为hold的任务)。',
  124. '当前状态为“已上线”的任务'
  125. ]
  126. },
  127. clickItem: 0
  128. }
  129. },
  130. watch: {
  131. searchForm: {
  132. handler(newV) {
  133. this.initData()
  134. },
  135. deep: true,
  136. immediate: true
  137. },
  138. title: {
  139. handler(newV) {
  140. this.clickItem = 0
  141. this.initData()
  142. }
  143. // immediate: true
  144. }
  145. },
  146. methods: {
  147. initData() { // 初始化
  148. if (this.requestObj) {
  149. const { requestData, requestChart } = this.requestObj
  150. this.getData(requestData)
  151. if (this.title === '缺陷') {
  152. this.getChart(requestChart, '3')
  153. this.getChart(requestChart, '5')
  154. } else {
  155. this.getChart(requestChart, this.itemType)
  156. }
  157. }
  158. },
  159. onChangeTagRadio(e) {
  160. const { requestChart } = this.requestObj
  161. this.getChart(requestChart, this.itemType)
  162. },
  163. async getData(requestUrl) { // 获取顶部数据
  164. const res = await requestUrl({ teamSearchInfo: this.searchForm })
  165. if (res.code === 200) {
  166. this.statisticsList = res.data || []
  167. if (this.statisticsList.length > 0) {
  168. const show = this.statisticsList[0].total + this.statisticsList[1].total > 0
  169. this.$emit('showTips', this.title, show)
  170. }
  171. // 如果是点击左边6个区域的,保留idList,如果点击是图表,默认回到左边第一个区域中的idList
  172. if (this.clickItem < 0) {
  173. this.clickItem = 0
  174. this.changeData(this.statisticsList[0].idList, this.statisticsList[0].label)
  175. } else {
  176. this.changeData(this.statisticsList[this.clickItem].idList, this.statisticsList[this.clickItem].label)
  177. }
  178. }
  179. },
  180. async getChart(requestUrl, type) { // 获取图表数据
  181. const res = await requestUrl({ teamSearchInfo: this.searchForm, type: type })
  182. if (type === '3') {
  183. this.echartsOption = this.setChart(res.data)
  184. } else if (type === '5') {
  185. this.echartsOption2 = this.setChart(res.data)
  186. } else {
  187. const res = await requestUrl({ teamSearchInfo: this.searchForm, type })
  188. this.totalTask = res.data.total
  189. this.totalIdList = res.data.idList
  190. this.echartsOption = { ...res.data, type: this.itemType }
  191. }
  192. },
  193. setChart(chartData) { // 设置图表options
  194. const childArr = chartData.xaxis.map((item, index) => {
  195. return {
  196. value: chartData.yaxis[0] && chartData.yaxis[0].data[index] || 0,
  197. idList: chartData.yaxis[0] && chartData.yaxis[0].idList[index] || []
  198. }
  199. })
  200. const option = {
  201. color: ['#3AA1FF'],
  202. tooltip: { trigger: 'axis', axisPointer: { type: 'line' }}, // 默认为直线,可选为:'line' | 'shadow'
  203. grid: { left: '0', right: '0', top: '10%', bottom: '0', containLabel: true },
  204. xAxis: [{ type: 'category', data: chartData.xaxis, axisLabel: { interval: 0, rotate: 15 }, axisTick: { alignWithLabel: true }}],
  205. yAxis: [{ type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { type: 'dashed' }}}],
  206. series: [{
  207. name: '数量', type: 'bar', barWidth: '20px', data: childArr,
  208. itemStyle: { normal: { label: { show: true, formatter: '{c}', position: 'top' }}}
  209. }]
  210. }
  211. return option
  212. },
  213. getAll() {
  214. this.clickItem = -1
  215. this.changeData(this.totalIdList, `未上线的`)
  216. },
  217. chartChange(params) { // 点击图表产生触发列表更改
  218. let idList = params.data.idList || []
  219. // 本周需求状态流入图需要特殊处理。循环出对应下标的idlist
  220. if (this.itemType === '1') {
  221. // console.log(this.echartsOption.xaxis)
  222. const dataIndex = params.dataIndex
  223. this.echartsOption.yaxis.forEach(t => {
  224. idList = [...idList, ...t.idList[dataIndex]]
  225. })
  226. }
  227. this.clickItem = -1
  228. this.changeData(idList, params.name)
  229. },
  230. changeData(idList, name) { // 点击顶部数据触发列表更改
  231. this.$emit('change', this.title, idList, name)
  232. }
  233. }
  234. }
  235. </script>
  236. <style scoped lang="scss">
  237. .drawer-statistics {
  238. position: relative;
  239. width: 100%;
  240. padding-bottom: 1px;
  241. }
  242. .drawer-padding {
  243. padding-bottom: 13px;
  244. }
  245. //.fade-drawer-enter-active {
  246. // transition: all 1.5s ease
  247. //}
  248. //.fade-drawer-leave-active {s
  249. // transition: all 1.5s ease
  250. //}
  251. //.fade-drawer-enter, .fade-drawer-leave-to {
  252. // transition: all 1.5s ease;
  253. //}
  254. .statistics {
  255. position: relative;
  256. width: 100%;
  257. height: 474px;
  258. padding: 27px 35px;
  259. display: grid;
  260. grid-template-columns: 40% 60%;
  261. h2 {
  262. color: #333333;
  263. font-size: 16px;
  264. margin-bottom: 15px;
  265. font-weight: bold;
  266. }
  267. h3 {
  268. cursor: pointer;
  269. color: #999999;
  270. font-size: 18px;
  271. margin-bottom: 0px;
  272. span {
  273. color:#409EFF;
  274. font-size: 26px;
  275. }
  276. }
  277. }
  278. .statistics-data {
  279. .data-main{
  280. width: 80%;
  281. display: grid;
  282. grid-template-columns: repeat(2,190px);
  283. grid-column-gap: 30px;
  284. grid-template-rows: repeat(4,80px);
  285. grid-row-gap: 20px;
  286. }
  287. .data-item {
  288. cursor:pointer;
  289. box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.2);
  290. border-radius: 5px;
  291. display: grid;
  292. grid-template-rows: repeat(2,50%);
  293. align-items: center;
  294. padding: 5px 3px 5px 11px;
  295. label {
  296. font-weight: 400;
  297. color: #666666;
  298. cursor:pointer;
  299. }
  300. .number {
  301. font-weight: 500;
  302. color: #333333;
  303. font-size: 26px;
  304. }
  305. .color-red {
  306. color:#E02020;
  307. }
  308. }
  309. .active {
  310. border: 1px solid #409EFF;
  311. box-shadow: 0px 6px 12px rgba(64, 158, 255, 0.2);
  312. }
  313. }
  314. .statistics-chart {
  315. .two-title {
  316. width: 100%;
  317. display: grid;
  318. grid-template-columns: repeat(2,47.5%);
  319. grid-column-gap: 5%;
  320. }
  321. .two-chart-contain {
  322. width: 100%;
  323. height: 100%;
  324. display: grid;
  325. grid-template-columns: repeat(2,47.5%);
  326. grid-column-gap: 5%;
  327. }
  328. .chart-contain {
  329. width: 100%;
  330. height: 360px;
  331. }
  332. }
  333. .drawer-statistics:after {
  334. content: '';
  335. width: 100%;
  336. height: 14px;
  337. background-color: #F2F3F6;
  338. position: absolute;
  339. left: 0;
  340. bottom: 0;
  341. }
  342. .drawer {
  343. width: 26px;
  344. height: 12px;
  345. left: 50%;
  346. position: absolute;
  347. bottom: 1px;
  348. transform: translateX(-50%);
  349. z-index: 98;
  350. display: flex;
  351. justify-content: center;
  352. align-items: center;
  353. color: #666666;
  354. font-weight: bold;
  355. background-color: #ffffff;
  356. // border-bottom: 1px solid #999999;
  357. // border-left: 1px solid #999999;
  358. // border-right: 1px solid #999999;
  359. box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
  360. border-bottom-left-radius: 2px;
  361. border-bottom-right-radius: 2px;
  362. }
  363. .drawer-pull {
  364. top: 1px;
  365. }
  366. </style>