组件:
< ! -- * @Author: liuyu liuyu@xizhengtech. com* @Date: 2023 - 02 - 01 16 : 57 : 27 * @LastEditors: wangping wangping@xizhengtech. com* @LastEditTime: 2023 - 06 - 30 17 : 25 : 14 * @Description: 时间选择年 - 年
-- >
< template> < div class = "yearPicker" ref= "yearPicker" : width= "width" > < input class = "_inner" : style= "bindInputStyle" ref= "inputLeft" v- model= "startShowYear" @focus= "onFocus" @blur= "onBlur" type= "text" name= "yearInput" @keyup= "checkStartInput($event)" placeholder= "开始年份" / > < span> { { sp } } < / span> < input class = "_inner" : style= "bindInputStyle" ref= "inputRight" v- model= "endShowYear" @focus= "onFocus" @blur= "onBlur" type= "text" name= "yearInput" @keyup= "checkEndInput($event)" placeholder= "结束年份" / > < ! -- < i class = "dateIcon el-icon-date" > < / i> 按照自己标准库里面的图标设置-- > < ! -- < span class = "_inner labelText" > < / span> -- > < i class = "_inner labelText el-icon-date" > < / i> < div class = "_inner floatPanel" v- if = "showPanel" > < div class = "_inner leftPanel" > < div class = "_inner panelHead" > < i class = "_inner el-icon-d-arrow-left" @click= "onClickLeft" > < / i> { { leftYearList[ 0 ] + " - " + leftYearList[ 9 ] } } < / div> < div class = "_inner panelContent" > < div : class = "{ oneSelected : item === startYear && oneSelected, startSelected : item === startYear, endSelected : item === endYear, betweenSelected : item > startYear && item < endYear, } " v-for=" item in leftYearList" :key=" item"> < a : class = "{ cell : true , _inner : true , selected : item === startYear || item === endYear, } " @click=" onClickItem ( item) " @mouseover=" onHoverItem ( item) "> { { item } } < / a> < / div> < / div> < / div> < div class = "line" > < / div> < div class = "_inner rightPanel" > < div class = "_inner panelHead" > < i class = "_inner el-icon-d-arrow-right" @click= "onClickRight" > < / i> { { rightYearList[ 0 ] + " - " + rightYearList[ 9 ] } } < / div> < div class = "_inner panelContent" > < div : class = "{ startSelected : item === startYear, endSelected : item === endYear, betweenSelected : item > startYear && item < endYear, } " v-for=" item in rightYearList" :key=" item"> < a : class = "{ cell : true , _inner : true , selected : item === endYear || item === startYear, } " @click=" onClickItem ( item) " @mouseover=" onHoverItem ( item) "> { { item } } < / a> < / div> < / div> < / div> < / div> < / div>
< / template> < script>
import moment from "moment" ;
const SELECT_STATE = { unselect : 0 , selecting : 1 , selected : 2 ,
} ;
export default { name : "yearPicker" , computed : { bindInputStyle ( ) { return { "--placeholderColor" : "#c0c4cc" , } ; } , oneSelected ( ) { return ( this . curState === SELECT_STATE . selecting && ( this . startYear === this . endYear || this . endYear == null ) ) ; } , startDate ( ) { return this . startYear; } , leftYearList ( ) { return this . yearList. slice ( 0 , 10 ) ; } , rightYearList ( ) { return this . yearList. slice ( 10 , 20 ) ; } , startYearFormat ( ) { if ( this . _. isNil ( this . startYear) ) { return null ; } return moment ( this . startYear) . startOf ( "year" ) . format ( "yyyy" ) ; } , endYearFormat ( ) { if ( this . _. isNil ( this . endYear) ) { return null ; } return moment ( this . endYear) . endOf ( "year" ) . format ( "yyyy" ) ; } , } , props : { width : { default : 200 , } , labelWidth : { default : 40 , } , sp : { default : "-" , } , initYear : { default : null , } , } , data ( ) { return { itemBg : { } , startShowYear : null , endShowYear : null , yearList : [ ] , showPanel : false , startYear : null , endYear : null , curYear : 0 , curSelectedYear : 0 , curState : SELECT_STATE . unselect, } ; } , methods : { checkStartInput ( event ) { if ( isNaN ( this . startShowYear) ) { this . startShowYear = this . startYear; } else { this . startYear = this . startShowYear * 1 ; this . changeYear ( ) ; } } , checkEndInput ( ) { if ( isNaN ( this . endShowYear) ) { this . endShowYear = this . endYear; } else { this . endYear = this . endShowYear * 1 ; this . changeYear ( ) ; } } , changeYear ( ) { if ( this . startYear > this . endYear) { let tmp = this . endYear; this . endYear = this . startYear; this . startYear = tmp; this . startShowYear = this . startYear; this . endShowYear = this . endYear; } if ( this . startYear && this . endYear) { this . $emit ( "updateTimeRange" , { startYear : moment ( this . startYear + "" ) . startOf ( "year" ) . valueOf ( ) , endYear : moment ( this . endYear + "" ) . endOf ( "year" ) . valueOf ( ) + 1 , } ) ; } else { console. warn ( "WARN:年份不合法" , this . startYear, this . endYear) ; } } , onHoverItem ( iYear ) { if ( this . curState === SELECT_STATE . selecting) { let tmpStart = this . curSelectedYear; this . endYear = Math. max ( tmpStart, iYear) ; this . startYear = Math. min ( tmpStart, iYear) ; } } , onClickItem ( iYear ) { if ( this . curState === SELECT_STATE . unselect || this . curState === SELECT_STATE . selected) { this . startYear = iYear; this . curSelectedYear = iYear; this . endYear = null ; this . curState = SELECT_STATE . selecting; } else if ( this . curState === SELECT_STATE . selecting) { this . endShowYear = this . endYear; this . startShowYear = this . startYear; this . curState = SELECT_STATE . selected; this . $emit ( "updateTimeRange" , { startYear : moment ( this . startYear + "" ) . startOf ( "year" ) . valueOf ( ) , endYear : moment ( this . endYear + "" ) . endOf ( "year" ) . valueOf ( ) + 1 , } ) ; setTimeout ( ( ) => { this . showPanel = false ; } , 300 ) ; } } , onFocus ( ) { this . $nextTick ( ( ) => { this . showPanel = true ; } ) ; } , onBlur ( ) { } , updateYearList ( ) { let iStart = Math. floor ( this . curYear / 10 ) * 10 - 10 ; iStart = iStart < 0 ? 0 : iStart; this . yearList = [ ] ; for ( let index = 0 ; index < 20 ; index++ ) { this . yearList. push ( iStart + index) ; } } , closePanel ( e ) { if ( ! this . showPanel) { return ; } if ( typeof e. target. className !== "string" ) { this . $nextTick ( ( ) => { this . showPanel = false ; } ) ; return ; } if ( e. target. className. indexOf ( "_inner" ) === - 1 || ( e. target. name === "yearInput" && e. target !== this . $refs. inputLeft && e. target !== this . $refs. inputRight) ) { this . $nextTick ( ( ) => { this . showPanel = false ; } ) ; } e. stopPropagation ( ) ; return false ; } , onClickLeft ( ) { this . curYear = this . curYear * 1 - 10 ; this . updateYearList ( ) ; } , onClickRight ( ) { this . curYear = this . curYear * 1 + 10 ; this . updateYearList ( ) ; } , setYear ( startYearStamp, endYearStamp ) { if ( ! isNaN ( startYearStamp) && ! isNaN ( endYearStamp) ) { let startYear = moment ( startYearStamp) . format ( "yyyy" ) ; let endYear = moment ( endYearStamp) . format ( "yyyy" ) ; this . startYear = startYear * 1 ; this . endYear = endYear * 1 ; this . endShowYear = endYear * 1 ; this . startShowYear = startYear * 1 ; } } , } , created ( ) { this . curYear = moment ( ) . format ( "yyyy" ) ; this . updateYearList ( ) ; } , beforeUnmount ( ) { document. removeEventListener ( "click" , this . closePanel . bind ( this ) ) ; } , mounted ( ) { this . $refs. yearPicker. style = "padding-left:" + this . labelWidth + "px" ; document. addEventListener ( "click" , this . closePanel . bind ( this ) ) ; } ,
} ;
< / script>
< style lang= "scss" scoped>
. yearPicker { font- size: 14px; display : flex; position : relative; transition : all 0 . 3s; input { & : : placeholder { color : var ( -- placeholderColor) ; } } input : first- child { text- align: center; } . labelText { position : absolute; left : 10px; top : 10px; color : #c4c6d1; } background- color: #fff; span { padding : 0 8px; height : 36px; line- height: 36px; } border : 1px solid #eff1f3; height : 36px; line- height: 36px; border- radius: 4px; padding : 0 28px 0 8px; box- sizing: border- box; . floatPanel { > div { width : 50 % ; } position : absolute; display : flex; background- color: #fff; z- index: 9999 ! important; border- radius: 4px; height : 252px; top : 50px; left : 0px; box- shadow: 0 2px 12px 0 rgba ( 0 , 0 , 0 , 0.1 ) ; border : 1px solid #dfe4ed; . panelContent { display : grid; grid- template- columns: 25 % 25 % 25 % 25 % ; width : 100 % ; height : calc ( 100 % - 15px) ; margin- top: 8px; . oneSelected { border- top- right- radius: 24px; border- bottom- right- radius: 24px; } . startSelected { background- color: #f2f6fc; border- top- left- radius: 24px; border- bottom- left- radius: 24px; } . endSelected { background- color: #f2f6fc; border- top- right- radius: 24px; border- bottom- right- radius: 24px; } . betweenSelected { background- color: #f2f6fc; } > div { width : 75px; height : 48px; line- height: 48px; margin : 6px 0 ; text- align: center; a { display : inline- block; width : 60px; height : 36px; cursor : pointer; line- height: 36px; border- radius: 18px; color : #606266 ; } . selected { background- color: #1890ff; color : #fff; } } } . panelHead { height : 38px; line- height: 38px; position : relative; text- align: center; font- size: 16px; border- bottom: 1px solid #dfe4ed; i { position : absolute; cursor : pointer; & : hover { color : #1890ff; } } } . rightPanel { margin : 16px; display : flex; flex- direction: column; } . line { width : 1px; height : 100 % ; background : #dfe4ed; } . leftPanel { margin : 16px; display : flex; flex- direction: column; } . leftPanel . panelHead i { left : 0px; top : 10px; font- size: 14px; color : #717273 ; } . rightPanel . panelHead i { right : 0px; top : 8px; } . leftPanel . panelHead i: hover, . rightPanel . panelHead i: hover { cursor : pointer; } } . floatPanel: : before { content : "" ; border- bottom: 6 . 5px solid #797979 ; border- left: 6 . 5px solid transparent; border- right: 6 . 5px solid transparent; position : absolute; left : 44px; - webkit- transform: translateX ( - 50 % ) ; transform : translateX ( - 50 % ) ; top : - 5 . 5px; border- radius: 5px; } . floatPanel: : after { content : "" ; border- bottom: 8px solid #fff; border- left: 8px solid transparent; border- right: 8px solid transparent; position : absolute; left : 44px; - webkit- transform: translateX ( - 50 % ) ; transform : translateX ( - 50 % ) ; top : - 5px; border- radius: 5px; }
}
input { width : 100px; border : none; height : 37px; line- height: 37px; box- sizing: border- box; background- color: transparent; text- align: center; color : #606266 ;
}
input : focus { outline : none; background- color: transparent;
}
. yearPicker: hover { border- color: #1890ff;
}
. dateIcon { position : absolute; right : 16px; top : 9px; color : #adb2bc;
}
< / style>
使用:
< YearYear1 style= "width:300px" : initYear= "dateValue2" @updateTimeRange= "updateStatisticYear" / > dateValue2 : [ ] , updateStatisticYear ( val ) { console. log ( "年" , val) ;
} ,