Initial commit of akmon project
This commit is contained in:
14
uni_modules/lime-date-time-picker/changelog.md
Normal file
14
uni_modules/lime-date-time-picker/changelog.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## 0.0.7(2025-04-24)
|
||||
- fix: 修复uniapp v2 app 报错问题
|
||||
## 0.0.6(2025-04-23)
|
||||
- feat: 兼容uniappx 鸿蒙next
|
||||
## 0.0.5(2025-04-17)
|
||||
- fix: 修复uniapp缺少导出onChange
|
||||
## 0.0.4(2025-03-25)
|
||||
- fix: 修复空字符时无法使用
|
||||
## 0.0.3(2025-01-09)
|
||||
- feat: 增加`change`事件
|
||||
## 0.0.2(2024-12-27)
|
||||
- feat: 兼容vue2
|
||||
## 0.0.1(2024-12-27)
|
||||
- init
|
||||
@@ -0,0 +1,56 @@
|
||||
// @ts-nocheck
|
||||
import { TimeModeValues } from './type';
|
||||
// 使用位运算定义模式
|
||||
// const MODES = {
|
||||
// YEAR: 1 << 0, // 1
|
||||
// MONTH: 1 << 1, // 2
|
||||
// DATE: 1 << 2, // 4
|
||||
// HOUR: 1 << 3, // 8
|
||||
// MINUTE: 1 << 4 // 16
|
||||
// SECOND : 1 << 4 // 32
|
||||
// };
|
||||
|
||||
export const MODE_YEAR = 1; // 0001
|
||||
export const MODE_MONTH = 2; // 0010
|
||||
export const MODE_DATE = 4; // 0100
|
||||
export const MODE_HOUR = 8; // 1000
|
||||
export const MODE_MINUTE = 16; // 10000
|
||||
export const MODE_SECOND = 32; // 100000
|
||||
|
||||
export const MODE_MAP = new Map<string, number>([
|
||||
['年', MODE_YEAR],
|
||||
['月', MODE_MONTH],
|
||||
['日', MODE_DATE],
|
||||
['时', MODE_HOUR],
|
||||
['分', MODE_MINUTE],
|
||||
['秒', MODE_SECOND],
|
||||
['year', MODE_YEAR],
|
||||
['month', MODE_MONTH],
|
||||
['date', MODE_DATE],
|
||||
['hour', MODE_HOUR],
|
||||
['minute', MODE_MINUTE],
|
||||
['second', MODE_SECOND],
|
||||
])
|
||||
|
||||
export const FORMAT_MAP = new Map<string, string>([
|
||||
['year', 'YYYY'],
|
||||
['month', 'MM'],
|
||||
['date', 'DD'],
|
||||
['hour', 'HH'],
|
||||
['minute', 'mm'],
|
||||
['second', 'ss'],
|
||||
])
|
||||
|
||||
export const UNIT_MAP = new Map<string, string>([
|
||||
['year', '年'],
|
||||
['month', '月'],
|
||||
['date', '日'],
|
||||
['hour', '时'],
|
||||
['minute', '分'],
|
||||
['second', '秒'],
|
||||
])
|
||||
|
||||
|
||||
// 定义时间列名称数组
|
||||
export const MODE_NAMES : TimeModeValues[] = ['year', 'month', 'date', 'hour', 'minute', 'second'];
|
||||
export const DEFAULT_FORMAT = 'YYYY-MM-DD HH:mm:ss'
|
||||
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<l-picker
|
||||
:title="title"
|
||||
:titleStyle="titleStyle"
|
||||
:confirm-btn="confirmBtn"
|
||||
:confirm-style="confirmStyle"
|
||||
:cancel-btn="cancelBtn"
|
||||
:cancel-style="cancelStyle"
|
||||
:itemHeight="itemHeight"
|
||||
:itemColor="itemColor"
|
||||
:itemFontSize="itemFontSize"
|
||||
:itemActiveColor="itemActiveColor"
|
||||
:indicatorStyle="indicatorStyle"
|
||||
:bgColor="bgColor"
|
||||
:groupHeight="groupHeight"
|
||||
:radius="radius"
|
||||
:value="valueOfPicker"
|
||||
:columns="columns"
|
||||
@confirm="onConfirm"
|
||||
@cancel="onCancel"
|
||||
@change="onChange"
|
||||
@pick="onPick">
|
||||
</l-picker>
|
||||
</template>
|
||||
<script lang="uts" setup>
|
||||
import { DateTimePickerProps, DateValue, DateTimePickerColumn, TimeModeValues, DateTimePickerColumnItem } from './type';
|
||||
import { PickerColumn, PickerColumnItem, PickerConfirmEvent, PickerPickEvent, PickerValue } from '@/uni_modules/lime-picker';
|
||||
import { getMeaningColumn } from './utils';
|
||||
import { DEFAULT_FORMAT, MODE_NAMES, FORMAT_MAP, UNIT_MAP } from './constant';
|
||||
import { dayuts, Dayuts } from '@/uni_modules/lime-dayuts/common'
|
||||
import { DayutsUnit } from '@/uni_modules/lime-dayuts'
|
||||
import { clamp } from '@/uni_modules/lime-shared/clamp'
|
||||
|
||||
const emit = defineEmits(['change', 'cancel', 'confirm', 'pick', 'update:modelValue', 'update:value'])
|
||||
const props = withDefaults(defineProps<DateTimePickerProps>(), {
|
||||
mode: 1 | 2 | 4,
|
||||
format: DEFAULT_FORMAT,
|
||||
showUnit: true,
|
||||
resetIndex: false,
|
||||
minHour: 0,
|
||||
maxHour: 23,
|
||||
minMinute: 0,
|
||||
maxMinute: 59
|
||||
})
|
||||
// 默认值
|
||||
let defaultValue : DateValue = props.value ?? props.defaultValue ?? props.defaultValue ?? Date.now()
|
||||
const innerValue = computed({
|
||||
set(value : DateValue) {
|
||||
if(defaultValue == value) return
|
||||
defaultValue = value;
|
||||
emit('change', value)
|
||||
emit('update:modelValue', value)
|
||||
emit('update:value', value)
|
||||
},
|
||||
get() : DateValue {
|
||||
const value = props.value ?? props.modelValue ?? defaultValue
|
||||
return typeof value == 'string' && (value as string).length == 0 ? Date.now() : value
|
||||
}
|
||||
} as WritableComputedOptions<DateValue>)
|
||||
|
||||
|
||||
const meaningColumn = getMeaningColumn(props.mode);
|
||||
const isTimeMode = ['hour', 'minute', 'second'].includes(meaningColumn[0]);
|
||||
const normalize = (val : DateValue | null, defaultDay : Dayuts) : Dayuts => val != null && dayuts(val).isValid() ? dayuts(val) : defaultDay;
|
||||
const start = computed(() : Dayuts => normalize(props.start as DateValue | null, dayuts().subtract(10, 'year')));
|
||||
const end = computed(() : Dayuts => normalize(props.end as DateValue | null, dayuts().add(10, 'year')));
|
||||
const rationalize = (val : Dayuts) : Dayuts => {
|
||||
if (isTimeMode) return val;
|
||||
if (val.isBefore(start.value)) return start.value;
|
||||
if (val.isAfter(end.value)) return end.value;
|
||||
return val;
|
||||
};
|
||||
|
||||
const calcDate = (currentValue : DateValue | null) : Dayuts => {
|
||||
if (isTimeMode) {
|
||||
const dateStr = dayuts(start.value).format('YYYY-MM-DD');
|
||||
currentValue = `${dateStr} ${currentValue}`;
|
||||
}
|
||||
return currentValue != null && dayuts(currentValue).isValid() ? rationalize(dayuts(currentValue)) : start.value;
|
||||
};
|
||||
|
||||
const curDate = ref(calcDate(innerValue.value));
|
||||
const valueOfPicker = computed(() : string[] => meaningColumn.map((item) : string => curDate.value.get(item).toString()));
|
||||
const columnCache = new Map<string, DateTimePickerColumnItem[]>();
|
||||
const columns = computed(() : DateTimePickerColumn[] => {
|
||||
const ret : DateTimePickerColumn[] = [];
|
||||
|
||||
const getDate = (date : Dayuts) : number[] => [
|
||||
date.year(),
|
||||
date.month() + 1,
|
||||
date.date(),
|
||||
date.hour(),
|
||||
date.minute(),
|
||||
date.second(),
|
||||
];
|
||||
//@ts-ignore
|
||||
const [curYear, curMonth, curDay, curHour, curMinute] = getDate(curDate.value);
|
||||
const [minYear, minMonth, minDay, minHour, minMinute, minSecond] = getDate(start.value);
|
||||
const [maxYear, maxMonth, maxDay, maxHour, maxMinute, maxSecond] = getDate(end.value);
|
||||
|
||||
const isInMinYear = curYear == minYear;
|
||||
const isInMaxYear = curYear == maxYear;
|
||||
const isInMinMonth = isInMinYear && curMonth == minMonth;
|
||||
const isInMaxMonth = isInMaxYear && curMonth === maxMonth;
|
||||
const isInMinDay = isInMinMonth && curDay == minDay;
|
||||
const isInMaxDay = isInMaxMonth && curDay == maxDay;
|
||||
const isInMinHour = isInMinDay && curHour == minHour;
|
||||
const isInMaxHour = isInMaxDay && curHour == maxHour;
|
||||
const isInMinMinute = isInMinHour && curMinute == minMinute;
|
||||
const isInMaxMinute = isInMaxHour && curMinute == maxMinute;
|
||||
|
||||
const generateColumn = (type : string, lowerBound : number, upperBound : number) => {
|
||||
const cacheKey = `${type}-${lowerBound}-${upperBound}`;
|
||||
if (columnCache.has(cacheKey)) {
|
||||
ret.push(columnCache.get(cacheKey)!)
|
||||
return
|
||||
}
|
||||
|
||||
const arr : DateTimePickerColumnItem[] = [];
|
||||
for (let i = lowerBound; i <= upperBound; i++) {
|
||||
const value = i;
|
||||
arr.push({
|
||||
label: props.renderLabel != null ? props.renderLabel!(type, i.toString()) : `${value}${props.showUnit ? UNIT_MAP.get(type) : ''}`,
|
||||
value: type == 'month' ? `${value - 1}` : value.toString(),
|
||||
} as DateTimePickerColumnItem);
|
||||
}
|
||||
|
||||
if (props.customFilter != null) {
|
||||
const _arr = props.customFilter!(type, arr)
|
||||
ret.push(_arr)
|
||||
columnCache.set(cacheKey, _arr);
|
||||
} else {
|
||||
ret.push(arr)
|
||||
columnCache.set(cacheKey, arr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (meaningColumn.includes('year')) {
|
||||
generateColumn('year', minYear, maxYear);
|
||||
}
|
||||
if (meaningColumn.includes('month')) {
|
||||
const lower = isInMinYear ? minMonth : 1;
|
||||
const upper = isInMaxYear ? maxMonth : 12;
|
||||
generateColumn('month', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('date')) {
|
||||
const lower = isInMinMonth ? minDay : 1;
|
||||
const upper = isInMaxMonth ? maxDay : dayuts(`${curYear}-${curMonth}`).daysInMonth();
|
||||
generateColumn('date', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('hour')) {
|
||||
const lower = isInMinDay && !isTimeMode ? minHour : clamp(props.minHour, 0, 23);// 0;
|
||||
const upper = isInMaxDay && !isTimeMode ? maxHour : clamp(props.maxHour, lower, 23);//23;
|
||||
generateColumn('hour', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('minute')) {
|
||||
const lower = isInMinHour && !isTimeMode ? minMinute : clamp(props.minMinute, 0, 59);//0;
|
||||
const upper = isInMaxHour && !isTimeMode ? maxMinute : clamp(props.maxMinute, lower, 59);//59;
|
||||
generateColumn('minute', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('second')) {
|
||||
const lower = isInMinMinute && !isTimeMode ? minSecond : 0;
|
||||
const upper = isInMaxMinute && !isTimeMode ? maxSecond : 59;
|
||||
generateColumn('second', lower, upper);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
|
||||
const innterFormat = computed(() : string => {
|
||||
const first = meaningColumn.length > 0 ? meaningColumn[0] : 'year';
|
||||
const last = meaningColumn.length > 0 ? meaningColumn[meaningColumn.length - 1] : 'date';
|
||||
|
||||
const format = DEFAULT_FORMAT.substring(
|
||||
DEFAULT_FORMAT.indexOf(FORMAT_MAP.get(first)!),
|
||||
DEFAULT_FORMAT.lastIndexOf(FORMAT_MAP.get(last)!) + FORMAT_MAP.get(last)!.length
|
||||
)
|
||||
return format
|
||||
})
|
||||
const onConfirm = ({ values } : PickerConfirmEvent) => {
|
||||
|
||||
// const first = meaningColumn.length > 0 ? meaningColumn[0]: 'year';
|
||||
// const last = meaningColumn.length > 0 ? meaningColumn[meaningColumn.length - 1]: 'date';
|
||||
|
||||
// const format = DEFAULT_FORMAT.substring(
|
||||
// DEFAULT_FORMAT.indexOf(FORMAT_MAP.get(first)!),
|
||||
// DEFAULT_FORMAT.lastIndexOf(FORMAT_MAP.get(last)!) + FORMAT_MAP.get(last)!.length
|
||||
// )
|
||||
|
||||
let cur = curDate.value
|
||||
// MODE_NAMES
|
||||
values.forEach((item, index) => {
|
||||
const type = meaningColumn[index]
|
||||
cur = cur.set(type, parseInt(`${item}`, 10))
|
||||
})
|
||||
const curValue = cur.format(props.format)
|
||||
|
||||
innerValue.value = cur.format(innterFormat.value);
|
||||
emit('confirm', curValue);
|
||||
}
|
||||
const onCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
const onPick = ({ values, column, index } : PickerPickEvent) => {
|
||||
const type = meaningColumn[column];
|
||||
const val = curDate.value.set(type as DayutsUnit, parseInt(columns.value[column][index].value, 10));
|
||||
|
||||
curDate.value = rationalize(val);
|
||||
emit('pick', rationalize(val).format(props.format))
|
||||
}
|
||||
|
||||
const onChange = (values : PickerValue[]) => {
|
||||
let cur = curDate.value
|
||||
values.forEach((item, index) => {
|
||||
const type = meaningColumn[index]
|
||||
cur = cur.set(type, parseInt(`${item}`, 10))
|
||||
})
|
||||
curDate.value = rationalize(cur as Dayuts)
|
||||
const curValue = curDate.value.format(innterFormat.value)
|
||||
innerValue.value = curValue
|
||||
}
|
||||
const stop = watch(innerValue, (val : DateValue) => {
|
||||
curDate.value = calcDate(val);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stop()
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<l-picker
|
||||
:title="title"
|
||||
:titleStyle="titleStyle"
|
||||
:confirm-btn="confirmBtn"
|
||||
:confirm-style="confirmStyle"
|
||||
:cancel-btn="cancelBtn"
|
||||
:cancel-style="cancelStyle"
|
||||
:itemHeight="itemHeight"
|
||||
:itemColor="itemColor"
|
||||
:itemFontSize="itemFontSize"
|
||||
:itemActiveColor="itemActiveColor"
|
||||
:indicatorStyle="indicatorStyle"
|
||||
:bgColor="bgColor"
|
||||
:groupHeight="groupHeight"
|
||||
:radius="radius"
|
||||
:value="valueOfPicker"
|
||||
:columns="columns"
|
||||
@confirm="onConfirm"
|
||||
@cancel="onCancel"
|
||||
@change="onChange"
|
||||
@pick="onPick">
|
||||
</l-picker>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
import { defineComponent, computed, ref, watch, onBeforeUnmount} from '@/uni_modules/lime-shared/vue';
|
||||
import { DateTimePickerProps, DateValue, DateTimePickerColumn, TimeModeValues, DateTimePickerColumnItem } from './type';
|
||||
import { PickerColumn, PickerColumnItem, PickerConfirmEvent, PickerPickEvent } from '@/uni_modules/lime-picker';
|
||||
import { getMeaningColumn } from './utils';
|
||||
import { DEFAULT_FORMAT, MODE_NAMES, FORMAT_MAP, UNIT_MAP } from './constant';
|
||||
import { dayuts, Dayuts, DayutsUnit} from '@/uni_modules/lime-dayuts'
|
||||
import { clamp } from '@/uni_modules/lime-shared/clamp'
|
||||
import dataTimePickerProps from './props';
|
||||
export default defineComponent({
|
||||
name: 'l-date-time-picker',
|
||||
props: dataTimePickerProps,
|
||||
emits: ['change', 'cancel', 'confirm', 'pick', 'update:modelValue', 'update:value','input'],
|
||||
setup(props, {emit}) {
|
||||
// 默认值
|
||||
let defaultValue : DateValue = props.value ?? props.defaultValue ?? props.defaultValue ?? Date.now()
|
||||
const innerValue = computed({
|
||||
set(value : DateValue) {
|
||||
if(defaultValue == value) return
|
||||
defaultValue = value;
|
||||
emit('change', value)
|
||||
emit('update:modelValue', value)
|
||||
emit('update:value', value)
|
||||
// #ifdef VUE2
|
||||
emit('input', value)
|
||||
// #endif
|
||||
},
|
||||
get() : DateValue {
|
||||
const value = props.value ?? props.modelValue ?? defaultValue
|
||||
return typeof value == 'string' && value.length == 0 ? Date.now() : value
|
||||
// return props.value ?? props.modelValue ?? defaultValue
|
||||
}
|
||||
} as WritableComputedOptions<DateValue>)
|
||||
|
||||
const meaningColumn = getMeaningColumn(props.mode);
|
||||
const isTimeMode = ['hour', 'minute', 'second'].includes(meaningColumn[0]);
|
||||
const normalize = (val : DateValue | null, defaultDay : Dayuts) : Dayuts => val != null && dayuts(val).isValid() ? dayuts(val) : defaultDay;
|
||||
const start = computed(() : Dayuts => normalize(props.start as DateValue | null, dayuts().subtract(10, 'year')));
|
||||
const end = computed(() : Dayuts => normalize(props.end as DateValue | null, dayuts().add(10, 'year')));
|
||||
const rationalize = (val : Dayuts) : Dayuts => {
|
||||
if (isTimeMode) return val;
|
||||
if (val.isBefore(start.value)) return start.value;
|
||||
if (val.isAfter(end.value)) return end.value;
|
||||
return val;
|
||||
};
|
||||
const calcDate = (currentValue : DateValue | null) : Dayuts => {
|
||||
if (isTimeMode) {
|
||||
const dateStr = dayuts(start.value).format('YYYY-MM-DD');
|
||||
currentValue = `${dateStr} ${currentValue}`;
|
||||
}
|
||||
return currentValue != null && dayuts(currentValue).isValid() ? rationalize(dayuts(currentValue)) : start.value;
|
||||
};
|
||||
|
||||
const curDate = ref(calcDate(innerValue.value));
|
||||
const valueOfPicker = computed(() : string[] => meaningColumn.map((item) : string => curDate.value.get(item).toString()));
|
||||
const columnCache = new Map<string, DateTimePickerColumnItem[]>();
|
||||
const columns = computed(() : DateTimePickerColumn[] => {
|
||||
const ret : DateTimePickerColumn[] = [];
|
||||
|
||||
const getDate = (date : Dayuts) : number[] => [
|
||||
date.year(),
|
||||
date.month() + 1,
|
||||
date.date(),
|
||||
date.hour(),
|
||||
date.minute(),
|
||||
date.second(),
|
||||
];
|
||||
const [curYear, curMonth, curDay, curHour, curMinute] = getDate(curDate.value);
|
||||
const [minYear, minMonth, minDay, minHour, minMinute, minSecond] = getDate(start.value);
|
||||
const [maxYear, maxMonth, maxDay, maxHour, maxMinute, maxSecond] = getDate(end.value);
|
||||
|
||||
const isInMinYear = curYear == minYear;
|
||||
const isInMaxYear = curYear == maxYear;
|
||||
const isInMinMonth = isInMinYear && curMonth == minMonth;
|
||||
const isInMaxMonth = isInMaxYear && curMonth === maxMonth;
|
||||
const isInMinDay = isInMinMonth && curDay == minDay;
|
||||
const isInMaxDay = isInMaxMonth && curDay == maxDay;
|
||||
const isInMinHour = isInMinDay && curHour == minHour;
|
||||
const isInMaxHour = isInMaxDay && curHour == maxHour;
|
||||
const isInMinMinute = isInMinHour && curMinute == minMinute;
|
||||
const isInMaxMinute = isInMaxHour && curMinute == maxMinute;
|
||||
|
||||
const generateColumn = (type: string, lowerBound: number, upperBound: number) => {
|
||||
const cacheKey = `${type}-${lowerBound}-${upperBound}`;
|
||||
if (columnCache.has(cacheKey)) {
|
||||
ret.push(columnCache.get(cacheKey)!)
|
||||
return
|
||||
}
|
||||
|
||||
const arr: DateTimePickerColumnItem[] = [];
|
||||
for (let i = lowerBound; i <= upperBound; i++) {
|
||||
const value = i;
|
||||
arr.push({
|
||||
label: props.renderLabel !=null ? props.renderLabel!(type, i) : `${value}${props.showUnit ? UNIT_MAP.get(type) : ''}`,
|
||||
value: type == 'month' ? `${value - 1}` : value.toString(),
|
||||
} as DateTimePickerColumnItem);
|
||||
}
|
||||
|
||||
if(props.customFilter != null) {
|
||||
const _arr = props.customFilter!(type, arr)
|
||||
ret.push(_arr)
|
||||
columnCache.set(cacheKey, _arr);
|
||||
} else {
|
||||
ret.push(arr)
|
||||
columnCache.set(cacheKey, arr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (meaningColumn.includes('year')) {
|
||||
generateColumn('year', minYear, maxYear);
|
||||
}
|
||||
if (meaningColumn.includes('month')) {
|
||||
const lower = isInMinYear ? minMonth : 1;
|
||||
const upper = isInMaxYear ? maxMonth : 12;
|
||||
generateColumn('month', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('date')) {
|
||||
const lower = isInMinMonth ? minDay : 1;
|
||||
const upper = isInMaxMonth ? maxDay : dayuts(`${curYear}-${curMonth}`).daysInMonth();
|
||||
generateColumn('date', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('hour')) {
|
||||
const lower = isInMinDay && !isTimeMode ? minHour : clamp(props.minHour, 0, 23);// 0;
|
||||
const upper = isInMaxDay && !isTimeMode ? maxHour : clamp(props.maxHour, lower, 23);//23;
|
||||
generateColumn('hour', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('minute')) {
|
||||
const lower = isInMinHour && !isTimeMode ? minMinute : clamp(props.minMinute, 0, 59);//0;
|
||||
const upper = isInMaxHour && !isTimeMode ? maxMinute : clamp(props.maxMinute, lower, 59);//59;
|
||||
generateColumn('minute', lower, upper);
|
||||
}
|
||||
if (meaningColumn.includes('second')) {
|
||||
const lower = isInMinMinute && !isTimeMode ? minSecond : 0;
|
||||
const upper = isInMaxMinute && !isTimeMode ? maxSecond : 59;
|
||||
generateColumn('second', lower, upper);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
|
||||
const innterFormat = computed(() : string => {
|
||||
const first = meaningColumn.length > 0 ? meaningColumn[0] : 'year';
|
||||
const last = meaningColumn.length > 0 ? meaningColumn[meaningColumn.length - 1] : 'date';
|
||||
|
||||
const format = DEFAULT_FORMAT.substring(
|
||||
DEFAULT_FORMAT.indexOf(FORMAT_MAP.get(first)!),
|
||||
DEFAULT_FORMAT.lastIndexOf(FORMAT_MAP.get(last)!) + FORMAT_MAP.get(last)!.length
|
||||
)
|
||||
return format
|
||||
})
|
||||
const onConfirm = ({ values } : PickerConfirmEvent) => {
|
||||
|
||||
// const first = meaningColumn.length > 0 ? meaningColumn[0]: 'year';
|
||||
// const last = meaningColumn.length > 0 ? meaningColumn[meaningColumn.length - 1]: 'date';
|
||||
|
||||
// const format = DEFAULT_FORMAT.substring(
|
||||
// DEFAULT_FORMAT.indexOf(FORMAT_MAP.get(first)!),
|
||||
// DEFAULT_FORMAT.lastIndexOf(FORMAT_MAP.get(last)!) + FORMAT_MAP.get(last)!.length
|
||||
// )
|
||||
|
||||
let cur = curDate.value
|
||||
// MODE_NAMES
|
||||
values.forEach((item, index) => {
|
||||
const type = meaningColumn[index]
|
||||
cur = cur.set(type, parseInt(`${item}`, 10))
|
||||
})
|
||||
const curValue = cur.format(props.format)
|
||||
|
||||
innerValue.value = cur.format(innterFormat.value);
|
||||
emit('confirm', curValue);
|
||||
}
|
||||
const onCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
const onPick = ({ values, column, index } : PickerPickEvent) => {
|
||||
const type = meaningColumn[column];
|
||||
const val = curDate.value.set(type as DayutsUnit, parseInt(columns.value[column][index].value, 10));
|
||||
|
||||
curDate.value = rationalize(val);
|
||||
emit('pick', rationalize(val).format(props.format))
|
||||
}
|
||||
const onChange = (values: PickerValue[]) => {
|
||||
let cur = curDate.value
|
||||
values.forEach((item, index) => {
|
||||
const type = meaningColumn[index]
|
||||
cur = cur.set(type, parseInt(`${item}`, 10))
|
||||
})
|
||||
curDate.value = rationalize(cur as Dayuts)
|
||||
const curValue = curDate.value.format(innterFormat.value)
|
||||
innerValue.value = curValue
|
||||
|
||||
}
|
||||
const stop = watch(innerValue, (val : DateValue) => {
|
||||
curDate.value = calcDate(val);
|
||||
});
|
||||
|
||||
onBeforeUnmount(()=>{
|
||||
stop()
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
valueOfPicker,
|
||||
columns,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
onChange,
|
||||
onPick
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,133 @@
|
||||
// @ts-nocheck
|
||||
export default {
|
||||
/** 取消按钮文字 */
|
||||
cancelBtn: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
cancelStyle: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
/** 确定按钮文字 */
|
||||
confirmBtn: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
confirmStyle: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
/** 组件国际化语言,目前支持: 简体中文(zh)、(tc)、英文(en)、日语(ja)、韩语(ko)、俄语(ru)等六种语言 */
|
||||
customLocale: {
|
||||
type: String,
|
||||
default: 'zh',
|
||||
},
|
||||
/** 选择器的最大可选时间,默认为当前时间+10年 */
|
||||
end: {
|
||||
type: [String, Number],
|
||||
default: null,
|
||||
},
|
||||
/** 列选项过滤函数,支持自定义列内容。(type 值可为: year, month, date, hour, minute, second) */
|
||||
customFilter: {
|
||||
type: Function,
|
||||
},
|
||||
/** 用于格式化 pick、change、confirm 事件返回的值,[详细文档](https://day.js.org/docs/en/display/format) */
|
||||
format: {
|
||||
type: String,
|
||||
default: 'YYYY-MM-DD HH:mm:ss',
|
||||
},
|
||||
/**1 = year = 年;2 = month = 月;4 = date = 日;8 = hour = 时; 16 = minute = 分; 32 = second = 秒 */
|
||||
mode: {
|
||||
type: [String, Number],
|
||||
default: 1|2|4,
|
||||
},
|
||||
/** 选择器的最小可选时间,默认为当前时间-10年 */
|
||||
start: {
|
||||
type: [String, Number],
|
||||
default: null,
|
||||
},
|
||||
/** 时间间隔步数,示例:`{ minute: 5 }` */
|
||||
steps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
titleStyle: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
/** 选中值 */
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: null,
|
||||
},
|
||||
/** 选中值,非受控属性 */
|
||||
defaultValue: {
|
||||
type: [String, Number],
|
||||
default: null,
|
||||
},
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
itemHeight: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
itemColor: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
itemFontSize: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
itemActiveColor: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
|
||||
indicatorStyle: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
bgColor:{
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
groupHeight:{
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
radius:{
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
showUnit: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
resetIndex: {
|
||||
type: Boolean
|
||||
},
|
||||
minHour: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
maxHour: {
|
||||
type: Number,
|
||||
default: 23
|
||||
},
|
||||
minMinute: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
maxMinute: {
|
||||
type: Number,
|
||||
default: 59
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// @ts-nocheck
|
||||
import { PickerColumn, PickerColumnItem, PickerConfirmEvent, PickerPickEvent } from '@/uni_modules/lime-picker';
|
||||
export type TimeModeValues = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second';
|
||||
export type DateValue = any;//string | number;
|
||||
export type DateTimePickerColumn = PickerColumn//DateTimePickerColumnItem[];
|
||||
|
||||
export type DateTimePickerColumnItem = PickerColumnItem;
|
||||
|
||||
export interface DateTimePickerProps {
|
||||
/** 取消按钮文字 */
|
||||
cancelBtn?: string;
|
||||
cancelStyle ?: string;
|
||||
/** 确定按钮文字 */
|
||||
confirmBtn?: string;
|
||||
confirmStyle ?: string;
|
||||
/** 组件国际化语言,目前支持: 简体中文(zh)、(tc)、英文(en)、日语(ja)、朝鲜语(ko)、俄语(ru)等六种语言 */
|
||||
customLocale?: 'zh' | 'tc' | 'en' | 'ja' | 'ko' | 'ru';
|
||||
/** 选择器的最大可选时间,默认为当前时间+10年 */
|
||||
end?: DateValue;//string;
|
||||
/** 选择器的最小可选时间,默认为当前时间-10年 */
|
||||
start?: DateValue; //string;
|
||||
/** 时间间隔步数,示例:`{ minute: 5 }` */
|
||||
steps?: UTSJSONObject
|
||||
/** 标题 */
|
||||
title?: string;
|
||||
titleStyle ?: string;
|
||||
/** 选中值 */
|
||||
value?: DateValue;
|
||||
defaultValue?: DateValue;
|
||||
modelValue?: DateValue;
|
||||
/* 用于格式化 pick、change、confirm 事件返回的值,[详细文档](https://day.js.org/docs/en/display/format)
|
||||
*/
|
||||
format: string;
|
||||
/**
|
||||
* 时间选择器的显示模式,可以是单个模式或多个模式的组合。
|
||||
* 使用位运算符来组合多个模式。
|
||||
*
|
||||
* 例如:
|
||||
* - 单个模式:1
|
||||
* - 多个模式组合:4 | 8
|
||||
* - 1 -> 年 | 2 -> 月 | 4 -> 日 | 8 -> 时 | 16 -> 分 | 32 -> 秒
|
||||
*/
|
||||
mode: any//number
|
||||
customFilter?: ((type: TimeModeValues, columns: DateTimePickerColumn) => DateTimePickerColumn);
|
||||
/**
|
||||
* 自定义label
|
||||
*/
|
||||
renderLabel?: ((type: string, value: string) => string);
|
||||
showUnit: boolean;
|
||||
|
||||
itemHeight?: string;
|
||||
itemColor?: string;
|
||||
itemFontSize?: string;
|
||||
itemActiveColor?: string;
|
||||
|
||||
indicatorStyle?: string;
|
||||
bgColor?:string;
|
||||
groupHeight?:string;
|
||||
radius?:string;
|
||||
resetIndex: boolean
|
||||
|
||||
minHour:number;
|
||||
maxHour:number;
|
||||
minMinute:number;
|
||||
maxMinute:number;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// @ts-nocheck
|
||||
import { TimeModeValues } from './type';
|
||||
import { MODE_NAMES, MODE_MAP, MODE_YEAR, MODE_MONTH, MODE_DATE, MODE_HOUR, MODE_MINUTE, MODE_SECOND } from './constant'
|
||||
|
||||
|
||||
/**
|
||||
* 根据给定的模式返回具有意义的时间列数组。
|
||||
* @param {number} mode - 表示时间模式的位掩码。
|
||||
* @returns {TimeModeValues[]} - 返回具有意义的时间列名称数组。
|
||||
*/
|
||||
export function getMeaningColumn(mode : any) : TimeModeValues[] {
|
||||
// 初始化结果数组
|
||||
const res : TimeModeValues[] = [];
|
||||
|
||||
let _mode:number = 0;
|
||||
if(typeof mode == 'string') {
|
||||
MODE_MAP.forEach((value, key) => {
|
||||
if((mode as string).includes(key)) {
|
||||
_mode = _mode | value;
|
||||
}
|
||||
})
|
||||
} else if(typeof mode == 'number') {
|
||||
_mode = mode as number
|
||||
}
|
||||
|
||||
if(_mode <= 0) {
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
// 定义对应的位掩码数组
|
||||
const modeBitmasks = [MODE_YEAR, MODE_MONTH, MODE_DATE, MODE_HOUR, MODE_MINUTE, MODE_SECOND];
|
||||
|
||||
// 查找被设置的位掩码
|
||||
const activeBitmasks = modeBitmasks.filter(bitmask => (_mode & bitmask) != 0);
|
||||
|
||||
// 如果没有位掩码被设置,返回空数组
|
||||
if (activeBitmasks.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 初始化最长连续子序列和当前连续子序列
|
||||
let longestSequence : number[] = [];
|
||||
let currentSequence : number[] = [];
|
||||
|
||||
// 遍历所有被设置的位掩码
|
||||
activeBitmasks.forEach(bitmask => {
|
||||
// 如果当前序列为空或当前位掩码是前一个位掩码的两倍,则将其加入当前序列
|
||||
if (currentSequence.length == 0 || bitmask == currentSequence[currentSequence.length - 1] * 2) {
|
||||
currentSequence.push(bitmask);
|
||||
} else {
|
||||
// 如果当前序列长度大于最长序列长度,则更新最长序列
|
||||
if (currentSequence.length > longestSequence.length) {
|
||||
longestSequence = currentSequence;
|
||||
}
|
||||
// 开始新的序列
|
||||
currentSequence = [bitmask];
|
||||
}
|
||||
});
|
||||
|
||||
// 检查最后一个序列是否是最长的
|
||||
if (currentSequence.length > longestSequence.length) {
|
||||
longestSequence = currentSequence;
|
||||
}
|
||||
|
||||
// 将最长连续子序列的位掩码转换为对应的模式名并返回
|
||||
return longestSequence.map(bitmask => MODE_NAMES[modeBitmasks.indexOf(bitmask)]);
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<view class="demo-block">
|
||||
<text class="demo-block__title-text ultra">DateTimePicker 时间选择器</text>
|
||||
<text class="demo-block__desc-text">用于选择时间,支持日期、时分等时间维度。</text>
|
||||
<view class="demo-block__body">
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">基础用法</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">年月</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择日期" :mode="1|2"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">时分秒</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择时间" :mode="8|16|32"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">完整的时间</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择日期" :mode="1|2|4|8|16|32"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">自定义范围{{value}}</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
v-model="value"
|
||||
:mode="1|2|4"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">自定义label</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
:mode="1|2|4"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:renderLabel="renderLabel"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">过滤项</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
:mode="1|2|4"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:customFilter="filter"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
import { DateTimePickerColumnItem, DateTimePickerColumn, TimeModeValues } from '@/uni_modules/lime-date-time-picker'
|
||||
|
||||
const value = ref('2024-05-02')
|
||||
|
||||
|
||||
const onConfirm = (value: string) => {
|
||||
console.log('onConfirm', value)
|
||||
}
|
||||
const onChange = (value: string) => {
|
||||
console.log('onChange', value)
|
||||
}
|
||||
const renderLabel = (type: TimeModeValues, value: string): string => {
|
||||
if(type == 'year') {
|
||||
return `${value}年`
|
||||
}
|
||||
return value
|
||||
}
|
||||
const filter = (type: TimeModeValues, columns: DateTimePickerColumn):DateTimePickerColumn => {
|
||||
if (type == 'month') {
|
||||
return columns.filter((option) => parseInt(option.value) % 6 == 0);
|
||||
}
|
||||
return columns
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.btn {
|
||||
margin-bottom: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.demo-block {
|
||||
margin: 32px 0 0;
|
||||
|
||||
// overflow: visible;
|
||||
&.card {
|
||||
// background-color: white;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
margin-top: 8px;
|
||||
|
||||
&-text {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
display: flex;
|
||||
margin-left: 5px;
|
||||
|
||||
&.large {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
line-height: 26px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
&.ultra {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 32px;
|
||||
padding-left: 15px ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__desc-text {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
margin: 8px 16px 0 0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
&__body {
|
||||
margin: 16px 0;
|
||||
overflow: visible;
|
||||
|
||||
.demo-block {
|
||||
// margin-top: 0px;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<view class="demo-block">
|
||||
<text class="demo-block__title-text ultra">DateTimePicker 时间选择器</text>
|
||||
<text class="demo-block__desc-text">用于选择时间,支持日期、时分等时间维度</text>
|
||||
<view class="demo-block__body">
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">基础用法</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">年月 1|2 </text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择日期" :mode="3"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">时分秒 8|16|32</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择时间" :mode="56"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">完整的时间 1|2|4|8|16|32</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker confirm-btn="确认" cancel-btn="取消" title="选择日期" :mode="63"></l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">自定义范围{{value}}</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
v-model="value"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
@confirm="onConfirm"
|
||||
@pick="onPick">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">自定义label</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:renderLabel="renderLabel"
|
||||
@confirm="onConfirm"
|
||||
@pick="onPick">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="demo-block card">
|
||||
<text class="demo-block__title-text">过滤项</text>
|
||||
<view class="demo-block__body">
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:customFilter="filter"
|
||||
@confirm="onConfirm"
|
||||
@pick="onPick">
|
||||
</l-date-time-picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: '2024-05-02'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onConfirm(value) {
|
||||
console.log('onConfirm', value)
|
||||
},
|
||||
onPick(value) {
|
||||
console.log('onPick', value)
|
||||
},
|
||||
renderLabel(type, value) {
|
||||
if(type == 'year') {
|
||||
return `${value}年`
|
||||
}
|
||||
return value
|
||||
},
|
||||
filter(type, columns) {
|
||||
if (type == 'month') {
|
||||
return columns.filter((option) => parseInt(option.value) % 6 == 0);
|
||||
}
|
||||
return columns
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.btn {
|
||||
margin-bottom: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.demo-block {
|
||||
margin: 32px 0 0;
|
||||
|
||||
// overflow: visible;
|
||||
&.card {
|
||||
// background-color: white;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
margin-top: 8px;
|
||||
|
||||
&-text {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
display: flex;
|
||||
margin-left: 5px;
|
||||
|
||||
&.large {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
line-height: 26px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
&.ultra {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 32px;
|
||||
padding-left: 15px ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__desc-text {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
margin: 8px 16px 0 0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
&__body {
|
||||
margin: 16px 0;
|
||||
overflow: visible;
|
||||
|
||||
.demo-block {
|
||||
// margin-top: 0px;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
2
uni_modules/lime-date-time-picker/index.ts
Normal file
2
uni_modules/lime-date-time-picker/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// @ts-nocheck
|
||||
export * from './components/l-date-time-picker/type'
|
||||
91
uni_modules/lime-date-time-picker/package.json
Normal file
91
uni_modules/lime-date-time-picker/package.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"id": "lime-date-time-picker",
|
||||
"displayName": "lime-date-time-picker 时间选择器",
|
||||
"version": "0.0.7",
|
||||
"description": "lime-date-time-picker 用于选择时间,支持日期、时分等时间维度的时间选择,兼容uniapp/uniappx",
|
||||
"keywords": [
|
||||
"date-time-picker",
|
||||
"datetime-picker",
|
||||
"时间选择",
|
||||
"时间"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^4.42"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"lime-picker",
|
||||
"lime-dayuts",
|
||||
"lime-shared"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "u",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "u",
|
||||
"app-uvue": "y",
|
||||
"app-harmony": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
236
uni_modules/lime-date-time-picker/readme.md
Normal file
236
uni_modules/lime-date-time-picker/readme.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# lime-date-time-picker 时间选择器
|
||||
- 用于选择时间,支持日期、时分等时间维度
|
||||
- 插件依赖`lime-shared`, `lime-picker`不喜勿下
|
||||
|
||||
## 文档
|
||||
[date-time-picker](https://limex.qcoon.cn/components/date-time-picker.html)
|
||||
|
||||
## 安装
|
||||
插件市场导入即可。首次导入可能需要重新编译
|
||||
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础使用
|
||||
通过 `v-model` 绑定当前选中的日期,通过 `start` 和 `end` 属性来设定可选的时间范围。在实际场景中 通常搭配 [Popup](https://ext.dcloud.net.cn/plugin?id=20769)一起使用。
|
||||
```html
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
v-model="value"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
```
|
||||
```js
|
||||
const value = ref('2024-05-02');
|
||||
|
||||
const onConfirm = (value: string) => {
|
||||
console.log('onConfirm', value)
|
||||
}
|
||||
const onChange = (value: string) => {
|
||||
console.log('onChange', value)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 类型选择
|
||||
通过 `mode` 属性可以控制选项的类型,它可以是number,也可以是中文或英文,支持以任意顺序对 `1 = 年 = year` 、 `2 = 月 = month` 、 `4 = 日 = date` 、 `8 = 时 = hour` 、 `16 = 分 = minute` 、 `32 = 秒 = second` 进行排列组合。
|
||||
|
||||
比如:<br>
|
||||
|
||||
传入 `1` 来单独选择年份<br>。
|
||||
传入 `2` 来单独选择月份<br>。
|
||||
传入 `1|2` 来选择年份和月份,位运算结果:`3`传入`3`也可以<br>。
|
||||
传入 `2|4` 来选择月份和日期,位运算结果:`6`传入`6`也可以<br>。
|
||||
传入 `1|2|4` 来选择年月日,位运算结果:`7`传入`7`也可以<br>。
|
||||
传入 `4|8` 来选择日时,位运算结果:`12`传入`12`也可以<br>。
|
||||
传入 `8|16` 来选择时分,位运算结果:`24`传入`24`也可以<br>。
|
||||
传入 `8|16|32` 来选择时分秒,位运算结果:`56`传入`56`也可以<br>。
|
||||
传入 `1|2|4|8` 来选择年月日时,位运算结果:`15`传入`15`也可以<br>。
|
||||
传入 `1|2|4|8|16` 来选择年月日时分,位运算结果:`31`传入`31`也可以<br>。
|
||||
传入 `1|2|4|8|16|32` 来选择年月日时分秒,位运算结果:`63`传入`63`也可以<br>。
|
||||
任意组合,但必须是连续的。不能相隔即不能`日`和`分`这种组合,如果觉得数字不够直观,也可以直接写对应的中文或英文
|
||||
```html
|
||||
// 数值
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
:mode="1|2|4"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
//文本
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
mode="年月日时分"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
@confirm="onConfirm"
|
||||
@change="onChange">
|
||||
</l-date-time-picker>
|
||||
```
|
||||
```js
|
||||
const value = ref('2024-05-02')
|
||||
```
|
||||
|
||||
|
||||
### 自定义label
|
||||
通过传入 `renderLabel` 函数,可以对选项文字进行格式化处理。
|
||||
```html
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:renderLabel="renderLabel"
|
||||
@confirm="onConfirm">
|
||||
</l-date-time-picker>
|
||||
```
|
||||
```js
|
||||
import { TimeModeValues } from '@/uni_modules/lime-date-time-picker'
|
||||
const renderLabel = (type: TimeModeValues, value: string): string => {
|
||||
if(type == 'year') {
|
||||
return `${value}年`
|
||||
}
|
||||
return value
|
||||
}
|
||||
```
|
||||
|
||||
### 过滤项
|
||||
通过传入 `customFilter` 函数,可以对选项数组进行过滤,实现自定义选项间隔。
|
||||
```html
|
||||
<l-date-time-picker
|
||||
title="选择日期"
|
||||
confirm-btn="确认"
|
||||
cancel-btn="取消"
|
||||
start="2020-6-30"
|
||||
end="2025-6-30"
|
||||
format="YYYY-MM-DD"
|
||||
:customFilter="filter"
|
||||
@confirm="onConfirm">
|
||||
</l-date-time-picker>
|
||||
```
|
||||
```js
|
||||
import { DateTimePickerColumn, TimeModeValues } from '@/uni_modules/lime-date-time-picker'
|
||||
const filter = (type: TimeModeValues, columns: DateTimePickerColumn):DateTimePickerColumn => {
|
||||
if (type == 'month') {
|
||||
return columns.filter((option) => parseInt(option.value) % 6 == 0);
|
||||
}
|
||||
return columns
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 查看示例
|
||||
- 导入后直接使用这个标签查看演示效果
|
||||
|
||||
```html
|
||||
<!-- // 代码位于 uni_modules/lime-date-time-picker/compoents/lime-date-time-picker -->
|
||||
<lime-date-time-picker />
|
||||
```
|
||||
|
||||
|
||||
### 插件标签
|
||||
- 默认 l-date-time-picker 为 component
|
||||
- 默认 lime-date-time-picker 为 demo
|
||||
|
||||
### 关于vue2的使用方式
|
||||
- 插件使用了`composition-api`, 如果你希望在vue2中使用请按官方的教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置
|
||||
- 关键代码是: 在main.js中 在vue2部分加上这一段即可
|
||||
```js
|
||||
// vue2
|
||||
import Vue from 'vue'
|
||||
import VueCompositionAPI from '@vue/composition-api'
|
||||
Vue.use(VueCompositionAPI)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Picker Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| v-model | 当前选中的日期 | _string_ | - |
|
||||
| value | 当前选中的日期 | _string_ | - |
|
||||
| start | 选择器的最小可选时间,默认为当前时间-10年 | _string\|number_ | - |
|
||||
| end | 选择器的最大可选时间,默认为当前时间+10年 | _string\|number_ | - |
|
||||
| format | 用于confirm事件参数格式化详细[文档](https://ext.dcloud.net.cn/plugin?id=17301) | _string_ | `` |
|
||||
| mode | 1=年、2=月、4=日、8=时、16=分、32=秒,任意组合。 | _string\|numbr_ | `1|2|4` |
|
||||
| customFilter | 选项过滤函数(type 可能值为 year, month, day, hour, minute)。 | _Func_ | `` |
|
||||
| renderLabel | 选项格式化函数(type 可能值为 year, month, day, hour, minute)。 | _Func_ | `` |
|
||||
| showUnit | label后面是否显示单位 | _boolean_ | `true` |
|
||||
| minHour | 可选的最小小时 | _number_ | `0` |
|
||||
| maxHour | 可选的最大小时 | _number_ | `23` |
|
||||
| minMinute | 可选的最小分钟 | _number_ | `0` |
|
||||
| maxMinute | 可选的最大分种 | _number_ | `59` |
|
||||
| cancelBtn | 取消按钮文字 | _string_ | `` |
|
||||
| cancelStyle | 取消按钮样式 | _string_ | `` |
|
||||
| confirmBtn | 确定按钮文字 | _string_ | `` |
|
||||
| confirmStyle | 确定按钮样式 | _string_ | `` |
|
||||
| title | 标题 | _string_ | `` |
|
||||
| titleStyle | 标题样式 | _string_ | `` |
|
||||
| itemHeight | 每项高度 | _string_ | `50px` |
|
||||
| itemColor | 每项文本颜色 | _string_ | `` |
|
||||
| itemFontSize | 每项文本字体大小 | _string_ | `` |
|
||||
| itemActiveColor | 每项文本选中颜色 | _string_ | `` |
|
||||
| indicatorStyle | 选择器中间选中框的样式 | _string_ | `` |
|
||||
| bgColor | 选择器背景色 | _string_ | `` |
|
||||
| groupHeight | 选项组高度 | _string_ | `400rpx` |
|
||||
| radius | 圆角 | _string_ | |
|
||||
|
||||
|
||||
### Events
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
| ------ | ------------------------ | ---------------------- |
|
||||
| cancel | 点击取消按钮时触发 | __ |
|
||||
| change | 选中变化时候触发 | _value: string_ |
|
||||
| confirm | 点击确认按钮时触发 | _value:string_ |
|
||||
| pick | 任何一列选中都会触发 | _value:string_ |
|
||||
|
||||
|
||||
|
||||
|
||||
## 主题定制
|
||||
|
||||
### 样式变量
|
||||
|
||||
组件提供了下列 CSS 变量,可用于自定义样式,uvue app无效。
|
||||
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| ------------------------ | -------------------- | ---- |
|
||||
| --l-picker-border-radius | _24rpx_ | - |
|
||||
| --l-picker-bg-color | _$bg-color-container_ | - |
|
||||
| --l-picker-toolbar-height | _116rpx_ | - |
|
||||
| --l-picker-cancel-color | _text-color-2_ | - |
|
||||
| --l-picker-confirm-color | _$primary-color_ | - |
|
||||
| --l-picker-button-font-size | _32rpx_ | - |
|
||||
| --l-picker-title-font-size | _36rpx_ | - |
|
||||
| --l-picker-title-font-weight | _700_ | - |
|
||||
| --l-picker-title-line-height | _52rpx_ | - |
|
||||
| --l-picker-title-color | _$text-color-1_ | - |
|
||||
| --l-picker-group-height | _400rpx_ | - |
|
||||
| --l-picker-indicator-bg-color | _$fill-4_ | - |
|
||||
| --l-picker-indicator-border-radius | _12rpx_ | - |
|
||||
| --l-picker-item-height | _50px_ | - |
|
||||
| --l-picker-item-color | _$text-color-1_ | - |
|
||||
| --l-picker-item-active-color | _$text-color-1_ | - |
|
||||
| --l-picker-item-active-color | _$text-color-1_ | - |
|
||||
| --l-picker-loading-mask-color | _rgba(255,255,255,.9)_ | - |
|
||||
| --l-picker-item-font-size | _$font-size-md_ | - |
|
||||
|
||||
|
||||
## 打赏
|
||||
|
||||
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
|
||||

|
||||

|
||||
Reference in New Issue
Block a user