statisticsHeader.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <template>
  2. <div class="flight-statistics-header">
  3. <template v-if="title">
  4. <div class="title">{{ title }}</div>
  5. <div class="status" v-if="asShow">
  6. <div :class="picShow ? 'st_pic' : 'st_pics'" @click="picup"></div>
  7. <div :class="!picShow ? 'st_tab' : 'st_tabs'" @click="picups"></div>
  8. </div>
  9. </template>
  10. <el-form ref="form" class="form" :model="formData">
  11. <el-form-item v-for="item in formItems" :key="item.prop" :prop="item.prop" :label="item.label" :style="{
  12. width: item.width || '120px',
  13. }">
  14. <template v-if="item.inputType === 'input'">
  15. <el-input v-model="formData[item.prop]" :size="item.size || 'small'" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable" />
  16. </template>
  17. <template v-if="item.inputType === 'select'">
  18. <el-select v-model="formData[item.prop]" :filterable="item.filterable" :default-first-option="item.filterable" :size="item.size || 'small'" :placeholder="item.placeholder || '请选择'" :multiple="item.multiple" :collapse-tags="item.multiple" :clearable="item.clearable" :disabled="item.disabled" @change="
  19. (value) => {
  20. item.changeHandler && call(item.changeHandler, value);
  21. }
  22. ">
  23. <el-option v-for="option in item.options" :key="option.value" :value="option.value" :label="option.label" />
  24. </el-select>
  25. </template>
  26. <template v-if="item.inputType === 'datePicker'">
  27. <el-date-picker v-model="formData[item.prop]" :size="item.size || 'small'" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
  28. </template>
  29. <template v-if="item.inputType === 'datetimerange'">
  30. <el-date-picker v-model="formData[item.prop]" type="datetimerange" range-separator="至" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始日期" end-placeholder="结束日期">
  31. </el-date-picker>
  32. </template>
  33. <template v-if="item.inputType === 'erdatime'">
  34. <template v-if="item.haveDisabled">
  35. <el-date-picker value-format="YYYY-MM-DD" v-model="formData[item.prop]" type="date" :disabled-date="item.disabledDate" placeholder="选择日期">
  36. </el-date-picker>
  37. </template>
  38. <template v-else>
  39. <el-date-picker value-format="YYYY-MM-DD" v-model="formData[item.prop]" type="date" placeholder="选择日期">
  40. </el-date-picker>
  41. </template>
  42. </template>
  43. <template v-if="item.inputType === 'cascader'">
  44. <el-cascader v-model="formData[item.prop]" :size="item.size || 'small'" :placeholder="item.placeholder || '请选择'" :options="item.options" :props="item.props" :clearable="item.clearable" :disabled="item.disabled" @change="
  45. (value) => {
  46. item.changeHandler && call(item.changeHandler, value);
  47. }
  48. " />
  49. </template>
  50. </el-form-item>
  51. <el-form-item v-if="formItems.length">
  52. <el-button type="primary" size="small" @click="getData">{{
  53. buttonText
  54. }}</el-button>
  55. </el-form-item>
  56. <el-form-item v-if="withExport">
  57. <img src="@/assets/nav/ic_export.png" title="导出" class="btn-icon-only" @click="exportClickHandler" />
  58. </el-form-item>
  59. <el-form-item v-if="withSetting">
  60. <img src="@/assets/nav/ic_setting.png" title="节点设置" class="btn-icon-only" @click="settingClickHandler" />
  61. </el-form-item>
  62. </el-form>
  63. </div>
  64. </template>
  65. <script>
  66. import { Query } from "@/api/webApi";
  67. import { Format } from "@/utils/validate";
  68. export default {
  69. name: "StatisticsHeader",
  70. props: {
  71. asShow: {
  72. type: Boolean,
  73. default: true,
  74. },
  75. title: {
  76. type: String,
  77. default: "",
  78. },
  79. items: {
  80. type: Array,
  81. default: undefined,
  82. },
  83. customItems: {
  84. type: Array,
  85. default: () => [],
  86. },
  87. data: {
  88. type: Object,
  89. default: undefined,
  90. },
  91. buttonText: {
  92. type: String,
  93. default: "查询",
  94. },
  95. withExport: {
  96. type: Boolean,
  97. default: true,
  98. },
  99. withSetting: {
  100. type: Boolean,
  101. default: false,
  102. },
  103. eledata: {
  104. type: String,
  105. default: "",
  106. },
  107. action: {
  108. type: Number,
  109. default: true,
  110. },
  111. },
  112. data () {
  113. return {
  114. picShow: true,
  115. formData: {
  116. range: "",
  117. inOrOut: "",
  118. interval: "",
  119. airline: [],
  120. area: "",
  121. airport: [],
  122. terminal: "",
  123. dateTime: "",
  124. flightType: "",
  125. baggageType: "",
  126. passengerType: [],
  127. },
  128. formItems: [
  129. {
  130. prop: "range",
  131. inputType: "select",
  132. placeholder: "统计范围",
  133. requiredWarning: "请先选择统计范围",
  134. options: [
  135. {
  136. value: "全部",
  137. label: "全部",
  138. },
  139. {
  140. value: "航线",
  141. label: "航线",
  142. },
  143. {
  144. value: "基地分公司",
  145. label: "基地分公司",
  146. },
  147. {
  148. value: "航站",
  149. label: "航站",
  150. },
  151. {
  152. value: "航站楼",
  153. label: "航站楼",
  154. },
  155. ],
  156. changeHandler (value) {
  157. this.formData.inOrOut = "";
  158. // this.formData.interval = ''
  159. this.formData.area = "";
  160. this.formData.airline = "";
  161. this.formData.airport = "";
  162. this.formData.terminal = "";
  163. this.setInOrOutOptions(value);
  164. const airlineItem = this.formItems.find(
  165. (item) => item.prop === "airline"
  166. );
  167. const areaItem = this.formItems.find(
  168. (item) => item.prop === "area"
  169. );
  170. const airportItem = this.formItems.find(
  171. (item) => item.prop === "airport"
  172. );
  173. const terminalItem = this.formItems.find(
  174. (item) => item.prop === "terminal"
  175. );
  176. airlineItem && (airlineItem.disabled = true);
  177. areaItem && (areaItem.disabled = true);
  178. airportItem && (airportItem.disabled = true);
  179. terminalItem && (terminalItem.disabled = true);
  180. switch (value) {
  181. case "航线":
  182. airlineItem && (airlineItem.disabled = false);
  183. break;
  184. case "基地分公司":
  185. areaItem && (areaItem.disabled = false);
  186. break;
  187. case "航站":
  188. airportItem && (airportItem.disabled = false);
  189. break;
  190. case "航站楼":
  191. terminalItem && (terminalItem.disabled = false);
  192. break;
  193. default:
  194. break;
  195. }
  196. },
  197. },
  198. {
  199. prop: "inOrOut",
  200. inputType: "select",
  201. placeholder: "进出港",
  202. requiredWarning: "请先选择进出港",
  203. clearable: true,
  204. options: [],
  205. },
  206. {
  207. prop: "interval",
  208. inputType: "select",
  209. placeholder: "时间维度",
  210. requiredWarning: "请先选择统计时间维度",
  211. clearable: true,
  212. options: [
  213. {
  214. value: "日",
  215. label: "按日统计",
  216. },
  217. {
  218. value: "月",
  219. label: "按月统计",
  220. },
  221. {
  222. value: "季",
  223. label: "按季统计",
  224. },
  225. {
  226. value: "年",
  227. label: "按年统计",
  228. },
  229. ],
  230. },
  231. {
  232. prop: "dateTime",
  233. inputType: "datePicker",
  234. width: "240px",
  235. requiredWarning: "请先选择统计时间范围",
  236. },
  237. {
  238. prop: "airline",
  239. inputType: "select",
  240. placeholder: "航线",
  241. width: "180px",
  242. filterable: true,
  243. clearable: true,
  244. multiple: true,
  245. disabled: true,
  246. queryId: '',
  247. setKey: "a2",
  248. options: [],
  249. },
  250. {
  251. prop: "area",
  252. inputType: "select",
  253. placeholder: "基地分公司",
  254. filterable: true,
  255. clearable: true,
  256. disabled: true,
  257. queryId:'',
  258. setKey: "a5",
  259. options: [],
  260. },
  261. {
  262. prop: "airport",
  263. inputType: "select",
  264. placeholder: "航站",
  265. width: "150px",
  266. filterable: true,
  267. clearable: true,
  268. multiple: true,
  269. disabled: true,
  270. queryId: '',
  271. setKey: "a2",
  272. options: [],
  273. },
  274. {
  275. prop: "terminal",
  276. inputType: "select",
  277. placeholder: "航站楼",
  278. filterable: true,
  279. clearable: true,
  280. disabled: true,
  281. queryId: '',
  282. setKey: "a2",
  283. options: [],
  284. },
  285. ],
  286. };
  287. },
  288. watch: {
  289. asShow: {
  290. handler (val) {
  291. // console.log(val);
  292. },
  293. deep: true,
  294. immediate: true,
  295. },
  296. items: {
  297. handler (val) {
  298. val && (this.formItems = val);
  299. },
  300. deep: true,
  301. immediate: true,
  302. },
  303. formData: {
  304. handler (val) {
  305. if (this.action === 14 || this.action === 2 || this.action === 19) {
  306. this.$emit("fore", val);
  307. }
  308. },
  309. deep: true,
  310. immediate: true,
  311. },
  312. data: {
  313. handler (val) {
  314. val && (this.formData = val);
  315. },
  316. deep: true,
  317. immediate: true,
  318. },
  319. eledata: {
  320. handler (val) {
  321. this.formData = {};
  322. },
  323. deep: true,
  324. immediate: true,
  325. },
  326. },
  327. created () {
  328. this.customItems.forEach((item) => {
  329. if (typeof item.itemIndex === "number") {
  330. if (item.prop) {
  331. this.formItems.splice(item.itemIndex, item.replaceNum, item);
  332. } else {
  333. this.formItems.splice(item.itemIndex, item.replaceNum);
  334. }
  335. } else {
  336. this.formItems.push(item);
  337. }
  338. });
  339. this.formItems.forEach((item) => {
  340. if (item.queryId && item.setKey) {
  341. this.getOptions(item.queryId, item.setKey, item.prop);
  342. }
  343. if (item.defaultOption) {
  344. this.formData[item.prop] = item.defaultOption;
  345. }
  346. });
  347. },
  348. mounted () {
  349. },
  350. methods: {
  351. picup () {
  352. this.picShow = false;
  353. this.$emit("upset", this.picShow);
  354. },
  355. picups () {
  356. this.picShow = true;
  357. this.$emit("upset", this.picShow);
  358. },
  359. call (func, ...args) {
  360. func.call(this, ...args);
  361. },
  362. getData () {
  363. try {
  364. this.formItems.forEach((item) => {
  365. if (
  366. item.requiredWarning &&
  367. (!this.formData[item.prop] || this.formData[item.prop].length === 0)
  368. ) {
  369. throw new Error(item.requiredWarning);
  370. }
  371. });
  372. } catch (error) {
  373. this.$message.warning(error.message);
  374. return;
  375. }
  376. if (this.formData.range === "航线" && !this.formData.airline) {
  377. this.$message.warning("请先选择航线");
  378. return;
  379. } else if (this.formData.range === "航站" && !this.formData.airport) {
  380. this.$message.warning("请先选择航站");
  381. return;
  382. } else if (this.formData.range === "基地分公司" && !this.formData.area) {
  383. this.$message.warning("请先选择基地分公司");
  384. return;
  385. }
  386. this.$emit("getFormData", this.formData);
  387. },
  388. exportClickHandler () {
  389. this.$emit("export");
  390. },
  391. settingClickHandler () {
  392. this.$emit("setting");
  393. },
  394. setInOrOutOptions (range) {
  395. const theInOrOutItem = this.formItems.find(
  396. (item) => item.prop === "inOrOut"
  397. );
  398. switch (range) {
  399. case "全部":
  400. case "航线":
  401. theInOrOutItem.options = [
  402. {
  403. label: "全部",
  404. value: "全部",
  405. },
  406. ];
  407. this.formData.inOrOut = "全部";
  408. this.formItems[1].disabled = true;
  409. break;
  410. case "基地分公司":
  411. case "航站":
  412. case "航站楼":
  413. theInOrOutItem.options = [
  414. {
  415. value: "全部",
  416. label: "全部",
  417. },
  418. {
  419. value: "进港",
  420. label: "进港",
  421. },
  422. {
  423. value: "离港",
  424. label: "出港",
  425. },
  426. ];
  427. this.formItems[1].disabled = false;
  428. break;
  429. default:
  430. theInOrOutItem.options = [];
  431. this.formItems[1].disabled = false;
  432. break;
  433. }
  434. },
  435. async getOptions (queryId, setKey, prop) {
  436. try {
  437. const { code, returnData, message } = await Query({
  438. id: queryId,
  439. dataContent: [],
  440. });
  441. if (Number(code) === 0) {
  442. const arr = returnData.listValues.map((element) => ({
  443. label: element[setKey],
  444. value: element[setKey],
  445. }));
  446. const theItem = this.formItems.find((item) => item.prop === prop);
  447. theItem.options = arr;
  448. } else {
  449. this.$message.error(message);
  450. }
  451. } catch (error) {
  452. this.$message.error("失败");
  453. }
  454. },
  455. },
  456. };
  457. </script>
  458. <style lang="scss" scoped>
  459. .flight-statistics-header {
  460. // padding-top: 24px;
  461. // min-height: 80px;
  462. display: flex;
  463. justify-content: space-between;
  464. align-items: flex-start;
  465. position: relative;
  466. .status {
  467. position: absolute;
  468. left: 144px;
  469. display: flex;
  470. align-items: center;
  471. > .st_pic {
  472. width: 32px;
  473. height: 32px;
  474. border-radius: 4px;
  475. // background: url("../../../../assets/nav/ic_table_default.png") no-repeat;
  476. background-size: 100% 100%;
  477. margin-right: 8px;
  478. cursor: pointer;
  479. }
  480. > .st_pics {
  481. width: 32px;
  482. height: 32px;
  483. border-radius: 4px;
  484. // background: url("../../../../assets/nav/ic_table_check.png") no-repeat;
  485. background-size: 100% 100%;
  486. margin-right: 8px;
  487. cursor: pointer;
  488. }
  489. > .st_tab {
  490. width: 32px;
  491. height: 32px;
  492. border-radius: 4px;
  493. // background: url("../../../../assets/nav/ic_chart_default.png") no-repeat;
  494. background-size: 100% 100%;
  495. cursor: pointer;
  496. }
  497. > .st_tabs {
  498. width: 32px;
  499. height: 32px;
  500. border-radius: 4px;
  501. // background: url("../../../../assets/nav/ic_chart_check.png") no-repeat;
  502. background-size: 100% 100%;
  503. cursor: pointer;
  504. }
  505. }
  506. .title {
  507. margin-right: 24px;
  508. padding-left: 16px;
  509. // min-width: 190px;
  510. height: 32px;
  511. line-height: 32px;
  512. font-size: 18px;
  513. font-family: Helvetica, "Microsoft YaHei";
  514. font-weight: bold;
  515. white-space: nowrap;
  516. position: relative;
  517. color: #fff;
  518. &::before {
  519. content: "";
  520. width: 4px;
  521. height: 20px;
  522. background: #66b1ff;
  523. position: absolute;
  524. top: 0;
  525. bottom: 0;
  526. left: 0;
  527. margin: auto;
  528. }
  529. }
  530. ::v-deep .form {
  531. display: flex;
  532. flex-wrap: wrap;
  533. > .el-form-item {
  534. margin-bottom: 24px;
  535. // width: 185px;
  536. &:not(:last-child) {
  537. margin-right: 8px;
  538. }
  539. &:nth-last-child(2),
  540. &:nth-last-child(3) {
  541. margin-right: 16px;
  542. }
  543. .el-form-item__content {
  544. height: 32px;
  545. line-height: 30px;
  546. .el-input {
  547. &.is-disabled .el-input__inner {
  548. border: none;
  549. }
  550. .el-input__inner {
  551. border-radius: 4px;
  552. font-family: Helvetica, "Microsoft YaHei";
  553. color: #303133;
  554. border-color: #ffffff;
  555. &:hover {
  556. border-color: #c0c4cc;
  557. }
  558. &:focus {
  559. border-color: #409eff;
  560. }
  561. }
  562. }
  563. .el-date-editor--daterange.el-input,
  564. .el-date-editor--daterange.el-input__inner,
  565. .el-date-editor--timerange.el-input,
  566. .el-date-editor--timerange.el-input__inner {
  567. width: 100%;
  568. border-radius: 4px;
  569. border-color: #ffffff;
  570. color: #303133;
  571. font-family: Helvetica, "Microsoft YaHei";
  572. &:hover {
  573. border-color: #c0c4cc;
  574. }
  575. &.is-active {
  576. border-color: #409eff;
  577. }
  578. .el-input__icon {
  579. color: #303133;
  580. }
  581. .el-range-separator {
  582. line-height: 28px;
  583. }
  584. }
  585. .el-select,
  586. .el-cascader {
  587. .el-input {
  588. .el-icon-arrow-up::before {
  589. content: "\e78f";
  590. }
  591. .el-icon-arrow-down::before {
  592. content: "\e790";
  593. }
  594. &:not(.is-disabled) {
  595. .el-input__icon,
  596. .el-input__inner::-webkit-input-placeholder {
  597. color: #303133;
  598. }
  599. }
  600. }
  601. }
  602. .el-button {
  603. border-radius: 4px;
  604. font-family: Helvetica, "Microsoft YaHei";
  605. }
  606. .btn-icon-only {
  607. width: 24px;
  608. height: 24px;
  609. cursor: pointer;
  610. }
  611. }
  612. }
  613. }
  614. }
  615. </style>