magiccube-vue3
Version:
vue3-js版组件库
217 lines (194 loc) • 7.11 kB
JavaScript
import { ref, reactive, computed } from 'vue'
import * as utils from '../../utils/common'
import MonthCell from './month-cell'
import YearCell from './year-cell'
/**
* 日历控件操作功能封装层
*/
const Inner = {
props: {
data: Array,
/** 支持两种类型 default和range,其中default包含单选和多选 */
type: {
type: String,
default: 'default'
},
multi: Boolean,
enableStart: String,
enableEnd: String,
},
emits: ['change'],
setup(props, { emit, expose }) {
const state = reactive({
view: 'month',
year: '',
// range日历中 右侧日历日期显示
endYear: '',
})
const cacheValue = ref([])
const model = computed({
get(){
const v = cacheValue.value.length? cacheValue.value : props.data
return v.map(n => utils.dateFormat(n, 'YYYY/MM/DD'))
},
set(value){
cacheValue.value = value
}
})
/**
* 日历视图初始化
* 在dropdown打开时 进行一次初始化
* 在切换月或年时 再次进行日历视图初始化
*/
const set = (date = '') => {
const initValue = cacheValue.value?.length? cacheValue.value[0] : ''
const d = date ? new Date(date) : initValue ? new Date(initValue) : new Date()
state.view = 'month'
state.year = d.getFullYear()
if(props.type === 'range') {
state.endYear = state.year + 1
}
}
const reset = () => {
cacheValue.value = []
}
/**
* toolbar中 切换按钮点击函数
*/
const handleChangeView = (e, action) => {
e.stopPropagation()
switch (action) {
// 上年
case 'prev_year': {
set(`${state.year - 1}/1/1`)
break
}
// 下年
case 'next_year': {
set(`${state.year + 1}/1/1`)
break
}
case 'change_year': {
state.view = 'year'
break
}
}
}
// 年份或月份切换选择函数
const handleChangeYear = (value) => {
state.view = 'month'
state.year = value
}
const handleSelectMonth = (value) => {
const v = sortRangeResult(value)
model.value = v
emit('change', v)
}
const toolbarNode = (forward) => (
<div class="mc-month__toolbar">
<div class="mc-month__toolbar--child">
{
props.type !== 'range' || (props.type === 'range' && forward === 'left') ? (
<>
<span class="mc-month__toolbar--year" onClick={(e) => handleChangeView(e, 'prev_year')}></span>
</>
) : ''
}
</div>
<div class="mc-month__toolbar--child current-date-view">
<span class={{
disabled: props.type === 'range'
}}
onClick={(e) => handleChangeView(e, 'change_year')}>
{forward === 'right'? state.endYear : state.year}年
</span>
</div>
<div class="mc-month__toolbar--child">
{
props.type !== 'range' || (props.type === 'range' && forward === 'right') ? (
<>
<span class="mc-month__toolbar--year right" onClick={(e) => handleChangeView(e, 'next_year')}></span>
</>
) : ''
}
</div>
</div>
)
const monthViewNode = () => {
if (props.type === 'range') {
return (
<>
<div class="mc-month__range left">
{toolbarNode('left')}
<MonthCell v-model={model.value}
year={state.year}
type={props.type}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
onChange={handleSelectMonth} />
</div>
<div class="mc-month__range right">
{toolbarNode('right')}
<MonthCell v-model={model.value}
year={state.endYear}
type={props.type}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
onChange={handleSelectMonth} />
</div>
</>
)
} else {
return (
<>
{toolbarNode()}
<MonthCell v-model={model.value}
year={state.year}
type={props.type}
multi={props.multi}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
onChange={handleSelectMonth} />
{
props.multi ? (
<div class="mc-month__footer">
<McButton onClick={handleConfirm}>确定</McButton>
</div>
) : ''
}
</>
)
}
}
// 单日历 多选时 需要点击确定按钮 才会更新选中的结果
const handleConfirm = () => {
if (props.multi) {
emit('change', model.value)
}
}
// 对结果进行排序
const sortRangeResult = (value) => {
return value.sort((a, b) => new Date(a).getTime() - new Date(b).getTime())
}
expose({
set,
reset
})
return () => (
<div class={[
'mc-month__panel',
{
range: props.type === 'range'
}
]}>
{
state.view === 'year' ? <YearCell year={state.year} onChange={handleChangeYear} /> : ''
}
{
state.view === 'month' ? monthViewNode() : ''
}
</div>
)
}
}
export { Inner, Inner as default }