magiccube-vue3
Version:
vue3-js版组件库
217 lines (195 loc) • 7.37 kB
JavaScript
import { ref, reactive, computed } from 'vue'
import * as utils from '../../utils/common'
import Calendar from './calendar'
import YearView from './year-view'
import MonthView from './month-view'
import Toolbar from './toolbar'
/**
* 日历控件操作功能封装层
*/
const Inner = {
props: {
data: Array,
type: String,
multi: Boolean,
enableStart: String,
enableEnd: String,
},
emits: ['change'],
setup(props, { emit, expose }) {
const state = reactive({
view: 'day',
year: '',
month: '',
// range日历中 右侧日历日期显示
endYear: '',
endMonth: '',
// 年份选择视图中 年份显示
yearChoiceCenter: ''
})
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 = model.value?.length ? model.value[0] : ''
const d = date ? new Date(date) : initValue ? new Date(initValue) : new Date()
state.view = 'day'
state.year = d.getFullYear()
state.month = d.getMonth() + 1
}
const reset = () => {
cacheValue.value = []
}
// range类型 日历视图的列表内容
const rangeToView = computed(() => {
const d = new Date(`${state.year}/${state.month}/1`)
const month = d.getMonth() + 1
d.setMonth(month)
const start = utils.dateFormat(`${state.year}/${state.month}/1`, 'YYYY/MM/DD')
const end = utils.dateFormat(d, 'YYYY/MM/DD')
state.endYear = d.getFullYear()
state.endMonth = d.getMonth() + 1
return [start, end]
})
// 单日历 日历列表内容
const singleView = computed(() => {
return utils.dateFormat(`${state.year}/${state.month}/1`, 'YYYY/MM/DD')
})
/**
* toolbar中 切换按钮点击函数
*/
const dayViewNode = () => {
if (props.type === 'range') {
return (
<>
<div class="mc-date__range left">
<Toolbar
type={props.type}
forward="left"
year={state.year}
month={state.month}
endYear={state.endYear}
endMonth={state.endMonth}
onChange={handleChangeToolbar} />
<Calendar v-model={model.value}
type={props.type}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
view-date={rangeToView.value[0]}
onChange={handleChangeValue} />
</div>
<div class="mc-date__range right">
<Toolbar
type={props.type}
forward="right"
year={state.year}
month={state.month}
endYear={state.endYear}
endMonth={state.endMonth}
onChange={handleChangeToolbar} />
<Calendar v-model={model.value}
type={props.type}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
view-date={rangeToView.value[1]}
onChange={handleChangeValue} />
</div>
</>
)
} else {
return (
<>
<Toolbar
type={props.type}
year={state.year}
month={state.month}
endYear={state.endYear}
endMonth={state.endMonth}
onChange={handleChangeToolbar} />
<Calendar v-model={model.value}
multi={props.multi}
enableStart={props.enableStart}
enableEnd={props.enableEnd}
view-date={singleView.value}
onChange={handleChangeValue} />
{
props.multi ? (
<div class="mc-date__footer">
<McButton onClick={handleConfirm}>确定</McButton>
</div>
) : ''
}
</>
)
}
}
// 单日历 多选时 需要点击确定按钮 才会更新选中的结果
const handleConfirm = () => {
if (props.multi) {
emit('change', model.value)
}
}
const handleChangeYear = (year) => {
state.view = 'day'
state.year = year
}
const handleChangeMonth = (month) => {
state.view = 'day'
state.month = month
}
const handleChangeToolbar = (data) => {
const { type, year, month, view } = data
if (type === 'view') {
state.view = view
} else {
state.year = year
state.month = month
}
}
// 选择日期函数
const handleChangeValue = (value) => {
const _val = sortRangeResult(value)
model.value = _val
emit('change', _val)
}
// 对结果进行排序
const sortRangeResult = (value) => {
return value.sort((a, b) => new Date(a).getTime() - new Date(b).getTime())
}
expose({
set,
reset
})
return () => (
<div class={[
'mc-date__panel',
{
range: props.type === 'range'
}
]}>
{
state.view === 'day' ? dayViewNode() : ''
}
{
state.view === 'year' ? <YearView year={state.year} onChange={handleChangeYear} /> : ''
}
{
state.view === 'month' ? <MonthView month={state.month} onChange={handleChangeMonth} /> : ''
}
</div>
)
}
}
export { Inner, Inner as default }