workMeeting.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. <template>
  2. <div class="workMeeting">
  3. <div class="page-query-core">
  4. <query
  5. :show="['company', 'floor', 'time']"
  6. :query-data.sync="queryData"
  7. :reset="reset"
  8. :floor-options="floorOptions"
  9. :search="search"
  10. style="
  11. background: #fff;
  12. height: 60px;
  13. padding: 10px;
  14. border-radius: 5px;
  15. margin-bottom: 10px;
  16. "
  17. ></query>
  18. <card :title="'核心指标'">
  19. <CoreData :data-list="coreData"></CoreData>
  20. </card>
  21. </div>
  22. <div style="margin-top: 12px">
  23. <a-row>
  24. <a-col :span="18">
  25. <div class="workMeeting-left ioc-card-content">
  26. <card title="会议分析">
  27. <a-row>
  28. <a-col :span="2">
  29. <a-menu
  30. style="width: 100%"
  31. :default-selected-keys="defaultSelectedKeys"
  32. mode="inline"
  33. @click="huiyiClick"
  34. >
  35. <!-- style="width: 100px" -->
  36. <!-- :open-keys.sync="openKeys" -->
  37. <template v-for="(value, key) in roomInfo">
  38. <a-menu-item
  39. v-for="item in value"
  40. :key="item.value"
  41. v-if="key == queryData.floorId"
  42. >
  43. {{ item.value }}
  44. </a-menu-item>
  45. </template>
  46. </a-menu>
  47. </a-col>
  48. <a-col :span="3">
  49. <div class="week-box" v-for="n in timeArr" :key="n.weekday">
  50. <div class="week">{{ n.weekday }}</div>
  51. <div class="date">{{ n.date }}</div>
  52. </div>
  53. </a-col>
  54. <a-col :span="19">
  55. <timeline
  56. v-if="showMeetingLine"
  57. v-for="(value, key, index) in meetingInfo"
  58. :key="index"
  59. :select="currCheckMeeting"
  60. v-bind="{
  61. startTime: 8,
  62. endTime: 18,
  63. huiyiInfo: value,
  64. }"
  65. :style="{ height: '60px' }"
  66. ></timeline>
  67. </a-col>
  68. </a-row>
  69. <div class="workMeeting-left-detail">
  70. <a-descriptions :column="2" :colon="false">
  71. <a-descriptions-item>
  72. <template #label>
  73. <span class="workMeeting-left-detail-label"
  74. >会议主题:</span
  75. >
  76. </template>
  77. <div class="workMeeting-left-detail-content">
  78. {{ currMeeting.subject }}
  79. </div>
  80. </a-descriptions-item>
  81. <a-descriptions-item>
  82. <template #label>
  83. <span class="workMeeting-left-detail-label"
  84. >会议配置:</span
  85. >
  86. </template>
  87. <div
  88. class="workMeeting-left-detail-content"
  89. v-if="currMeeting.subject"
  90. >
  91. 智慧场景策略配置
  92. </div>
  93. </a-descriptions-item>
  94. <a-descriptions-item>
  95. <template #label>
  96. <span class="workMeeting-left-detail-label"
  97. >预约部门:</span
  98. >
  99. </template>
  100. <div class="workMeeting-left-detail-content">
  101. {{ deptData[currMeeting.deptId] }}
  102. </div>
  103. </a-descriptions-item>
  104. <a-descriptions-item>
  105. <template #label>
  106. <span class="workMeeting-left-detail-label"
  107. >会议成本:</span
  108. >
  109. </template>
  110. <div
  111. class="workMeeting-left-detail-content"
  112. style="background-color: #ffffff"
  113. v-if="currMeeting.subject"
  114. >
  115. 30元/小时
  116. </div>
  117. </a-descriptions-item>
  118. <a-descriptions-item>
  119. <template #label>
  120. <span class="workMeeting-left-detail-label"
  121. >参会人员:</span
  122. >
  123. </template>
  124. <div
  125. style="width: 100%; vertical-align: top"
  126. v-if="currMeeting.subject"
  127. >
  128. <div
  129. style="
  130. display: inline-block;
  131. vertical-align: top;
  132. margin: 1px 3px;
  133. "
  134. >
  135. <a-avatar
  136. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  137. />
  138. <div>张三</div>
  139. </div>
  140. <div
  141. style="
  142. display: inline-block;
  143. vertical-align: top;
  144. margin: 1px 3px;
  145. "
  146. >
  147. <a-avatar
  148. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  149. />
  150. <div>张雪峰</div>
  151. </div>
  152. <div
  153. style="
  154. display: inline-block;
  155. vertical-align: top;
  156. margin: 1px 3px;
  157. "
  158. >
  159. <a-avatar
  160. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  161. />
  162. <div>张明</div>
  163. </div>
  164. <div
  165. style="
  166. display: inline-block;
  167. vertical-align: top;
  168. margin: 1px 3px;
  169. "
  170. >
  171. <a-avatar
  172. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  173. />
  174. <div>李阳</div>
  175. </div>
  176. <div
  177. style="
  178. display: inline-block;
  179. vertical-align: top;
  180. margin: 1px 3px;
  181. "
  182. >
  183. <a-avatar
  184. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  185. />
  186. <div>王佳佳</div>
  187. </div>
  188. </div>
  189. </a-descriptions-item>
  190. <a-descriptions-item>
  191. <template #label>
  192. <span class="workMeeting-left-detail-label"
  193. >会议费用:</span
  194. >
  195. </template>
  196. <div
  197. class="workMeeting-left-detail-content"
  198. style="background-color: #ffffff"
  199. v-if="currMeeting.subject"
  200. >
  201. 35元/小时
  202. </div>
  203. </a-descriptions-item>
  204. </a-descriptions>
  205. </div>
  206. </card>
  207. </div>
  208. </a-col>
  209. <a-col :span="6">
  210. <div class="workMeeting-right ioc-card-content">
  211. <card title="成本趋势">
  212. <template #title-extra>
  213. <div style="font-size: 18px; color: #4d4d4d; margin-top: 3px">
  214. 成本集中
  215. </div>
  216. </template>
  217. <div class="cben" style="margin-bottom: 15px">
  218. <WorkMeetingCostTrend
  219. ref="WorkMeetingCostTrend"
  220. :queryData="queryData"
  221. :height="460"
  222. />
  223. </div>
  224. </card>
  225. </div>
  226. </a-col>
  227. <a-col :span="18">
  228. <div
  229. class="workMeeting-left ioc-card-content"
  230. style="margin-bottom: 15px"
  231. >
  232. <card title="会议室时长">
  233. <MeetingTimeCharts :height="300"></MeetingTimeCharts>
  234. </card>
  235. </div>
  236. </a-col>
  237. </a-row>
  238. </div>
  239. </div>
  240. </template>
  241. <script>
  242. import query from "@/components/common/query.vue";
  243. import card from "@/components/common/card.vue";
  244. import timeline from "@/components/common/timeLine.vue";
  245. import WorkMeetingCostTrend from "@/components/work/meeting/component/workMeetingCostTrend.vue";
  246. import MeetingTimeCharts from "@/components/scene/meeting/chart/meetingTimeCharts.vue";
  247. import apiWorkMeeting from "@/api/work/apiWorkMeeting";
  248. export default {
  249. components: {
  250. query,
  251. card,
  252. timeline,
  253. WorkMeetingCostTrend,
  254. MeetingTimeCharts,
  255. },
  256. data() {
  257. let timeRange = this.$util.dateUtil.getNearlyMonthRange();
  258. return {
  259. showMeetingLine: false,
  260. timeArr: [
  261. {
  262. id: 0,
  263. weekday: "周一",
  264. date: "",
  265. },
  266. {
  267. id: 1,
  268. weekday: "周二",
  269. date: "",
  270. },
  271. {
  272. id: 2,
  273. weekday: "周三",
  274. date: "",
  275. },
  276. {
  277. id: 3,
  278. weekday: "周四",
  279. date: "",
  280. },
  281. {
  282. id: 4,
  283. weekday: "周五",
  284. date: "",
  285. },
  286. ],
  287. deptData: {
  288. 0: "业务一部",
  289. 1: "业务二部",
  290. 2: "业务三部",
  291. },
  292. queryData: {
  293. companyId: "0",
  294. floorId: "7",
  295. timeRange: timeRange,
  296. },
  297. currRoom: "701",
  298. floorOptions: [
  299. {
  300. value: "7",
  301. label: "7F",
  302. },
  303. {
  304. value: "8",
  305. label: "8F",
  306. },
  307. {
  308. value: "9",
  309. label: "9F",
  310. },
  311. //{
  312. // value: '',
  313. // label: "全部"
  314. //},
  315. //{
  316. // value: '1',
  317. // label: "1F"
  318. //},
  319. //{
  320. // value: '10',
  321. // label: "10F"
  322. //},
  323. //{
  324. // value: '11',
  325. // label: "11F"
  326. //},{
  327. // value: '12',
  328. // label: "12F"
  329. //},{
  330. // value: '15',
  331. // label: "15F"
  332. //},{
  333. // value: '16',
  334. // label: "16F"
  335. //},{
  336. // value: '17',
  337. // label: "17F"
  338. //},{
  339. // value: '18',
  340. // label: "18F"
  341. //},{
  342. // value: '19',
  343. // label: "19F"
  344. //},{
  345. // value: '20',
  346. // label: "20F"
  347. //},{
  348. // value: '30',
  349. // label: "30F"
  350. //},
  351. ],
  352. columns: [
  353. { title: "序号", dataIndex: "index", key: "1", width: 48 },
  354. { title: "姓名", dataIndex: "name", key: "2", width: 60 },
  355. { title: "部门", dataIndex: "department", key: "3", width: 80 },
  356. { title: "最后进入时间", dataIndex: "time", key: "4", width: 90 },
  357. ],
  358. coreData: [
  359. {
  360. title: "会议室饱和度(月)",
  361. num: "",
  362. unit: "%",
  363. historyDesc: "同比",
  364. historyNum: 0.4,
  365. },
  366. {
  367. title: "会议室占用率(天)",
  368. num: "",
  369. unit: "%",
  370. historyDesc: "同比",
  371. historyNum: 0,
  372. },
  373. {
  374. title: "会议室占用率",
  375. num: 0,
  376. unit: "%",
  377. historyDesc: "同比",
  378. historyNum: 0,
  379. },
  380. {
  381. title: "会议室人均成本(元/人/月)",
  382. num: 0,
  383. historyDesc: "同比",
  384. historyNum: 0,
  385. },
  386. {
  387. type: 1,
  388. showStar: true,
  389. title: "值得关注",
  390. content: "",
  391. },
  392. ],
  393. defaultSelectedKeys: ["701", "801", "901"],
  394. tabsItemArr: [],
  395. roomInfo: {
  396. 7: [
  397. {
  398. label: "701",
  399. value: "701",
  400. },
  401. {
  402. label: "702",
  403. value: "702",
  404. },
  405. {
  406. label: "703",
  407. value: "703",
  408. },
  409. ],
  410. 8: [
  411. {
  412. label: "801",
  413. value: "801",
  414. },
  415. {
  416. label: "802",
  417. value: "802",
  418. },
  419. {
  420. label: "803",
  421. value: "803",
  422. },
  423. ],
  424. 9: [
  425. {
  426. label: "901",
  427. value: "901",
  428. },
  429. {
  430. label: "902",
  431. value: "902",
  432. },
  433. {
  434. label: "903",
  435. value: "903",
  436. },
  437. ],
  438. },
  439. meetingInfo: {},
  440. currMeeting: {},
  441. };
  442. },
  443. mounted() {
  444. //this.changeTab(1);
  445. this.init();
  446. this.setDate();
  447. this.getMeetingRecordData();
  448. },
  449. methods: {
  450. init() {
  451. this.$store.loadingStore().loadingWithApi(this.getCoreData(), 2000);
  452. },
  453. currCheckMeeting(val) {
  454. this.currMeeting = val;
  455. },
  456. setDate() {
  457. this.timeArr = this.timeArr.map((v) => {
  458. return {
  459. id: v.id,
  460. weekday: v.weekday,
  461. date: this.$moment().weekday(v.id).format("YYYY/MM/DD"),
  462. };
  463. });
  464. // for(let i=1;i<=5;i++){
  465. // this.timeArr.push({
  466. // weekday:this.$moment().weekday(i).format(),
  467. // date:this.$moment().weekday(i).format("YYYY/MM/DD")
  468. // })
  469. // }
  470. },
  471. reset() {},
  472. search() {
  473. this.$util.asyncPromise(
  474. this.getCoreData(),
  475. this.$refs.WorkMeetingCostTrend.getData(),
  476. this.getMeetingRecordData()
  477. );
  478. },
  479. getMeetingRecordData() {
  480. this.showMeetingLine = false;
  481. let params = {};
  482. Object.assign(params, this.queryData);
  483. params.timeRange = this.$util.dateUtil.getCurrWeekRange();
  484. let resultObj = {};
  485. let app = this;
  486. this.timeArr.forEach((i) => {
  487. resultObj[i.date] = [];
  488. });
  489. this.meetingInfo = resultObj;
  490. return apiWorkMeeting
  491. .getMeetingRecords(params)
  492. .then((res) => {
  493. let arr = res.filter((item) => item.room == this.currRoom);
  494. for (let i = 0; i < arr.length; i++) {
  495. let obj = app.$moment(arr[i].startTime).format("yyyy/MM/DD");
  496. resultObj[obj].push(arr[i]);
  497. }
  498. this.meetingInfo = resultObj;
  499. this.showMeetingLine = true;
  500. })
  501. .catch((err) => {
  502. this.showMeetingLine = true;
  503. });
  504. },
  505. huiyiClick(e) {
  506. //this.changeTab(e.key);
  507. this.currRoom = e.key;
  508. this.getMeetingRecordData();
  509. },
  510. //changeTab(index) {
  511. // this.tabsItemArr = this.tabsArr[index].content;
  512. //},
  513. getCoreData() {
  514. return apiWorkMeeting.getCoreData(this.queryData).then((res) => {
  515. this.coreData[0].num = res.list[0].value;
  516. this.coreData[0].historyNum = res.list[0].compare;
  517. this.coreData[1].num = res.list[1].value;
  518. this.coreData[1].historyNum = res.list[1].compare;
  519. this.coreData[2].num = res.list[2].value;
  520. this.coreData[2].historyNum = res.list[2].compare;
  521. this.coreData[3].num = res.list[3].value;
  522. this.coreData[3].historyNum = res.list[3].compare;
  523. this.coreData[4].content = res.worthAttention;
  524. });
  525. },
  526. },
  527. };
  528. </script>
  529. <style lang="less" scoped>
  530. .workMeeting {
  531. .workMeeting-left {
  532. background-color: #ffffff;
  533. padding: 2px 15px;
  534. border-radius: 4px;
  535. margin-right: 6px;
  536. .ant-col-3 {
  537. .week-box {
  538. height: 60px;
  539. width: 100%;
  540. position: relative;
  541. color: rgb(77, 77, 77, 0.2);
  542. .week {
  543. width: 80%;
  544. height: 50%;
  545. position: absolute;
  546. top: 0;
  547. right: 0;
  548. display: flex;
  549. align-items: center;
  550. }
  551. .date {
  552. width: 80%;
  553. height: 50%;
  554. position: absolute;
  555. right: 0;
  556. bottom: 0;
  557. margin: 0 auto;
  558. }
  559. }
  560. }
  561. .workMeeting-left-detail {
  562. margin-top: 30px;
  563. padding: 0 20px;
  564. margin-bottom: 12px;
  565. .workMeeting-left-detail-label {
  566. vertical-align: top;
  567. color: #b2b2b2;
  568. }
  569. .workMeeting-left-detail-content {
  570. width: 100%;
  571. font-size: 12px;
  572. background-color: #f7f9fa;
  573. color: #999999;
  574. padding-left: 12px;
  575. }
  576. }
  577. }
  578. /deep/ .ant-descriptions-item {
  579. vertical-align: top;
  580. }
  581. /deep/ .ant-descriptions-item-content {
  582. width: 80%;
  583. line-height: 24px;
  584. }
  585. .workMeeting-right {
  586. background-color: #ffffff;
  587. padding: 2px 15px;
  588. border-radius: 4px;
  589. margin-left: 6px;
  590. }
  591. }
  592. </style>