實現步驟:
1、季度選擇器組件
<template> <div style="display: inline-block;"> <mark style="position: fixed;top: 0;bottom: 0;left: 0;right: 0;background: rgba(0,0,0,0);z-index: 999;" v-show="showSeason" @click.stop="showSeason=false" ></mark> <el-input :placeholder="placeholder" v-model="showValue" v-bind="$attrs" @focus="clickInput" ref="inputText"> <i slot="prefix" class="el-input__icon el-icon-date"></i> </el-input> <el-card class="box-card" style="width: 322px;padding: 0 30px 20px;margin-top: 10px;position: fixed;z-index: 9999" :style="{top:divTop + 'px'}" v-show="showSeason" ref="card" > <div class="clearfix" style="text-align: center;padding: 0;" slot="header"> <button class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left" type="button" aria-label="前一年" @click="prev" ></button> <span class="el-date-picker__header-label">{{ year }}年</span> <button class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right" type="button" aria-label="后一年" @click="next" ></button> </div> <div class="text item" style="text-align: center;"> <el-button style="width: 40%;color: #606266;float: left;" type="text" size="medium" @click="selectSeason(0)" >第一季度 </el-button> <el-button style="width: 40%;color: #606266;float: right;" type="text" size="medium" @click="selectSeason(1)" >第二季度 </el-button> </div> <div class="text item" style="text-align: center;"> <el-button style="width: 40%;color: #606266;float: left;" type="text" size="medium" @click="selectSeason(2)" >第三季度 </el-button> <el-button style="width: 40%;color: #606266;float: right;" type="text" size="medium" @click="selectSeason(3)" >第四季度 </el-button> </div> </el-card> </div> </template> <script> export default { name: "quarter-picker", model: { prop: 'inputValue', event: 'inputValue' }, props: { valueArr: { type: Array, default: () => { return ['01-01,03-31', '04-01,06-30', '07-01,09-30', '10-01,12-31']; } }, placeholder: { type: String, default: '請選擇季度' }, inputValue: { type: Array, default: function() { return []; } }, changeValue: { type: Function, default: () => {} }, otherData: { type: Object, default: () => { return {}; } } }, mounted() { if (this.inputValue != null && this.inputValue.length > 0) { this.showText(this.inputValue); } window.addEventListener('scroll', this.handleScroll, true); }, watch: { inputValue(newValue) { if (newValue.length > 0) { this.showText(newValue); } else { this.showValue = ""; } } }, data() { return { showSeason: false, showValue: '', year: new Date().getFullYear(), season: '', divTop: 0 }; }, methods: { handleScroll() { let inputText = this.$refs.inputText.$el; if (inputText.getBoundingClientRect().top + 220 > document.body.offsetHeight) { this.divTop = inputText.getBoundingClientRect().top - 215; } else { this.divTop = inputText.getBoundingClientRect().top + 30; } }, clickInput() { this.handleScroll(); this.showSeason = true; }, prev() { this.year = this.year * 1 - 1; }, next() { this.year = this.year * 1 + 1; }, selectSeason(i) { let that = this; that.season = i + 1; // 得到當前季度 let arr = that.valueArr[i].split(','); let value = []; let start = that.year + '-' + arr[0]; // 得到當前季度的開始日期 let end = that.year + '-' + arr[1]; // 得到當前季度的結束日期 value.push(start); // 將季度開始日期和季度結束日期存入數組中 value.push(end); if (this.inputValue != null && this.inputValue[0] != value[0]) { this.changeValue(value, this.otherData); } this.$emit('inputValue', value); that.showSeason = false; this.showText(value); }, showText(value) { // value為數組,數組索引為0的值為季度開始時間 let arr = value[0].split('-'); // 將季度開始時間用-進行分割 this.year = arr[0]; let month = arr[1]; this.season = Math.ceil(month / 3); // 向上取整 this.showValue = `${this.year}年${this.season}季度`; // 設置顯示格式 } } } </script> <style scoped> ._mark { position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0); z-index: 999; } .yearBtn { text-align: center; padding: 0 } .box-card { width: 322px; padding: 0 3px 20px; margin-top: 10px; position: fixed; z-index: 9999 } .text.item { text-align: center; } .text.item >>> .el-button { width: 40%; color: #606266; } .text.item ._left { float: left; } .text.item ._right { float: right; } </style>
2、引入季度選擇器組件
import QuarterPicker from "../../../components/quarter-picker/index";
3、注冊季度選擇器組件
components: { QuarterPicker },
4、使用季度選擇器組件
<el-table-column label="季度" align="center" width="150px"> <template slot-scope="scope"> <quarter-picker v-model="scope.row.quarter" readonly="readonly" :other-data="scope.row" :change-value="saveQuarter" /> </template> </el-table-column>
通過other-data屬性將scope.row傳遞到子組件,通過change-value將saveQuarter方法傳遞到子組件,然后在子組件中調用saveQuarter方法。
其中saveQuarter方法如下:
saveQuarter(value, row) { const data = { id: row.id, start: value[0], // 季度開始日期 end: value[1] // 季度結束日期 }; inAPI.saveOrUpdateQuarter(data).then(response => { if (response.success) { this.$message.success(response.msg); } }); },
后台可以使用NVARCHAR2存儲季度,長度為6,格式為:年度-季度,如2022-1,2022-2,2022-3,2022-4
將季度開始時間轉化為季度的方法:
private String toQuarter(String start) { String[] arr = start.split("-"); String year = arr[0]; String month = arr[1]; int q = Integer.parseInt(month) / 3 + 1; return year + "-" + q; }
將季度轉成季度開始日期和季度結束日期的方法:
private List<String> toRange(String quarter) { List<String> result = new ArrayList<>(); String[] arr = quarter.split("-"); String year = arr[0]; String q = arr[1]; switch (q) { case "1": result.add(year + "-01-01"); result.add(year + "-03-31"); break; case "2": result.add(year + "-04-01"); result.add(year + "-06-30"); break; case "3": result.add(year + "-07-01"); result.add(year + "-09-30"); break; case "4": result.add(year + "-10-01"); result.add(year + "-12-31"); break; } return result; }