近期老板看我们太闲了,上个厕所都占不到坑了,于是,老板:你们把后台的功能往飞书小程序迁移吧,嘿嘿,看我不给你写点防御性代码,后面再整个后台app版,主打的一个工作稳定。
那么好,开整呗,谁让咱是打工的呢!首先就是基建,这个这边就不多废话了(这边也是提取了一个飞书小程序模版,回头闲一点再优化优化丢到github上)。
那么直接到写业务阶段,这边我们小程序ui库使用的taro-ui,我们后台的ui库是ant-design,那么问题就来了,抛开组件抛出来的数据结构不一致不说,tm好多组件直接没有,气冲冲的跑到老板办公室,得加钱,这是另外的价钱,于是于是就开始画饼了。
这块后台最常用的而taroui没有的组件:
- 日期选择器
ant-design
taroui
2.选择器
ant-design
taroui
这块就举个例子,就以上两个组件taro可以说是实现不了后台相同的功能的,只能自己手撸一个,本文是日期选择器所以以下内容就针对日期时间选择器,选择器这快也是大概按照飞书内部的选择器封装了一个,后续也会出相关的文章,
这块还有一个就是taro的日期选择和时间选择是分开的,而我们后台是一个字段,好吧开整,
功能
首先分析一波,需要做到的功能:
- 详情回显
- 选择日期时间后抛给父组件
- 首次默认是当前时间
PickerDateTime
import { Text, PickerView, PickerViewColumn, View } from "@tarojs/components";
import React, { useMemo, useRef, useState } from "react";
import { AtFloatLayout } from "taro-ui";
import dayjs from "dayjs";
export interface PickerDateTimeProps {
type: "date" | "datetime";
value: string;
onChange: (val: any) => void;
}
const findDateTimeIndex = (arr: Array<number | string>, val: number | string) => {
const index = arr.map(Number).indexOf(+val);
return index === -1 ? 0 : index;
};
const addZero = (num: number | string) => {
return +num <= 9 ? `0${+num}` : `${+num}`;
};
const getDateTimeConfig = () => {
function createDateTimeByStartAndEnd(start, end) {
const arr = Array.from({ length: end - start + 1 }, (_, i) => addZero(start + i));
return arr;
}
return [
createDateTimeByStartAndEnd(1990, 2024),
createDateTimeByStartAndEnd(1, 12),
createDateTimeByStartAndEnd(1, 31),
createDateTimeByStartAndEnd(0, 23),
createDateTimeByStartAndEnd(0, 59),
createDateTimeByStartAndEnd(0, 59)
];
};
const PickerDateTime: React.FC<PickerDateTimeProps> = props => {
const { value, onChange } = props;
const dates = getDateTimeConfig();
const [years, months, days, hours, minutes, seconds] = dates;
const [openSelector, setOpenSelector] = useState(true);
const selectIndexs = useRef<number[]>([]);
const generateEchoIndexByValue = useMemo(() => {
let indexs: number[] = [];
if (value) {
const [date, time] = value.split(" ");
const [year, month, day] = date.split("-");
const [hour, minute, second] = time.split(":");
indexs = [
findDateTimeIndex(years, year),
findDateTimeIndex(months, addZero(month)),
findDateTimeIndex(days, addZero(day)),
findDateTimeIndex(hours, addZero(hour)),
findDateTimeIndex(minutes, addZero(minute)),
findDateTimeIndex(seconds, addZero(second))
];
} else {
const now = dayjs();
indexs = [
findDateTimeIndex(years, now.year()),
findDateTimeIndex(months, addZero(now.month() + 1)),
findDateTimeIndex(days, addZero(now.date())),
findDateTimeIndex(hours, addZero(now.hour())),
findDateTimeIndex(minutes, addZero(now.minute())),
findDateTimeIndex(seconds, addZero(now.second()))
];
}
selectIndexs.current = indexs;
return indexs;
}, [value, years, months, days, hours, minutes, seconds]);
/**
* 根据选择的时间下标数组生成日期时间
* @param indexs
* @returns
*/
const generateDateTimeStrByIndexs = (indexs: number[]) => {
const datesArr = indexs.map((item, i) => dates[i][item]);
const date = datesArr.slice(0, 3).join("-");
const time = datesArr.slice(3).join(":");
return date + " " + time;
};
const onConfirm = () => {
const dateTime = generateDateTimeStrByIndexs(selectIndexs.current);
onChange(dateTime);
setOpenSelector(false);
};
return (
<View>
<View className="flex items-center justify-between text-xs text-gray-900">
<Text className="text-sm font-semibold">日期时间</Text>
<Text
onClick={() => {
setOpenSelector(true);
}}>
{value}
</Text>
</View>
<View>
<AtFloatLayout isOpened={openSelector}>
<View>
<Text className="block w-20 h-1 bg-slate-500 rounded-full mx-auto"></Text>
<View className="mt-3 mb-6 flex items-center justify-center pb-3 border-b-.5 border-gray-200 relative">
<Text className="text-base font-semibold text-gray-900">请选择日期</Text>
<Text className="text-xs text-42-blue absolute right-0 top-2" onClick={onConfirm}>
确认
</Text>
</View>
</View>
<View className=" grid grid-cols-6">
{["年", "月", "日", "时", "分", "秒"].map(head => {
return <Text className=" text-center col-span-1 text-xs font-semibold text-gray-900">{head}</Text>;
})}
</View>
<PickerView
indicatorStyle="height: 50px;"
style="width: 100%; height: 300px;"
value={generateEchoIndexByValue}
onChange={e => {
selectIndexs.current = e.detail.value;
}}>
<PickerViewColumn>
{years.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
<PickerViewColumn>
{months.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
<PickerViewColumn>
{days.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
<PickerViewColumn>
{hours.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
<PickerViewColumn>
{minutes.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
<PickerViewColumn>
{seconds.map(item => {
return <Text className="flex items-center justify-center text-xs text-gray-900">{item}</Text>;
})}
</PickerViewColumn>
</PickerView>
</AtFloatLayout>
</View>
</View>
);
};
export default PickerDateTime;
看看最终效果吧
以上就是该组件完整功能和代码了,希望这篇博客能帮助你更好地理解和使用这个组件,如果觉得这篇文章还有点屌用的,点赞收藏支持一下,谢谢🐶!