elementUI 日 周 月 季 年 时间选择控件封装

it2022-05-06  6

项目需求,时间选择需要满足按日,按周,按月,按季,按年进行选择,然后组件封装是基于elementUI的,实现效果如图:

日周月季年都有默认选择时间,项目需求,不能选择当前时间,所以按日选择,默认时间为昨天,按周选择默认时间为上周,以此类推。因为elementUI没有季度选择控件,所以这块也是在网上找的大神封装的,借用一下,表示感谢!季度控件,我在大神的基础上添加了时间禁用选项,包括当前及未来时间不能点击及样式定义。

那么季度时间选择为一个单独的组件,其余时间选择为一个组件,季度组件需引入总时间组件页面。

先说elementUI自带的吧:

<template> <!-- 日 周 月 季 年 时间选择控件 --> <div class="datetimepicker"> <el-select v-model="selectt" @change="dateTypeSelectChange" placeholder="请选择" style="width:65px;" > <el-option label="日" value="1"></el-option> <el-option label="周" value="2"></el-option> <el-option label="月" value="3"></el-option> <el-option label="季" value="4"></el-option> <el-option label="年" value="5"></el-option> </el-select> <el-date-picker v-if="selectt === '1'" format="yyyy-MM-dd" value-format="yyyy-MM-dd" :picker-options="dayDateOption" v-model="listQuery.day" @change="dayChange" type="date" placeholder="选择日" ></el-date-picker> <el-date-picker v-if="selectt === '2'" v-model="listQuery.week" type="week" format="yyyy 第 WW 周" :picker-options="weekDateOption" :editable="false" @change="weekdayChange" placeholder="选择周" ></el-date-picker> <el-date-picker v-if="selectt === '3'" v-model="listQuery.month" type="month" format="yyyy-MM" value-format="yyyy-MM" :picker-options="monthDateOption" :editable="false" @change="monthChange" placeholder="选择月" ></el-date-picker> <span v-if="selectt === '4'"> <!--季度时间选择控件 --> <jidu-date-picker ref="jidupicker" @chooseSeason="seasonChange" ></jidu-date-picker> </span> <el-date-picker v-if="selectt === '5'" v-model="listQuery.year" type="year" format="yyyy" value-format="yyyy" :picker-options="yearDateOptions" :editable="false" @change="yearChange" placeholder="选择年" ></el-date-picker> </div> </template>

那么主要的时间项配置都来源于elementUI官网,需要的可以查阅。

<script> // 这个项目使用的是vue3,数据与dom是分离显示的,主要是为了方便后期维护,数据全部是放在 // 引入的 datetimepickerapi 文件里 import datetimepickerapi from "@/api/components/datetimepacker"; import Base from "@/utils/BaseVue.js"; import jiduDatePicker from "@/components/datetimepicker/jiduDatePicker"; // 引入季度时间组件 const datetimepicker = { name: "datetimepicker", data() { // 如果不喜欢,或者项目没有使用这种数据分离方式开发,那么可以像之前那样,导出一个对象, // 将 datetimepickerapi 文件里的所有数据放在 data 方法里面即可 return datetimepickerapi.data; }, components: { jiduDatePicker }, props: {}, methods: { dateTypeSelectChange(val) { // 选择时间类型下拉,及默认时间设置 const data = {}; if (val === "1") { data.num = "1"; data.time = this.getDate(new Date().getTime() - 24 * 3600 * 1000); } else if (val === "2") { data.num = "2"; data.time = this.getDate(new Date().getTime() - 24 * 3600 * 1000 * 7); } else if (val === "3") { data.num = "3"; data.time = this.getBeforeMonth(); } else if (val === "4") { data.num = "4"; data.time = this.getBeforeSeason(); this.$nextTick(() => { this.$refs["jidupicker"].reset(); }); } else if (val === "5") { data.num = "5"; data.time = this.getBeforeYear(); } this.timereset(); this.$emit("dateTypeSelectChange", data); }, dayChange(val) { if (val) { // 在进行时间选择时,change事件可以获取到当前选择的时间,按日或者按月等都会向后台传递一个参数dateType, // 即当前的时间类型,按日或按年等,而与后台协商后,不管是按日或按年或其他,都向后台传递一个 // 完整的时间格式字符串,所以在向父组件发送时间之前,我对时间格式进行了拼接,最终格式都如2019-07-01这种, // 又因为项目时间不能选择当前时间,所以按日查询,为昨天时间,选择到天不需要拼接,按月为上一个月, // 选择到月需要拼接,按周为上一周的某一天,进行时间格式转化。 this.$emit("datetimeChange", val); } else { this.$emit("datetimeChange", this.getDate(new Date().getTime() - 24 * 3600 * 1000)); } }, weekdayChange(val) { if (val) { const week = this.getDate(val); this.$emit("datetimeChange", week); } else { this.$emit("datetimeChange", this.getDate(new Date().getTime() - 24 * 3600 * 1000)); } // console.log("周 子组件"); // console.log("v-modal绑定值" + this.listQuery.week); // console.log("转换后的" + week); }, monthChange(val) { if (val) { // 按月查询,需要拼接时间,因为与后台商定,不管是按日周月季年那种方式,后台都接受完整的年月日格式的时间参数 const month = val + "-01"; this.$emit("datetimeChange", month); } else { this.$emit("datetimeChange", this.getDate(new Date().getTime() - 24 * 3600 * 1000)); } // console.log("月"); // console.log("v-model" + val); // console.log(this.listQuery.month); }, seasonChange(val) { console.log("季"); console.log(val); this.$emit("datetimeChange", val); }, yearChange(val) { // console.log("年"); // console.log(val); if (val) { const year = val + "-01-01"; this.$emit("datetimeChange", year); } else { this.$emit("datetimeChange", this.getDate(new Date().getTime() - 24 * 3600 * 1000)); } }, timereset() { // 时间重置 const date = new Date(); const year = date.getFullYear(); const month = date.getMonth(); const day = date.getDate(); const week = date.getDay(); this.listQuery.day = this.getDate( new Date().getTime() - 24 * 3600 * 1000 ); this.listQuery.week = new Date(date.getTime() - 24 * 3600 * 1000 * 7); this.listQuery.month = this.getBeforeMonth(); // 在该组件里面并没有对季度时间选择组件进行重置,主要是因为挂在顺序的问题,因为在mounted重置时, // 默认显示的月,季度组件并没用渲染,所以我第一次使用的this.$refs["jidupickerref"].reset()方法报错。 this.listQuery.year = new Date(date.getTime() - 24 * 3600 * 1000 * 365); }, reset() { this.selectt = "3"; this.timereset(); }, getDate(time) { // 时间格式转化 年-月-日 var date = new Date(time); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; }, getBeforeMonth() { // 获取上个月时间 年-月-日 var seperator1 = "-"; var day = "01"; var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; if (month === 1) { year -= 1; month = 12; } else { month -= 1; } if (month >= 1 && month <= 9) { month = "0" + month; } var currentdate = year + seperator1 + month + seperator1 + day; return currentdate; }, getBeforeSeason() { // 获取上一季度 const year = new Date().getFullYear(); const month = new Date().getMonth() + 1; if (month <= 3) { year -= 1; return `${year}-10-01`; } else if (month > 3 && month <= 6) { return `${year}-01-01`; } else if (month > 6 && month <= 9) { return `${year}-04-01`; } else if (month > 9 && month <= 12) { return `${year}-07-01`; } }, getBeforeYear() { // 获取上一年 const year = new Date().getFullYear() - 1; return `${year}-01-01`; } }, created() {}, mounted() { this.timereset(); }, computed: {}, watch: {} }; Base.extendModel(datetimepicker); export default datetimepicker; </script>

强调一下,日周月季年时间选择input绑定的数据,与发送到父组件的数据是不同的,发送到父组件的参数是拼接后的数据。 

// 这是时间选择组件的数据项,传统方式可以将 datetimepackerData 数据放于组件内部的data方法中 import Base from "../Base"; class dateTimePacker extends Base { constructor(props) { super(props); let datetimepackerData = { selectt: "3", listQuery: { day: "", week: "", month: "", season: "", year: "" }, dayDateOption: { firstDayOfWeek: 1, disabledDate(time) { return time.getTime() > Date.now() - 8.64e7; } }, weekDateOption: { firstDayOfWeek: 1, disabledDate(time) { const week = new Date().getDay(); return time.getTime() > Date.now() - 8.64e7 * week; } }, monthDateOption: { disabledDate(time) { return time.getTime() > Date.now() - 8.64e7 * 30; } }, yearDateOptions: { disabledDate: time => { return time.getTime() > Date.now() - 8.64e7 * 30 * 12; } } }; this.data = this.$utils.extendsCreate(this.data, datetimepackerData); } apiLogin() { console.log("接口调用"); // 接口调用 } } export default new dateTimePacker();

重申一下,不管是按日周月季年,那种方式,向后台传递参数格式都为 yyyy-mm-dd,后台插件会根据当前时间和当前时间类型(日,周等)自动返回用户选择的时间区间,但是这仅仅是以来本项目需求,项目不同的,可以相应改变。

下面是季度时间组件:

<template> <!-- 季度选择时间控件 --> <div class="jidudatepicker"> <span> <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="选择季度" v-model="showValue" style="width:2.7rem;height: 0.36rem;line-height: 0.36rem;" @focus="showSeason=true" > <i slot="prefix" class="el-input__icon el-icon-date"></i> </el-input> <el-card class="box-card" style="width:322px;padding: 0 3px 20px;margin-top:10px;position:fixed;z-index:9999" v-show="showSeason" > <div slot="header" class="firstBtn"> <button type="button" aria-label="前一年" class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left" @click="prev" ></button> <span role="button" class="el-date-picker__header-label">{{year}}年</span> <button type="button" aria-label="后一年" @click="next" class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right" ></button> </div> <div class="text container"> <!-- 如下,绑定class,disabled为禁止选择的时间的设置 --> <el-button type="text" size="medium" :class="{'colorDis': this.year === this.beforeyear && this.season <= 1 || this.year > this.defaultyear}" :disabled="this.year === this.beforeyear && this.season <= 1 || this.year > this.defaultyear" style="width:47%;color: #606266;float:left;" @click="selectSeason(0)" >第一季度</el-button> <el-button type="text" size="medium" :class="{'colorDis': this.year === this.beforeyear && this.season <= 2 || this.year > this.defaultyear}" :disabled="this.year === this.beforeyear && this.season <= 2 || this.year > this.defaultyear" style="float:right;width:47%;color: #606266;" @click="selectSeason(1)" >第二季度</el-button> </div> <div class="item container" style="text-align:center;"> <el-button type="text" size="medium" :class="{'colorDis': this.year === this.beforeyear && this.season <= 3 || this.year > this.defaultyear}" :disabled="this.year === this.beforeyear && this.season <= 3 || this.year > this.defaultyear" style="width:47%;color: #606266;float:left;" @click="selectSeason(2)" >第三季度</el-button> <el-button type="text" size="medium" :class="{'colorDis': this.year === this.beforeyear && this.season <= 4 || this.year > this.defaultyear}" :disabled="this.year === this.beforeyear && this.season <= 4 || this.year > this.defaultyear" style="float:right;width:47%;color: #606266;" @click="selectSeason(3)" >第四季度</el-button> </div> </el-card> </span> </div> </template> <script> /** * @file: View 组件 季节选择控件 * @description: UI组件 可选择季节 * @api: valueArr : 季度value defalut['01-03', '04-06', '07-09', '10-12'] 默认值待设置 * 代码中注释部分是组件原默认时间配置,我这里做了更改,但是原设置可以参考 */ export default { name: "jududatepicker", props: { valueArr: { default: () => { return ["01-03", "04-06", "07-09", "10-12"]; }, type: Array }, getValue: { default: val => { return val; }, type: Function } // defaultValue: { // // 默认值 201904-201906 // default: "", // type: String // } }, data() { return { showSeason: false, season: "", year: new Date().getFullYear(), // input显示时间,会随着用户操作改变 defaultyear: new Date().getFullYear(), // 当前年份,不变 month: new Date().getMonth() + 1, // 当前月份,不变 showValue: "", beforeyear: null // 默认显示上一季度所用时间,可能是去年 }; }, created() { // if (this.defaultValue) { // let value = this.defaultValue; // let arr = value.split("-"); // this.year = arr[0].slice(0, 4); // let str = arr[0].slice(4, 6) + "-" + arr[1].slice(4, 6); // let arrAll = this.valueArr; // // valueArr ["01-03", "04-06", "07-09", "10-12"] // this.showValue = `${this.year} 年 ${arrAll.indexOf(str) + 1} 季度`; // } }, mounted() { // 每次挂在时都对组件进行重置,那么就不需要在上级组件中进行重置 this.getDefaultTime(); }, watch: { // defaultValue: function(value, oldValue) { // let arr = value.split("-"); // this.year = arr[0].slice(0, 4); // let str = arr[0].slice(4, 6) + "-" + arr[1].slice(4, 6); // let arrAll = this.valueArr; // // valueArr ["01-03", "04-06", "07-09", "10-12"] // this.showValue = `${this.year} 年 ${arrAll.indexOf(str) + 1} 季度`; // } }, methods: { one() { this.showSeason = false; }, 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 seasonValue = that.getValue(that.year + "-" + arr[0] + "-" + "01"); that.showSeason = false; this.showValue = `${this.year} 年 ${this.season} 季度`; that.$emit("chooseSeason", seasonValue); // 每次选择时间都将当前选择时间发送到父组件 }, reset() { // 季度重置 上一季度 this.getDefaultTime(); }, getDefaultTime() { // 获取默认的上一个季度 var year = this.defaultyear; var month = this.month; var season = null; if (month <= 3) { this.season = 1; year -= 1; season = 4; this.beforeyear = year; } else if (month > 3 && month <= 6) { this.season = 2; season = 1; this.beforeyear = year; } else if (month > 6 && month <= 9) { this.season = 3; season = 2; this.beforeyear = year; } else if (month > 9 && month <= 12) { this.season = 4; season = 3; this.beforeyear = year; } this.showValue = `${year} 年 ${season} 季度`; } } }; </script> <style lang="scss" scoped> .jidudatepicker { display: inline; .firstBtn { height: 30px; line-height: 34px; width: 100%; text-align: center; } .text { text-align: center; margin: 15px 0 10px; } .item { text-align: center; } } .colorDis { color: #999 !important; } </style> <style lang="scss"> .jidudatepicker { .el-card__header { padding: 12px; } } </style>

以上就是日周月季年时间选择控件的全部内容,需求不同的,可以进行更该。季度组件效果图如图:

 

baseVue.js文件

import $Utils from "./CollectionUtils.js"; import JButton from "components/j-element/JButton"; import { formatDate, getBeforeMonth, formatDateZeroArr, formatDateTime, formatDate8Time } from "@/utils/validate"; import { resolve } from "url"; import { reject } from "q"; const webSource = { websocket: null, currentRouter: "" }; const Base = { methods: { formatDate(date, fmt) { return formatDate(date, fmt); }, getBeforeMonth() { return getBeforeMonth(); }, formatDateZeroArr(date) { return formatDateZeroArr(date); }, formatDateTime() { return formatDateTime(); }, formatDate8Time() { return formatDate8Time(); }, activeNav() { //app let routerMenuPath = this.$router.currentRoute; let current = new Array(); if (this.$router.currentRoute.name === "Dashboard") { current.push({ name: "首页", path: "/layout/dashboard" }); } if (routerMenuPath.meta.menu_path) { let keyPath = this.$CollectionUtils.deepClone( routerMenuPath.meta.menu_path ); keyPath.push(this.$router.currentRoute.name); if (this.$CollectionUtils.isNull(this.menuList)) { for (let i in keyPath) { current.push(this.menuList[keyPath[i]]); } } } this.$store.dispatch("currentNav", current); }, openNotify() { //app this.$notify({ title: "HTML 片段", type: "warning", dangerouslyUseHTMLString: true, message: "<strong>这是 <i>HTML</i> 片段</strong>" }); }, openWebSocket() { console.log(`WebSocket连接成功${process.env.VUE_APP_SRC}`); }, webSocketOnError() { console.log("WebSocket连接发生错误"); this.initWebSocket(); }, webSocketSend(agentData) { // console.log('发送数据'); this.websocket.send(agentData); }, webSocketClose() { this.websocket.close(); }, initWebSocket(onmessage) { //初始化weosocket // this.websocket = new WebSocket("ws://192.168.5.169:6947"); // this.websocket = new WebSocket("ws://192.168.5.127:6947"); // this.websocket = new WebSocket("ws://1.85.32.5:51245"); this.websocket = new WebSocket(process.env.VUE_APP_SRC); this.websocket.onopen = this.openWebSocket; this.websocket.onerror = this.webSocketOnError; this.websocket.onmessage = onmessage; }, getBrowser() { var swf = false; if (typeof window.ActiveXObject !== "undefined") { swf = new window.ActiveXObject("ShockwaveFlash.ShockwaveFlash"); } else { swf = navigator.plugins["Shockwave Flash"]; } return swf; } }, computed: { users() { return {}; } }, beforeRouteEnter: (to, from, next) => { // console.log(to.name) next(); }, beforeRouteLeave: (to, from, next) => { // console.log('beforeRouteLeave') next(); }, extendModel(vueObj) { if (!vueObj.computed) { vueObj.computed = {}; } let computed = vueObj.computed; Object.keys(this.computed).forEach(key => { if (!computed[key]) { computed[key] = this.computed[key]; } }); if (!vueObj.methods) { vueObj.methods = {}; } let methods = vueObj.methods; Object.keys(this.methods).forEach(key => { if (!methods[key]) { methods[key] = this.methods[key]; } }); if (!vueObj.components) { vueObj.components = {}; } let components = vueObj.components; Object.keys(this.components).forEach(key => { if (!components[key]) { components[key] = this.components[key]; } }); vueObj.beforeRouteEnter = vueObj.beforeRouteEnter || this.beforeRouteEnter; vueObj.beforeRouteLeave = vueObj.beforeRouteLeave || this.beforeRouteLeave; return vueObj; }, components: { JButton } }; export default Base;

 


最新回复(0)