checkBoard.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. <template>
  2. <div :class="$style.content">
  3. <dv-full-screen-container>
  4. <!-- 头部内容 -->
  5. <div :class="$style.header">
  6. <dv-decoration-8 :class="$style.left" />
  7. <dv-decoration-5 :class="$style.center" :dur="5"/>
  8. <dv-decoration-8 :class="$style.right" :reverse="true" />
  9. <div :class="$style.title">{{ titleName }}</div>
  10. <div :class="$style.time">
  11. <!-- <span>月份:</span> -->
  12. <dv-border-box-8>
  13. <el-date-picker
  14. v-model="month"
  15. type="month"
  16. value-format="yyyy-MM"
  17. format="yyyy-MM"
  18. placeholder="日期选择"
  19. style="width: 120px"
  20. :readonly="false"
  21. :editable="true"
  22. :clearable="false"
  23. @change="updateAll"
  24. />
  25. </dv-border-box-8>
  26. </div>
  27. <!-- <div :class="$style.back" @click.prevent="goBack()">
  28. <dv-border-box-8>返回</dv-border-box-8>
  29. </div> -->
  30. </div>
  31. <dv-border-box-1>
  32. <!-- topBar -->
  33. <top-bar v-if="topBarData.length" :info="topBarData" :color="colors"/>
  34. <!-- middleCard -->
  35. <middle-card v-if="middleCardData.flag" :info="middleCardData" :list="tableData"/>
  36. <!-- bottomCard -->
  37. <bottom-card v-if="bottomCardData.flag" :info="bottomCardData" />
  38. </dv-border-box-1>
  39. </dv-full-screen-container>
  40. </div>
  41. </template>
  42. <script>
  43. import screenfull from 'screenfull'
  44. import curdPost from '@/business/platform/form/utils/custom/joinCURD.js'
  45. import { colors, getRandomColor } from './data.js'
  46. export default {
  47. name: 'checkBoard',
  48. components: {
  49. topBar: () => import('./component/testing/topBar'),
  50. middleCard: () => import('./component/testing/middleCard'),
  51. bottomCard: () => import('./component/testing/bottomCard')
  52. },
  53. data() {
  54. const d = new Date()
  55. return {
  56. titleName: '检测大数据平台',
  57. year: d.toJSON().slice(0, 4),
  58. month: d.toJSON().slice(0, 7),
  59. today: d.toJSON().slice(0, 10),
  60. colors: [],
  61. topBarData: [],
  62. tableData: {
  63. header: [
  64. '检测项目',
  65. // '检测类型',
  66. '送检时间',
  67. '完成时间',
  68. '检测员'
  69. ],
  70. data: [],
  71. rowNum: 7,
  72. columnWidth: ['350','100','100','90'],
  73. waitTime: 1500
  74. },
  75. middleCardData: {
  76. acceptData:[],
  77. taskData: [],
  78. flag: false
  79. },
  80. bottomCardData: {
  81. flag: false
  82. },
  83. timer: null
  84. }
  85. },
  86. // beforeRouteEnter(to, from, next){
  87. // Promise.all([ ]).done(([ res ]) => {
  88. // console.log(res)
  89. // }).then(err => {
  90. // window.observer.trigger('error', err)
  91. // next()
  92. // })
  93. // },
  94. created() {
  95. if (screenfull.isEnabled && !screenfull.isFullscreen) {
  96. this.allView()
  97. }
  98. const sql = 'select lei_xing_ming_che from t_mjjclx'
  99. curdPost('sql', sql).then(res => {
  100. const { data = [] } = res.variables || {}
  101. this.acceptList = data.map(i => i.lei_xing_ming_che)
  102. this.updateAll()
  103. if (this.timer){
  104. clearInterval(this.timer)
  105. }
  106. this.timer = setInterval(() => {
  107. this.updateAll()
  108. }, 1000 * 10)
  109. })
  110. },
  111. beforeDestroy() {
  112. if (screenfull.isFullscreen) {
  113. screenfull.toggle()
  114. }
  115. clearInterval(this.timer)
  116. },
  117. methods: {
  118. allView() {
  119. // 默认显示全屏
  120. screenfull.request()
  121. },
  122. goBack() {
  123. this.$router.back(-1)
  124. },
  125. updateAll(e) {
  126. this.colors = [...colors].sort(() => Math.random() - 0.5)
  127. this.getTopBarData()
  128. this.getMiddleData()
  129. this.getBottomData()
  130. },
  131. // 获取topBar数据
  132. /**
  133. * 委托——t_mjwtsqb
  134. * 检测——t_jchzb
  135. * 任务——t_rwfpb
  136. * 报告——t_mjjcbg
  137. */
  138. getTopBarData() {
  139. let quarter = this.getDateRange('quarter')
  140. let week = this.getDateRange('week')
  141. // 获取委托数及受理数
  142. const sql = `select wt.month as month, wt.accepted as accepted, wt2.today as today, wt2.week as week, wt2.quarter as quarter, wt2.year as year, jc.total as jcTotal, jc.finished as jcFinish, rw.task as task, rw.finished as rwFinish, bg.report as report, bg.process as process, bg.approval as approval, bg.finished as bgFinish
  143. from
  144. (select count(id_) as month, count(zhuang_tai_ = '委托结束' or zhuang_tai_ = '已完成' or null) as accepted from t_mjwtsqb where create_time_ LIKE '${this.month}%') wt,
  145. (select count(create_time_ like '${this.today}' or null) as today, count(create_time_ between '${week.start}' and '${week.end}' or null) as week, count(create_time_ between '${quarter.start}' and '${quarter.end}' or null) as quarter, count(create_time_ like '${this.year}%' or null) as year from t_mjwtsqb) wt2,
  146. (select count(id_) as total, count(jian_ce_zhuang_ta = '已完成' or null) as finished from t_jchzb where create_time_ LIKE '${this.month}%') jc,
  147. (select count(id_) as task, count(zhuang_tai_ = '已完成' or null) as finished from t_rwfpb where create_time_ LIKE '${this.month}%') rw,
  148. (select count(id_) as report, count(zhuang_tai_ = '报告待审核' or null) as process, count(zhuang_tai_ = '报告待审批' or null) as approval, count(zhuang_tai_ = '完成' or null) as finished from t_mjjcbg where create_time_ LIKE '${this.month}%') bg`
  149. // console.log(sql)
  150. curdPost('sql', sql).then(res => {
  151. const data = res.variables.data
  152. // console.log(data)
  153. if ( data && data.length ) {
  154. const { month, accepted, approval, jcFinish, jcTotal, process, report, rwFinish, task, today, week, quarter, year, bgFinish } = data[0]
  155. this.middleCardData.taskData = [month, jcTotal, task, report]
  156. let result = [
  157. // {
  158. // title: '委托',
  159. // children: [
  160. // {
  161. // label: '年度',
  162. // value: year
  163. // },
  164. // {
  165. // label: '月度',
  166. // value: month
  167. // },
  168. // {
  169. // label: '本周',
  170. // value: week
  171. // },
  172. // {
  173. // label: '本日',
  174. // value: today
  175. // },
  176. // {
  177. // label: '本月受理',
  178. // value: accepted
  179. // }
  180. // ],
  181. // unit: '单'
  182. // },
  183. {
  184. title: '样品分配',
  185. children: [
  186. {
  187. label: '总数',
  188. value: task
  189. },
  190. {
  191. label: '未完成',
  192. value: task - rwFinish
  193. },
  194. {
  195. label: '已完成',
  196. value: rwFinish
  197. }
  198. ],
  199. unit: '件'
  200. },
  201. {
  202. title: '检测',
  203. children: [
  204. {
  205. label: '总数',
  206. value: jcTotal
  207. },
  208. {
  209. label: '未完成',
  210. value: jcTotal - jcFinish
  211. },
  212. {
  213. label: '已完成',
  214. value: jcFinish
  215. }
  216. ],
  217. unit: '项'
  218. },
  219. {
  220. title: '报告',
  221. children: [
  222. {
  223. label: '总数',
  224. value: report
  225. },
  226. {
  227. label: '待审核',
  228. value: process
  229. },
  230. {
  231. label: '待审批',
  232. value: approval
  233. },
  234. {
  235. label: '已发放',
  236. value: bgFinish
  237. }
  238. ],
  239. unit: '份'
  240. }
  241. ]
  242. this.topBarData = result
  243. }
  244. })
  245. },
  246. // 获取中间图表数据
  247. getMiddleData() {
  248. // 获取检测数据
  249. // const sql1 = `select tm.jian_ce_xiang_mu_, tm.jian_ce_lei_bie_, IFNULL(rw.qi_wang_wan_cheng, '') as qi_wang_wan_cheng, rw.zhuang_tai_, ipe.NAME_ from t_rwfpb rw, ibps_party_employee ipe, t_mjjcnlfw tm where rw.jian_ce_yuan_ = ipe.ID_ and rw.jian_ce_xiang_mu_ = tm.id_ and rw.create_time_ like '${this.month}%'`
  250. const sql1 = `select tm.jian_ce_xiang_mu_, IFNULL(jc.jian_ce_shi_jian_, '') as startDate, IFNULL(jc.update_time_, '') as endDate, ipe.NAME_ as names from ibps_party_employee ipe, t_mjjcnlfw tm, t_jchzb jc where jc.jian_ce_yuan_ = ipe.ID_ and jc.jian_ce_xiang_mu_ = tm.id_ and jc.jian_ce_zhuang_ta = '已完成' and jc.jian_ce_shi_jian_ like '${this.month}%' order by jc.jian_ce_shi_jian_ desc`
  251. // 获取检测受理类型数据
  252. let sqlStr = ''
  253. this.acceptList.forEach((item, index) => {
  254. sqlStr += `count(tm.jian_ce_lei_bie_ = '${item}' or null) as r${index}${index === this.acceptList.length - 1 ? '' : ', '}`
  255. })
  256. const sql2 = `select ${sqlStr} from t_jchzb tj, t_mjjcnlfw tm where tj.jian_ce_xiang_mu_ = tm.id_ and tj.create_time_ like '${this.month}%'`
  257. // console.log(sqlStr, sql2)
  258. // 获取检测月度年度任务完成情况数据
  259. const sql3 = `select rw.zhuang_tai_ as state, DATE_FORMAT(rw.create_time_, '%Y-%m-%d %H:%i:%s') as time from t_rwfpb rw where rw.create_time_ like '${this.year}%'`
  260. Promise.all([
  261. curdPost('sql', sql1),
  262. curdPost('sql', sql2),
  263. curdPost('sql', sql3)
  264. ]).then(([res1, res2, res3]) => {
  265. const data1 = res1.variables.data || []
  266. const data2 = res2.variables.data || []
  267. const data3 = res3.variables.data || []
  268. // console.log(data1, data2)
  269. this.tableData.data = []
  270. data1.forEach(item => {
  271. item.startDate = item.startDate ? item.startDate.slice(0, 10) : ''
  272. item.endDate = item.endDate ? item.endDate.slice(0, 10) : ''
  273. item.names = item.names ? this.replaceSecondLetter(item.names) : ''
  274. this.tableData.data.push(Object.values(item))
  275. })
  276. let result = []
  277. let tempRes = Object.values(data2[0])
  278. this.acceptList.forEach((item, index) => {
  279. let o = {
  280. name: item,
  281. value: tempRes[index] ? tempRes[index] : null
  282. }
  283. result.push(o)
  284. })
  285. // 对数据进行排序
  286. result.sort((a, b) => b.value - a.value)
  287. // 根据排序后数据重新生成图例
  288. const newRes = result.slice(0, 6).map(i => i.name)
  289. let task = new Array(12).fill(0)
  290. let complete = new Array(12).fill(0)
  291. data3.forEach(item => {
  292. const index = parseInt(item.time.slice(5,7)) - 1
  293. if (item.state === '已完成') {
  294. complete[index]++
  295. }
  296. task[index]++
  297. })
  298. let taskCount = task.reduce((pre, cur) => pre + cur)
  299. let completeCount = complete.reduce((pre, cur) => pre + cur)
  300. let year = [
  301. {
  302. name: '未完成',
  303. value: taskCount - completeCount
  304. },
  305. {
  306. name: '已完成',
  307. value: completeCount
  308. }
  309. ]
  310. this.middleCardData.acceptData = result.slice(0, 6)
  311. this.middleCardData.config = this.getOptions(newRes)
  312. this.middleCardData.task = task
  313. this.middleCardData.complete = complete
  314. this.middleCardData.year = year
  315. this.middleCardData.flag = true
  316. })
  317. },
  318. // 获取底部图表数据
  319. getBottomData() {
  320. // 获取检测委托受理情况数据
  321. const sql1 = `select tm.zhuang_tai_ as state, DATE_FORMAT(tm.create_time_, '%Y-%m-%d %H:%i:%s') as time from t_mjwtsqb tm where tm.create_time_ like '${this.year}%'`
  322. // 获取报告发放数据
  323. const sql2 = `select zhuang_tai_ as state, DATE_FORMAT(create_time_, '%Y-%m-%d %H:%i:%s') as time from t_mjjcbg where create_time_ LIKE '${this.year}%'`
  324. // 获取样品 收样/留样/不合格数量
  325. const sql4 = `select count(a.id_) as receive, count(a.shi_fou_liu_yang_ = '是' or null) as keep, count(a.yan_shou_zhuang_t = '残缺' or null) as incomplete, count(a.jie_yang_zhuang_t = '待确认' or null) as unReceive from (select id_, shi_fou_liu_yang_, yan_shou_zhuang_t, jie_yang_zhuang_t from t_mjypdjb where create_time_ like '${this.month}%' group by yang_pin_bian_hao) as a`
  326. const sql5 = `select count( CASE WHEN jie_yang_zhuang_t != '已确认' THEN 1 END ) AS unReceive FROM t_mjypb WHERE create_time_ LIKE '${this.month}%'`
  327. Promise.all([
  328. curdPost('sql', sql1),
  329. curdPost('sql', sql2),
  330. curdPost('sql', sql4),
  331. curdPost('sql',sql5)
  332. ]).then(([ res1, res2, res4,res5]) => {
  333. this.bottomCardData.flag = false
  334. const data1 = res1.variables && res1.variables.data
  335. const data2 = res2.variables && res2.variables.data
  336. const data4 = res4.variables && res4.variables.data
  337. const data5 = res5.variables && res5.variables.data
  338. // console.log(data1, data2, data3, data4,data5)
  339. let trust = new Array(12).fill(0)
  340. let accepted = new Array(12).fill(0)
  341. let reports = new Array(12).fill(0)
  342. let compile = new Array(12).fill(0)
  343. // let task = new Array(12).fill(0)
  344. // let complete = new Array(12).fill(0)
  345. data1.forEach(item => {
  346. const index = parseInt(item.time.slice(5,7)) - 1
  347. if (item.state === '委托结束' || item.state === '已完成') {
  348. accepted[index]++
  349. }
  350. trust[index]++
  351. })
  352. data2.forEach(item => {
  353. const index = parseInt(item.time.slice(5,7)) - 1
  354. if (item.state && item.state.includes('完成')) {
  355. reports[index]++
  356. }
  357. compile[index]++
  358. })
  359. // let taskCount = task.reduce((pre, cur) => pre + cur)
  360. // let completeCount = complete.reduce((pre, cur) => pre + cur)
  361. // let year = [
  362. // {
  363. // name: '未完成',
  364. // value: taskCount - completeCount
  365. // },
  366. // {
  367. // name: '已完成',
  368. // value: completeCount
  369. // }
  370. // ]
  371. let sample = [data5[0].unReceive, data4[0].receive, data4[0].incomplete, data4[0].keep]
  372. this.bottomCardData.trust = trust
  373. this.bottomCardData.accepted = accepted
  374. this.bottomCardData.reports = reports
  375. this.bottomCardData.compile = compile
  376. // this.bottomCardData.task = task
  377. // this.bottomCardData.complete = complete
  378. // this.bottomCardData.year = year
  379. this.bottomCardData.sample = sample
  380. this.bottomCardData.flag = true
  381. // console.log(this.bottomCardData)
  382. })
  383. },
  384. // 获取本周和本季度的开始和结束日期,以对象形式返回
  385. getDateRange(type) {
  386. let current = new Date()
  387. if (!['year', 'quarter', 'week'].includes(type)) {
  388. console.log('type is error')
  389. return
  390. }
  391. if (type === 'year') {
  392. return current.getFullYear()
  393. }
  394. if (type === 'quarter') {
  395. let year = current.getFullYear()
  396. let month = current.getMonth()
  397. const dateList = [
  398. {
  399. start: `${year}-01-01`,
  400. end: `${year}-03-31`
  401. },
  402. {
  403. start: `${year}-04-01`,
  404. end: `${year}-06-31`
  405. },
  406. {
  407. start: `${year}-07-01`,
  408. end: `${year}-09-31`
  409. },
  410. {
  411. start: `${year}-10-01`,
  412. end: `${year}-12-31`
  413. }
  414. ]
  415. let quarter = dateList[parseInt(month / 3)]
  416. return quarter
  417. }
  418. if (type === 'week') {
  419. let week = {}
  420. let currentWeek = current.getDay() === 0 ? 7 : current.getDay()
  421. let temp = new Date(current - (currentWeek - 1) * 86400000)
  422. week.start = new Date(current - (currentWeek - 1) * 86400000).toJSON().slice(0, 10)
  423. week.end = new Date((temp / 1000 + 6 * 86400) * 1000).toJSON().slice(0, 10)
  424. return week
  425. }
  426. },
  427. // 隐藏人员名字
  428. replaceSecondLetter (name) {
  429. if (!name || name.length < 2) {
  430. return name
  431. }
  432. const [firstLetter, secondLetter, ...rest] = name
  433. return `${firstLetter}*${rest.join('')}`
  434. },
  435. getOptions (data) {
  436. let res = {
  437. option: [],
  438. colorList: []
  439. }
  440. const colorGenerator = getRandomColor(this.colors)
  441. data.forEach(item => {
  442. let color = colorGenerator.next().value
  443. let obj = {
  444. name: item,
  445. textStyle: {
  446. color
  447. }
  448. }
  449. res.option.push(obj)
  450. res.colorList.push(color)
  451. })
  452. return res
  453. }
  454. }
  455. }
  456. </script>
  457. <style lang="scss" module>
  458. .content {
  459. width: 100%;
  460. height: 100%;
  461. background-color: #030409;
  462. position: absolute;
  463. color: #fff;
  464. z-index: 999;
  465. :global {
  466. #dv-full-screen-container {
  467. background-image: url('./img/bg.png');
  468. background-size: 100% 100%;
  469. box-shadow: 0 0 3px blue;
  470. display: flex;
  471. flex-direction: column;
  472. }
  473. .main-content {
  474. flex: 1;
  475. display: flex;
  476. flex-direction: column;
  477. }
  478. .block-left-right-content {
  479. flex: 1;
  480. display: flex;
  481. margin-top: 0.8%;
  482. }
  483. .block-top-bottom-content {
  484. flex: 1;
  485. display: flex;
  486. flex-direction: column;
  487. box-sizing: border-box;
  488. padding-left: 0.8%;
  489. }
  490. .block-top-content {
  491. height: 55%;
  492. display: flex;
  493. flex-grow: 0;
  494. box-sizing: border-box;
  495. padding-bottom: 0.8%;
  496. }
  497. }
  498. .header {
  499. position: relative;
  500. width: 100%;
  501. height: 100px;
  502. display: flex;
  503. justify-content: space-between;
  504. flex-shrink: 0;
  505. .left, .right {
  506. width: 25%;
  507. height: 60px;
  508. }
  509. .center {
  510. width: 40%;
  511. height: 60px;
  512. margin-top: 30px;
  513. }
  514. .title {
  515. position: absolute;
  516. font-size: 30px;
  517. font-weight: bold;
  518. left: 50%;
  519. top: 15px;
  520. transform: translateX(-50%);
  521. }
  522. .time, .back {
  523. width: 8%;
  524. cursor: pointer;
  525. height: 2.825rem;
  526. line-height: 2.825rem;
  527. text-align: center;
  528. margin-top: 2.5%;
  529. flex: 1;
  530. position: absolute;
  531. color: #ffffff;
  532. }
  533. .time {
  534. display: flex;
  535. // justify-content: flex-end;
  536. // width: 20%;
  537. left: 75%;
  538. :global {
  539. .el-input--small .el-input__inner {
  540. width: 100% !important;
  541. background: rgba(255, 255, 255, 0);
  542. border: none;
  543. color: #fff;
  544. font-size: 16px;
  545. }
  546. }
  547. }
  548. .back {
  549. left: 75%;
  550. }
  551. }
  552. }
  553. </style>