diff --git a/devui/time-picker/index.ts b/devui/time-picker/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..aaab8f2001f7f26a9c5e0ef4add186e4bd1fa15c --- /dev/null +++ b/devui/time-picker/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue' +import TimePicker from './src/time-picker' + +TimePicker.install = function(app: App): void { + app.component(TimePicker.name, TimePicker) +} + +export { TimePicker } + +export default { + title: 'TimePicker 时间选择器', + category: '数据录入', + status: undefined, // TODO: 组件若开发完成则填入"已完成",并删除该注释 + install(app: App): void { + + app.use(TimePicker as any) + } +} diff --git a/devui/time-picker/src/components/popup-line/composables/use-popue-line.ts b/devui/time-picker/src/components/popup-line/composables/use-popue-line.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a1b1e762ce5486d98d581ec2bd9fbcaff4436cb --- /dev/null +++ b/devui/time-picker/src/components/popup-line/composables/use-popue-line.ts @@ -0,0 +1,260 @@ +import { Ref, ref } from 'vue' +import { ArrType } from '../../../types' + +const usePopupLine = ( + hourListRef: Array, minuteListRef: Array, secondListRef: Array, + minTime: string, maxTime: string, format: string, timeListDom: Ref, +): any => { + + const activeTime = ref('00:00:00') + const activeHour = ref('00') + const activeMinute = ref('00') + const activeSecond = ref('00') + + const activeTimeFun = (e: any, item: ArrType, index: number) => { + if (item.isDisabled) { + return false + } else { + setTimeActive(item, index) + e.target.parentElement.scrollTop = index * 30 + } + } + + + const setTimeActive = (item: ArrType, index: number) => { + + let activeTimeList = [] + let acitveTimeValue = ref('') + if (item.flag == 'hour') { + activeTimeList = hourListRef + acitveTimeValue = activeHour + getItemAstrict(item) + } else if (item.flag == 'minute') { + activeTimeList = minuteListRef + acitveTimeValue = activeMinute + getItemAstrict(item) + } else if (item.flag == 'second') { + activeTimeList = secondListRef + acitveTimeValue = activeSecond + } + + activeTimeList.map((tiemItem) => { + tiemItem.isActive = false + }) + activeTimeList[index].isActive = true + acitveTimeValue.value = activeTimeList[index].time + + + activeTime.value = `${activeHour.value}:${activeMinute.value}:${activeSecond.value}` + + if (activeTime.value < minTime) { + activeTime.value = minTime + resetTimeValue(minTime) + } else if (format == 'mm:ss' && `${activeMinute.value}:${activeSecond.value}` > maxTime.slice(3)) { + const newMinTime = minTime.slice(0, 3) + maxTime.slice(3) + resetTimeValue(newMinTime) + } else if (activeTime.value > maxTime) { + activeTime.value = maxTime + resetTimeValue(maxTime) + } + } + + // 获取最大值 最小值 + const getItemAstrict = (item: ArrType): void => { + let min = '00' + let max = '00' + + const minTimeHour = minTime.split(':')[0] + const minTimeMinute = minTime.split(':')[1] + const minTimeSecond = minTime.split(':')[2] + + const maxTimeHour = maxTime.split(':')[0] + const maxTimeMinute = maxTime.split(':')[1] + const maxTimeSecond = maxTime.split(':')[2] + + if (item.flag == 'hour') { + if (item.time == minTimeHour) { + min = minTimeMinute + // console.log('11') + setItemAstrict(minuteListRef, min, max) + activeMinute.value < minTimeMinute && setItemAstrict(secondListRef, minTimeSecond, max) + } else if (item.time == maxTimeHour) { + max = maxTimeMinute + // console.log('22') + setItemAstrict(minuteListRef, min, max) + setItemAstrict(secondListRef, min, maxTimeSecond) + } else { + // console.log('33') + setItemAstrict(minuteListRef, min, max) + setItemAstrict(secondListRef, min, max) + } + } + if (item.flag == 'minute' && format == 'mm:ss') { + if (item.time == minTimeMinute) { + min = minTimeSecond + setItemAstrict(secondListRef, min, max) + } else if (item.time == maxTimeMinute) { + max = maxTimeSecond + setItemAstrict(secondListRef, min, max) + } else { + setItemAstrict(secondListRef, min, max) + } + } else if (item.flag == 'minute') { + if (activeHour.value == minTimeHour && item.time == minTimeMinute) { + min = minTimeSecond + setItemAstrict(secondListRef, min, max) + // console.log('44') + } else if (activeHour.value == maxTimeHour && item.time == maxTimeMinute) { + max = maxTimeSecond + // console.log('55') + setItemAstrict(secondListRef, min, max) + } else { + // console.log('66') + setItemAstrict(secondListRef, min, max) + } + } + + } + // 设置最大值 最小值 + const setItemAstrict = (timeArr: Array, min: string, max: string) => { + timeArr.map(itme => { + if (min != '00' && itme.time < min) { + itme.isDisabled = true + } else if (max != '00' && itme.time > max) { + itme.isDisabled = true + } else { + itme.isDisabled = false + } + }) + } + + // 指定时间 + const resetTimeValue = (time: string) => { + const timeValueArr = time.split(':') + const minTiveArr = minTime.split(':') + + let hh = 0 + let mm = 0 + let ss = 0 + + if (format == 'hh:mm:ss') { + + hh = parseInt(timeValueArr[0]) + mm = parseInt(timeValueArr[1]) + ss = parseInt(timeValueArr[2]) + + timeListDom.value.children[0].scrollTop = hh * 30 + timeListDom.value.children[1].scrollTop = mm * 30 + timeListDom.value.children[2].scrollTop = ss * 30 + + activeHour.value = timeValueArr[0] + activeMinute.value = timeValueArr[1] + activeSecond.value = timeValueArr[2] + + resetTimeActive(hourListRef, timeValueArr[0]) + resetTimeActive(minuteListRef, timeValueArr[1]) + resetTimeActive(secondListRef, timeValueArr[2]) + + resetTimeAstrict(hourListRef, activeHour.value) + resetTimeAstrict(minuteListRef, activeMinute.value) + + } + else if (format == 'mm:hh:ss') { + hh = parseInt(timeValueArr[0]) + mm = parseInt(timeValueArr[1]) + ss = parseInt(timeValueArr[2]) + + timeListDom.value.children[0].scrollTop = mm * 30 + timeListDom.value.children[1].scrollTop = hh * 30 + timeListDom.value.children[2].scrollTop = ss * 30 + + activeHour.value = timeValueArr[0] + activeMinute.value = timeValueArr[1] + activeSecond.value = timeValueArr[2] + + resetTimeActive(hourListRef, timeValueArr[0]) + resetTimeActive(minuteListRef, timeValueArr[1]) + resetTimeActive(secondListRef, timeValueArr[2]) + + resetTimeAstrict(hourListRef, activeHour.value) + resetTimeAstrict(minuteListRef, activeMinute.value) + + } else if (format == 'hh:mm') { + + hh = parseInt(timeValueArr[0]) + mm = parseInt(timeValueArr[1]) + + timeListDom.value.children[0].scrollTop = hh * 30 + timeListDom.value.children[1].scrollTop = mm * 30 + + activeHour.value = timeValueArr[0] + activeMinute.value = timeValueArr[1] + + resetTimeActive(hourListRef, timeValueArr[0]) + resetTimeActive(minuteListRef, timeValueArr[1]) + + resetTimeAstrict(hourListRef, activeHour.value) + + } else if (format == 'mm:ss') { + + mm = parseInt(timeValueArr[1]) + ss = parseInt(timeValueArr[2]) + + timeListDom.value.children[0].scrollTop = mm * 30 + timeListDom.value.children[1].scrollTop = ss * 30 + + activeHour.value = minTiveArr[0] + activeMinute.value = timeValueArr[1] + activeSecond.value = timeValueArr[2] + + resetTimeActive(minuteListRef, timeValueArr[1]) + resetTimeActive(secondListRef, timeValueArr[2]) + + resetTimeAstrict(minuteListRef, activeMinute.value) + } + // activeTime.value = `${activeHour.value}:${activeMinute.value}:${activeSecond.value}` + + } + + // 解决清空之后,再次打开 最大值最小值限制范围失效 + const resetTimeAstrict = (timeArr: Array, time: string) => { + timeArr.map(item => { + if (item.time == time) { + getItemAstrict(item) + } + }) + } + + // 指定选中 + const resetTimeActive = (timeArr: Array, itemValue: string) => { + timeArr.map(item => { + if (item.time == itemValue) { + item.isActive = true + } else { + item.isActive = false + } + }) + } + + // 暂时返回选中 时 分 秒 + const getNewTime = () => { + return { activeTime, activeHour, activeMinute, activeSecond } + } + + return { + activeTime, + activeHour, + activeMinute, + activeSecond, + activeTimeFun, + resetTimeValue, + getNewTime + } +} + +export { + usePopupLine +} + + + diff --git a/devui/time-picker/src/components/popup-line/index.scss b/devui/time-picker/src/components/popup-line/index.scss new file mode 100644 index 0000000000000000000000000000000000000000..b39d6ad208f47afd787fbaca1c3b1916709e94fe --- /dev/null +++ b/devui/time-picker/src/components/popup-line/index.scss @@ -0,0 +1,70 @@ +@import '../../../../style/theme/color'; +@import '../../../../style/theme/shadow'; +@import '../../../../style/theme/corner'; +@import '../../../../style/core/_font'; + +.time-list { + width: 100%; + height: 250px; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + border-top: 1px solid rgba(0, 0, 0, 0.2); + + .time-ul { + height: 244px; + display: inline-block; + overflow: hidden; + cursor: pointer; + padding: 0; + margin: 0 auto; + padding-right: 8px; + border-right: 1px solid rgba(0, 0, 0, 0.2); + scroll-behavior: smooth; + padding-top: 2px; + border-top: 1px solid rgba(0, 0, 0, 0); + + &:hover { + overflow-y: overlay; + // overflow-y:auto ; + // padding-right: 0; + } + + &:last-child { + border-right: none; + } + + li { + padding: 0; + // text-align: center; + // padding-left: 40px; + text-align: center; + height: 30px; + line-height: 30px; + width: calc(100% + 8px); + + &:last-child { + margin-bottom: 214px; + } + + &:hover { + background-color: #5d7ef80c; + color: #8aa2f0; + } + } + + .active-li { + background-color: #5e7ce0; + color: #ffffff; + + &:hover { + background-color: #5e7ce0; + color: #ffffff; + } + } + + .disabled-li { + background-color: $devui-disabled-bg; + color: $devui-disabled-text; + cursor: not-allowed; + } + } +} diff --git a/devui/time-picker/src/components/popup-line/index.tsx b/devui/time-picker/src/components/popup-line/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b617e39a186318ffc8f4c76132c3e0b3b1f60858 --- /dev/null +++ b/devui/time-picker/src/components/popup-line/index.tsx @@ -0,0 +1,135 @@ +import { ref, defineComponent } from 'vue' +import { usePopupLine } from './composables/use-popue-line' +import './index.scss' + +type ArrType = { + type: 'hour' | 'minute' | 'seconde' + isActive: boolean + isDisabled: boolean + time: string + flag: string +} + +export default defineComponent({ + name: 'TTimeList', + props: { + hourList: { + type: Array, + default: () => [] + }, + minuteList: { + type: Array, + default: () => [] + }, + secondList: { + type: Array, + default: () => [] + }, + format: { + type: String, + default: 'hh:mm:ss' + }, + minTime: { + type: String, + default: '00:00:00' + }, + maxTime: { + type: String, + default: '23:59:59' + } + }, + setup(props, ctx,) { + const timeListDom = ref() + const { + getNewTime, + activeTimeFun, + resetTimeValue + } = usePopupLine( + props.hourList as Array, + props.minuteList as Array, + props.secondList as Array, + props.minTime, + props.maxTime, + props.format, + timeListDom, + ) + + const restScrooTop = () => { + for (let i = 0; i < timeListDom.value.children.length; i++) { + timeListDom.value.children[i].scrollTop = 0 + } + } + + const setOutoTime = (time: string) => { + resetTimeValue(time) + } + + + + const TimeLi = (timeArr: Array): any => { + return ( + timeArr.map((item: ArrType, index: number) => { + return ( +
  • { activeTimeFun(e, item, index,) }} + >{item.time} +
  • + ) + }) + ) + } + + const TimeUl = (timeList: Array) => { + return ( +
      6 ? '33.33%' : '50%' }}> {TimeLi(timeList)}
    + ) + } + + const formatTimeUl = () => { + const timeList = { + 'hh': props.hourList, + 'mm': props.minuteList, + 'ss': props.secondList + } + + const timeFormatArr = (props.format as string).split(':') + + return ( + timeFormatArr.map((timeItme) => { + return ( + TimeUl(timeList[timeItme]) + ) + }) + ) + } + + //TODO: 区分浏览器内核,解决firefox中鼠标离开元素不继续滚动的情况 + const selectTimeFun = (e: MouseEvent) => { + e.stopPropagation() + console.log(e); + + // e.stopPropagation() + // const ua = navigator.userAgent + // if (ua.indexOf('Firefox') > -1) { + // resetTimeValue(activeTime) + // } + } + + ctx.expose({ + restScrooTop, setOutoTime, getNewTime + }) + + return () => { + return ( +
    + { + formatTimeUl() + } +
    + ) + } + } +}) + + diff --git a/devui/time-picker/src/components/time-popup/index.scss b/devui/time-picker/src/components/time-popup/index.scss new file mode 100644 index 0000000000000000000000000000000000000000..e8e2b6fcb4a19c18c26d7fca9b0d4f8b5b220bdc --- /dev/null +++ b/devui/time-picker/src/components/time-popup/index.scss @@ -0,0 +1,54 @@ +@import '../../../../style/theme/color'; +@import '../../../../style/theme/shadow'; +@import '../../../../style/theme/corner'; +@import '../../../../style/core/_font'; + +.time-popup { + height: 310px; + position: fixed; + z-index: -1; + background-color: #ffffff; + box-shadow: $devui-shadow-length-connected-overlay; + visibility: hidden; + opacity: 0; + transition: 0.4s; + -webkit-transition: 0.4s; + transition-property: visibility, opacity, z-index; +} + +.show-popup { + visibility: visible; + z-index: 1052; + opacity: 1; + transition-property: visibility, opacity, z-index; +} + +.popup-btn { + height: 60px; + padding: 0 10px; + display: flex; + justify-content: space-between; + align-items: center; + + .ok-btn { + width: 80px; + height: 26px; + line-height: 26px; + text-align: center; + background-color: #5e7ce0; + font-size: 14px; + color: #ffffff; + border-radius: 2px; + cursor: pointer; + } + + .slot-time { + font-size: $devui-font-size-card-title; + cursor: pointer; + } + + .slot-time:hover { + color: $devui-primary-hover; + text-decoration: underline; + } +} diff --git a/devui/time-picker/src/components/time-popup/index.tsx b/devui/time-picker/src/components/time-popup/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..304d4fd3213e4357305c468a1afa81727ef97378 --- /dev/null +++ b/devui/time-picker/src/components/time-popup/index.tsx @@ -0,0 +1,114 @@ +import { defineComponent, ref, watch, onMounted } from 'vue'; +import { initializeTimeData, setTimeAstrict } from '../../utils' +import TimeList from '../popup-line/index' +import { Button } from '../../../../button/index'; +import { ArrType } from '../../types' + +import './index.scss' +export default defineComponent({ + name: 'TTimePopup', + components: { + TimeList, Button + }, + props: { + showPopup: { + type: Boolean, + default: false + }, + popupTop: { + type: Number, + default: -100 + }, + popupLeft: { + type: Number, + default: -100 + }, + popupWidth: { + type: Number, + default: 300 + }, + popupFormat: { + type: String, + default: 'hh:mm:ss' + }, + minTime: { + type: String, + default: '00:00:00' + }, + maxTime: { + type: String, + default: '23:59:59' + }, + bindData: { + type: String, + default: '00:00:00' + } + }, + emits: ['subData'], + setup(props, ctx) { + const popupDome = ref() + const timeListDom = ref() + const hourList = initializeTimeData('hour') + const minuteList = initializeTimeData('minute') + const secondList = initializeTimeData('second') + + onMounted(() => { + setTimeAstrict(hourList, minuteList, secondList, props.minTime, props.maxTime, props.popupFormat) + }) + + watch(() => [props.showPopup, props.bindData], ([showPopup, newTimeVal], [oldPopup, oldTimeVal]) => { + + if (showPopup || newTimeVal != oldTimeVal) { + timeListDom.value.setOutoTime(newTimeVal) + } else { + timeListDom.value.restScrooTop() + } + }) + + const changTimeData = () => { + return timeListDom.value.getNewTime() + } + + const subDataFun = (e: MouseEvent) => { + e.stopPropagation() + ctx.emit('subData') + } + + ctx.expose({ + changTimeData + }) + + return () => { + return ( + <> +
    + + + +
    + + ) + } + } +}) + diff --git a/devui/time-picker/src/composables/use-popup.ts b/devui/time-picker/src/composables/use-popup.ts new file mode 100644 index 0000000000000000000000000000000000000000..74e7742e5f2d2c73c90b852c8207491558224051 --- /dev/null +++ b/devui/time-picker/src/composables/use-popup.ts @@ -0,0 +1,148 @@ +import { Ref, ref } from 'vue' +import { TimeObj } from '../types' +import { getPositionFun } from '../utils' + +export default function usePicker( + hh:Ref,mm:Ref,ss:Ref,minTime:string,format:string, + autoOpen:boolean,disabled:boolean,value:string + ):any{ + const isActive = ref(false) + const showPopup = ref(false) + const devuiTimePicker = ref() + const inputDom = ref() + const left = ref(-100) + const top = ref(-100) + const timePopupDom = ref() + const timePickerValue = ref('') + const showClearIcon = ref(false) + const firsthandActiveTime = ref(`${hh.value}:${mm.value}:${ss.value}`) + const vModeValue = ref(value) + + const getPopupPosition = ()=>{ + getPositionFun(devuiTimePicker.value,left,top) + } + + const clickVerifyFun = (e: any) => { + e.stopPropagation() + isActive.value = false + showPopup.value = false + + if(disabled) return + + const path = (e.composedPath && e.composedPath()) || e.path + path.map( item => { + if (item == devuiTimePicker.value) { + if(firsthandActiveTime.value == '00:00:00'){ + vModeValue.value == '' + ? vModeValue.value = '00:00:00' + : '' + + vModeValue.value > minTime + ? firsthandActiveTime.value = vModeValue.value + : firsthandActiveTime.value = minTime + } + setInputValue() + isActive.value = true + showPopup.value = true + } + }) + } + + const getTimeValue = (e:MouseEvent)=>{ + e.stopPropagation() + if(showPopup.value){ + hh.value = timePopupDom.value.changTimeData().activeHour.value + mm.value = timePopupDom.value.changTimeData().activeMinute.value + ss.value = timePopupDom.value.changTimeData().activeSecond.value + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` + setInputValue() + } + } + + const setInputValue = ()=> { + if(format == 'hh:mm:ss'){ + vModeValue.value = `${hh.value}:${mm.value}:${ss.value}` + }else if(format == 'mm:hh:ss'){ + vModeValue.value = `${mm.value}:${hh.value}:${ss.value}` + }else if(format == 'hh:mm'){ + vModeValue.value = `${hh.value}:${mm.value}` + }else if(format == 'mm:ss'){ + vModeValue.value = `${mm.value}:${ss.value}` + } + } + + const clearAll = (e:MouseEvent)=>{ + e.stopPropagation() + showPopup.value = false + + if(minTime != '00:00:00'){ + const minTimeArr = minTime.split(':') + hh.value = minTimeArr[0] + mm.value = minTimeArr[1] + ss.value = minTimeArr[2] + }else{ + hh.value = '00' + mm.value = '00' + ss.value = '00' + } + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` + setInputValue() + } + + const isOutOpen =()=>{ + if(autoOpen){ + + const timeArr = vModeValue.value.split(':') + hh.value = timeArr[0] + mm.value = timeArr[1] + ss.value = timeArr[2] + + firsthandActiveTime.value = vModeValue.value + setInputValue() + isActive.value = true + showPopup.value = autoOpen + } + } + + // slot -- 选择时间 + const chooseTime = (slotTime:TimeObj) => { + if (slotTime.type) { + if (slotTime.type.toLowerCase() == 'hh') { + hh.value = slotTime.time + } else if (slotTime.type.toLowerCase() == 'mm') { + mm.value = slotTime.time + } else if (slotTime.type.toLowerCase() == 'ss') { + ss.value = slotTime.time + } + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` + setInputValue() + } else { + const timeArr = slotTime.time.split(':') + hh.value = timeArr[0] + mm.value = timeArr[1] + ss.value = timeArr[2] + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` + setInputValue() + } + } + + return { + isActive, + showPopup, + devuiTimePicker, + timePickerValue, + inputDom, + timePopupDom, + left,top, + showClearIcon, + firsthandActiveTime, + vModeValue, + getPopupPosition, + setInputValue, + getTimeValue, + clickVerifyFun, + isOutOpen, + clearAll, + chooseTime + } +} \ No newline at end of file diff --git a/devui/time-picker/src/time-picker-types.ts b/devui/time-picker/src/time-picker-types.ts new file mode 100644 index 0000000000000000000000000000000000000000..ca0b56c7faf231ef32c6865be101eea3d1961bda --- /dev/null +++ b/devui/time-picker/src/time-picker-types.ts @@ -0,0 +1,40 @@ +import { ExtractPropTypes, PropType } from 'vue'; + +export const timePickerProps = { + modelValue: { + type: String, + default: '' + }, + placeholder: { + type: String, + default: '00:00:00' + }, + disabled: { + type: Boolean, + default: false + }, + timePickerWidth: { + type: Number, + default: 210 + }, + minTime: { + type: String, + default: '00:00:00' + // 默认时间优先级:minTime > modelValue + }, + maxTime: { + type: String, + default: '23:59:59' + }, + format: { + type: String, + default: 'hh:mm:ss' + }, + autoOpen: { + type: Boolean, + default: false + } +} as const; + + +export type TimePickerProps = ExtractPropTypes; diff --git a/devui/time-picker/src/time-picker.scss b/devui/time-picker/src/time-picker.scss new file mode 100644 index 0000000000000000000000000000000000000000..46cacddf7a48bfa0c89528328199fa3a5836ad8d --- /dev/null +++ b/devui/time-picker/src/time-picker.scss @@ -0,0 +1,51 @@ +@import '../../style/theme/color'; +@import '../../style/theme/shadow'; +@import '../../style/theme/corner'; +@import '../../style/core/_font'; + +.devui-time-picker { + width: 200px; + box-sizing: border-box; + display: flex; + justify-content: space-between; + align-items: center; + border: 1px solid $devui-form-control-line; + position: relative; + transition: 0.2s; + + &:hover { + border: 1px solid $devui-form-control-line-hover; + } + + .time-input { + border: none; + outline: none; + width: 100%; + } + + .time-input-icon { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + + div { + text-align: right; + padding: 0 4px; + } + } +} + +.time-picker-active { + border: 1px solid $devui-form-control-line-active !important; +} + +.picker-disabled { + background-color: $devui-unavailable; + cursor: no-drop; + + * { + background-color: $devui-unavailable; + cursor: no-drop; + } +} diff --git a/devui/time-picker/src/time-picker.tsx b/devui/time-picker/src/time-picker.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6b9e85b33e868dbee866d32344a6cd607c92a04e --- /dev/null +++ b/devui/time-picker/src/time-picker.tsx @@ -0,0 +1,119 @@ +import { defineComponent, ref, onMounted, onUnmounted, watch } from 'vue' +import { TimePickerProps, timePickerProps } from './time-picker-types' +import { Icon } from '../../icon' +import usePicker from './composables/use-popup' +import TimePopup from './components/time-popup/index' + +import './time-picker.scss' + +export default defineComponent({ + name: 'DTimepicker', + components: { TimePopup }, + props: timePickerProps, + emits: ['selectedTimeChage', 'update:modelValue'], + setup(props: TimePickerProps, ctx) { + + const activeHour = ref('00') + const activeMinute = ref('00') + const activeSecond = ref('00') + const format = props.format.toLowerCase() + + const { + isActive, + showPopup, + devuiTimePicker, + inputDom, + left, top, + showClearIcon, + firsthandActiveTime, + chooseTime, + getTimeValue, + clickVerifyFun, + isOutOpen, + clearAll, + timePopupDom, + vModeValue, + getPopupPosition + } = usePicker(activeHour, activeMinute, activeSecond, props.minTime, format, props.autoOpen, props.disabled, props.modelValue) + + + const selectedTimeChage = () => { + isActive.value = false + showPopup.value = false + ctx.emit('selectedTimeChage', vModeValue.value) + } + + onMounted(() => { + getPopupPosition() + isOutOpen() + document.addEventListener('click', clickVerifyFun) + document.addEventListener('click', getTimeValue) + document.addEventListener('scroll', getPopupPosition) + window.addEventListener('resize', getPopupPosition) + }) + onUnmounted(() => { + document.removeEventListener('click', clickVerifyFun) + document.removeEventListener('click', getTimeValue) + document.removeEventListener('scroll', getPopupPosition) + window.removeEventListener('resize', getPopupPosition) + }) + + watch(vModeValue, (newValue: string) => { + ctx.emit('update:modelValue', vModeValue.value) + if (newValue != props.minTime) { + showClearIcon.value = true + } else { + showClearIcon.value = false + } + }) + + ctx.expose({ + clearAll, chooseTime + }) + + return () => { + return ( + <> +
    + + { + ctx.slots.customViewTemplate?.() + } + + +
    +
    + { + showClearIcon.value + ? + : '' + } +
    +
    + +
    +
    +
    + + ) + } + } +}) diff --git a/devui/time-picker/src/types.ts b/devui/time-picker/src/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..2d768b39b841ed93b65e30bb25e3d49364ed4e73 --- /dev/null +++ b/devui/time-picker/src/types.ts @@ -0,0 +1,14 @@ + +export type timeType = 'hh' | 'HH' | 'mm' | 'MM' | 'ss' | 'SS'; +export type TimeObj = { + time: string + type?: timeType +} + +export type ArrType = { + type: 'hour' | 'minute' | 'seconde' + isActive: boolean + isDisabled: boolean + time: string + flag: string +} diff --git a/devui/time-picker/src/utils.ts b/devui/time-picker/src/utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..cf537497e0894750e55a9df139aadd1d8a7a94e1 --- /dev/null +++ b/devui/time-picker/src/utils.ts @@ -0,0 +1,98 @@ +import { Ref, reactive } from 'vue' +import { ArrType } from './types' + +/** + * 动态调整弹窗位置 + * @param element + * @returns { top , left } + */ +export function getPositionFun(el: Element, left: Ref, top: Ref): any { + const inputDom = el.getBoundingClientRect() + const button = window.innerHeight - (inputDom.top + 20) + if (button > inputDom.top + 20) { + left.value = inputDom.x + top.value = inputDom.top + 20 + 10 + } else { + left.value = inputDom.x + top.value = inputDom.top - 316 + } +} + +/** + * 初始化数据 + * @param type 类型( 时,分,秒 ) + * @returns Array