doubleCarbonCar.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. <!--
  2. 车辆排放页面
  3. @author 刘梦祥
  4. @date 2023年2月8日
  5. -->
  6. <template>
  7. <div class="doubleCarbon-main-box flexColumn">
  8. <a-spin class="spinStyle" size="large" tip="Loading..." v-show="searchLoading"></a-spin>
  9. <!-- 头部搜索区域 -->
  10. <div class="borderColor">
  11. <div class="flex flex_between margin5rem">
  12. <div class="flex">
  13. <div class="mr1rem">
  14. 单位名称:
  15. <a-select
  16. style="width:200px;"
  17. v-model="searchParam.nameOfUnit"
  18. :allowClear="selectProps.allowClear"
  19. :mode="selectProps.mode"
  20. :options="options.nameOfUnit"
  21. :notFoundConent="selectProps.notFoundConent"
  22. :placeholder="selectProps.placeholder"
  23. ></a-select>
  24. </div>
  25. <div>
  26. 时间范围: <a-month-picker id="startTime" format="YYYY-MM" @change="changeTimeRangeS" placeholder="开始时间" />~
  27. <a-month-picker id="endTime" format="YYYY-MM" @change="changeTimeRangeE" placeholder="结束时间" />
  28. </div>
  29. </div>
  30. <div>
  31. <a-button class="mr1rem" @click="reset">重置</a-button>
  32. <a-button type="primary" @click="search">查询</a-button>
  33. </div>
  34. </div>
  35. <div class="cardTitle margin5rem">核心指标</div>
  36. <div v-if="coreList.length > 0" class="flex flex_around coreListBox margin5rem">
  37. <div v-for="(item, index) in coreList" :key="'coreList' + index">
  38. <div class="core_title">{{ item.title }}</div>
  39. <div class="core_value">
  40. {{ item.value ? item.value : "--" }}<span class="core_unit">{{ item.unit ? item.unit : "" }}</span
  41. ><span class="core_leavel" v-if="item.leavel" :style="{ color: $constant.COLOR_LEAVEL[item.leavel] }">!</span>
  42. </div>
  43. <div v-if="item.info" class="core_info">
  44. <span class="core_info_title">{{ item.info.title }}</span
  45. ><span class="core_info_value" :style="{ color: $constant.COLOR_LEAVEL[item.info.leavel] }"
  46. >{{ item.info.value
  47. }}<i
  48. v-if="item.info.leavel && (item.info.leavel == 1 || item.info.leavel == 3)"
  49. :class="item.info.leavel == 3 ? 'el-icon-caret-top' : 'el-icon-caret-bottom'"
  50. /></span>
  51. </div>
  52. </div>
  53. </div>
  54. <div class="flex flex_around coreListBox margin5rem" v-if="coreList.length == 0" style="height:120px;">
  55. <a-empty></a-empty>
  56. </div>
  57. </div>
  58. <!-- 碳排放分析和碳配额构成 -->
  59. <div class="flex" style="height:400px;">
  60. <div class="echartBox_left borderColor">
  61. <div class="cardTitle margin5rem">碳排放分析</div>
  62. <div class="margin5rem chartDomBox">
  63. <LineChart v-if="chartData.LineChartData" :echartData="chartData.LineChartData" />
  64. <a-empty v-else></a-empty>
  65. </div>
  66. </div>
  67. <div class="echartBox_right borderColor">
  68. <div class="cardTitle margin5rem">碳配额构成</div>
  69. <div class="margin5rem chartDomBox">
  70. <BarChart v-if="chartData.BarChartData" :echartData="chartData.BarChartData" />
  71. <a-empty v-else></a-empty>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </template>
  77. <script>
  78. import LineChart from "../../echart/LineChart.vue";
  79. import BarChart from "../../echart/BarChart.vue";
  80. import PieChart from "../../echart/PieChart.vue";
  81. // 模拟数据
  82. import AnalogData from "../AnalogData.js"
  83. export default {
  84. components: {
  85. LineChart,
  86. BarChart,
  87. PieChart
  88. },
  89. data() {
  90. return {
  91. // selectProps配置
  92. selectProps: {
  93. allowClear: true, // 支持清除
  94. mode: "default", // 模式['default'|'multiple'|'tags'|'combobox']
  95. notFoundConent: "Not Found", // 当下拉列表为空时显示的内容
  96. placeholder: "请选择", // 选择框默认文字 string|slot
  97. showArrow: true, // 是否显示下拉小箭头
  98. size: "large" // 选择框大小['large'|'small']
  99. },
  100. // 单位名称option可选值
  101. options: {
  102. nameOfUnit: [] // options 数据,如果设置则不需要手动构造 selectOption 节点
  103. },
  104. // loading状态
  105. searchLoading: true,
  106. // 头部搜索条件中绑定值
  107. monthArr: [],
  108. searchParam: {
  109. nameOfUnit: undefined,
  110. timeRange: [undefined, undefined]
  111. },
  112. // 头部核心指标循环显示数据
  113. coreList: [],
  114. // 双碳新闻模拟数据
  115. DoubleCarbonNewsInfoList: [],
  116. // 双碳新闻弹窗打开状态
  117. showModalStatus: false,
  118. // 弹窗暂存数据对象
  119. showModalInfo: {
  120. title: "--",
  121. content: "--",
  122. author: "--",
  123. pushTime: "--"
  124. },
  125. // chart暂存数据对象
  126. chartData: []
  127. };
  128. },
  129. created() {},
  130. mounted() {
  131. // 页面初始化
  132. this.init();
  133. //默认是当年的1月到12月
  134. this.defaulTimeRangeS();
  135. this.defaulTimeRangeE();
  136. },
  137. methods: {
  138. // 开始时间初始化
  139. defaulTimeRangeS() {
  140. this.searchParam.timeRange[0] = this.$moment()
  141. .startOf("year")
  142. .format("YYYY-MM-DD 00:00:00");
  143. document.getElementById("startTime").querySelector("input").value = this.$moment()
  144. .startOf("year")
  145. .format("YYYY-MM");
  146. },
  147. // 结束时间初始化
  148. defaulTimeRangeE() {
  149. this.searchParam.timeRange[1] = this.$moment()
  150. .endOf("year")
  151. .format("YYYY-MM-DD 23:59:59");
  152. document.getElementById("endTime").querySelector("input").value = this.$moment()
  153. .endOf("year")
  154. .format("YYYY-MM");
  155. },
  156. // 修改开始时间时
  157. changeTimeRangeS(date, dateStr) {
  158. // 修改时间前判断是否合理
  159. if (this.searchParam.timeRange[1]) {
  160. if (
  161. this.$moment(this.$moment(dateStr, "YYYY-MM").format("YYYY-MM-DD 00:00:00")).diff(
  162. this.$moment(this.searchParam.timeRange[1])
  163. ) > 0
  164. ) {
  165. this.$message.error("开始时间不能大于结束时间!请重新选择!");
  166. setTimeout(() => {
  167. document.getElementById("startTime").querySelector("input").value = this.$moment()
  168. .startOf("year")
  169. .format("YYYY-MM");
  170. }, 10);
  171. }
  172. }
  173. if (dateStr) {
  174. this.searchParam.timeRange[0] = this.$moment(dateStr, "YYYY-MM").format("YYYY-MM-DD 00:00:00");
  175. } else {
  176. this.searchParam.timeRange[0] = undefined;
  177. }
  178. },
  179. // 修改结束时间时
  180. changeTimeRangeE(date, dateStr) {
  181. // 修改时间前判断是否合理
  182. if (this.searchParam.timeRange[0]) {
  183. if (
  184. this.$moment(this.searchParam.timeRange[0]).diff(
  185. this.$moment(
  186. this.$moment(dateStr, "YYYY-MM")
  187. .endOf("month")
  188. .format("YYYY-MM-DD 23:59:59")
  189. )
  190. ) > 0
  191. ) {
  192. this.$message.error("结束时间不能小于开始时间!请重新选择!");
  193. setTimeout(() => {
  194. document.getElementById("endTime").querySelector("input").value = this.$moment()
  195. .endOf("year")
  196. .format("YYYY-MM");
  197. }, 10);
  198. }
  199. }
  200. if (dateStr) {
  201. this.searchParam.timeRange[1] = this.$moment(dateStr, "YYYY-MM")
  202. .endOf("month")
  203. .format("YYYY-MM-DD 23:59:59");
  204. } else {
  205. this.searchParam.timeRange[1] = undefined;
  206. }
  207. },
  208. // 查询事件
  209. search() {
  210. // 时间范围条件不合理判断
  211. if (this.searchParam.timeRange[0] || this.searchParam.timeRange[1]) {
  212. if (!this.searchParam.timeRange[0]) {
  213. this.$message.info("请选择开始时间!");
  214. return;
  215. } else if (!this.searchParam.timeRange[1]) {
  216. this.$message.info("请选择结束时间!");
  217. return;
  218. }
  219. }
  220. this.searchLoading = true;
  221. console.log("查询条件:", this.searchParam.nameOfUnit, this.searchParam.timeRange[0], this.searchParam.timeRange[1]);
  222. setTimeout(() => {
  223. this.searchLoading = false;
  224. }, 1000);
  225. },
  226. // 重置事件
  227. reset() {
  228. document.getElementById("startTime").querySelector("input").value = this.$moment()
  229. .startOf("year")
  230. .format("YYYY-MM");
  231. document.getElementById("endTime").querySelector("input").value = this.$moment()
  232. .endOf("year")
  233. .format("YYYY-MM");
  234. this.searchParam = {
  235. nameOfUnit: undefined,
  236. timeRange: [
  237. this.$moment()
  238. .startOf("year")
  239. .format("YYYY-MM-DD 00:00:00"),
  240. this.$moment()
  241. .endOf("year")
  242. .format("YYYY-MM-DD 23:59:59")
  243. ]
  244. };
  245. },
  246. // 弹窗显示事件
  247. showModal(item) {
  248. this.showModalStatus = true;
  249. this.showModalInfo = item;
  250. },
  251. // 弹窗隐藏事件
  252. onCancel() {
  253. this.showModalStatus = false;
  254. },
  255. init() {
  256. // 初始化加载[单位名称列表、核心指标、碳排放分析、碳配额构成、碳排放占比、双碳新闻]
  257. setTimeout(() => {
  258. this.options.nameOfUnit = AnalogData.optionsNameOfUnit;
  259. this.coreList = AnalogData.core_List;
  260. this.chartData = AnalogData.CHART_DATA;
  261. this.DoubleCarbonNewsInfoList = AnalogData.doubleCarbonNewsInfoList;
  262. this.searchLoading = false;
  263. }, 1000);
  264. }
  265. }
  266. };
  267. </script>
  268. <style lang="less" scoped>
  269. // 复用样式
  270. .flexColumn {
  271. display: flex;
  272. flex-direction: column;
  273. flex-wrap: nowrap;
  274. }
  275. .flex {
  276. display: flex;
  277. flex-wrap: wrap;
  278. align-content: center;
  279. align-items: center;
  280. &_center {
  281. display: flex;
  282. flex-wrap: wrap;
  283. align-content: center;
  284. align-items: center;
  285. justify-content: center;
  286. }
  287. &_between {
  288. display: flex;
  289. flex-wrap: wrap;
  290. align-content: center;
  291. align-items: center;
  292. justify-content: space-between;
  293. }
  294. &_around {
  295. display: flex;
  296. flex-wrap: wrap;
  297. align-content: center;
  298. align-items: center;
  299. justify-content: space-around;
  300. }
  301. }
  302. .borderColor {
  303. border: 1px solid #e7eaf1;
  304. }
  305. .margin5rem {
  306. margin: 0.5rem;
  307. }
  308. .padding5rem {
  309. padding: 0.5rem;
  310. }
  311. // 页面主题样式
  312. .doubleCarbon-main-box {
  313. position: relative;
  314. width: 100%;
  315. height: 100%;
  316. & * {
  317. user-select: none;
  318. -moz-user-select: none;
  319. -webkit-user-select: none;
  320. -ms-user-select: none;
  321. ::-webkit-scrollbar {
  322. width: 0 !important;
  323. }
  324. -ms-overflow-style: none;
  325. overflow: -moz-scrollbars-none;
  326. }
  327. & > div {
  328. // padding: 5px 10px;
  329. border-radius: 2px;
  330. margin-bottom: 10px;
  331. }
  332. .spinStyle {
  333. position: absolute;
  334. width: 100%;
  335. height: 100%;
  336. background: rgba(255, 255, 255, 0.75);
  337. z-index: 2;
  338. }
  339. }
  340. // 头部搜索框和(重置、查询)按钮之间的间距样式
  341. .mr1rem {
  342. margin-right: 1rem;
  343. }
  344. // 每个card标题的字体样式
  345. .cardTitle {
  346. padding-left: 5px;
  347. font-size: 14px;
  348. font-weight: bold;
  349. border-left: 5px solid @primary-color;
  350. }
  351. // 核心指标
  352. .coreListBox {
  353. border-radius: 0.5rem;
  354. background-color: rgb(233, 246, 253);
  355. & > div {
  356. position: relative;
  357. // border-left: 1px solid #909399;
  358. padding: 10px;
  359. margin: 10px;
  360. cursor: pointer;
  361. border-radius: 0.5rem;
  362. &:hover {
  363. background-color: rgb(210, 239, 255);
  364. }
  365. // &::before {
  366. // content: "";
  367. // position: absolute;
  368. // left: -10px;
  369. // height: calc(100% - 20px);
  370. // width: 1px;
  371. // background: #c9c9c9;
  372. // }
  373. }
  374. }
  375. // 核心指标中value的样式
  376. .core {
  377. &_title {
  378. font-size: 12px;
  379. padding-bottom: 10px;
  380. }
  381. &_leavel {
  382. font-size: 16px;
  383. font-weight: bold;
  384. }
  385. &_value {
  386. font-size: 16px;
  387. font-weight: 500;
  388. color: #000;
  389. }
  390. &_unit {
  391. padding-left: 0.5rem;
  392. font-size: 12px;
  393. font-weight: bold;
  394. color: #909399;
  395. }
  396. &_info {
  397. padding-top: 10px;
  398. font-size: 12px;
  399. &_title {
  400. color: #afafaf;
  401. }
  402. &_value {
  403. padding-left: 0.5rem;
  404. font-weight: bold;
  405. }
  406. }
  407. }
  408. // echartBox样式
  409. .echartBox {
  410. &_left {
  411. width: calc(100% - 300px - 10px);
  412. height: 100%;
  413. }
  414. &_right {
  415. margin-left: 10px;
  416. width: 300px;
  417. height: 100%;
  418. }
  419. }
  420. .chartDomBox {
  421. position: relative;
  422. width: calc(100% - 20px);
  423. height: calc(100% - 41px);
  424. display: flex;
  425. justify-content: center;
  426. }
  427. .DoubleCarbonNews {
  428. padding: 10px 0;
  429. font-weight: bold;
  430. color: #000;
  431. cursor: pointer;
  432. border-bottom: 1px solid #c9c9c9;
  433. &:hover {
  434. color: @primary-color;
  435. }
  436. & > div {
  437. overflow: hidden;
  438. text-overflow: ellipsis;
  439. white-space: nowrap;
  440. }
  441. & > div:nth-child(1) {
  442. width: 15%;
  443. }
  444. & > div:nth-child(2) {
  445. height: 21px;
  446. overflow: hidden;
  447. width: calc(50% - 110px);
  448. }
  449. & > div:nth-child(3) {
  450. width: 20%;
  451. }
  452. & > div:nth-child(4) {
  453. width: 15%;
  454. }
  455. & > div:nth-child(5) {
  456. width: 30px;
  457. }
  458. }
  459. // loading样式
  460. .spin-content {
  461. border: 1px solid #91d5ff;
  462. background-color: #e6f7ff;
  463. padding: 30px;
  464. }
  465. </style>