Compare commits

...

4 Commits

Author SHA1 Message Date
Lei OT 5772d61a85 页面隐藏时暂停时钟 1 year ago
Lei OT c4f13b5b8e perf: 时区设置一次 1 year ago
Lei OT aa62fc183e perf: timezone short name 1 year ago
Lei OT 7014f704d3 feat: timezone 1 year ago

@ -12,6 +12,7 @@
}, },
"dependencies": { "dependencies": {
"antd": "^5.14.0", "antd": "^5.14.0",
"countries-and-timezones": "^3.6.0",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"emoji-picker-react": "^4.8.0", "emoji-picker-react": "^4.8.0",

@ -6,23 +6,30 @@ import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc'; import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone'; import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
import { useVisibilityState } from '@/hooks/useVisibilityState';
dayjs.extend(utc); dayjs.extend(utc);
dayjs.extend(timezone); dayjs.extend(timezone);
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
const ExpireTimeClock = ({ expireTime }) => { const ExpireTimeClock = ({ expireTime }) => {
const isVisible = useVisibilityState();
const [customerDateTime, setCustomerDateTime] = useState(''); const [customerDateTime, setCustomerDateTime] = useState('');
const [isExpired, setIsExpired] = useState(false); const [isExpired, setIsExpired] = useState(false);
useEffect(() => { useEffect(() => {
const intervalId = setInterval(() => { let interval;
// .tz('Asia/Shanghai') UTC Asia/Shanghai GMT+8 if (isVisible) {
setCustomerDateTime(dayjs(expireTime).add(8, 'hours').fromNow()); interval = setInterval(() => {
}, 1000); // .tz('Asia/Shanghai') UTC Asia/Shanghai GMT+8
return () => clearInterval(intervalId); setCustomerDateTime(dayjs(expireTime).add(8, 'hours').fromNow());
}, [expireTime]); }, 1000);
} else {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [isVisible, expireTime]);
useEffect(() => { useEffect(() => {
const _ago = customerDateTime.slice(-3) === 'ago'; const _ago = customerDateTime.slice(-3) === 'ago';

@ -1,44 +1,94 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Typography } from 'antd'; import { Typography, Select } from 'antd';
// import { useConversationState } from '@/stores/ConversationContext'; import ct from 'countries-and-timezones';
import dayjs from 'dayjs'; import { useVisibilityState } from '@/hooks/useVisibilityState';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc); const LocalTimeClock = ({ region, timezone, ...props }) => {
dayjs.extend(timezone); const isVisible = useVisibilityState();
const LocalTimeClock = ((props) => {
// const { customerOrderProfile: orderInfo } = useConversationState();
const [countryTimezones, setCountryTimezones] = useState([]);
const [timezoneP, setTimezoneP] = useState(timezone);
const [customerDateTime, setCustomerDateTime] = useState(); const [customerDateTime, setCustomerDateTime] = useState();
// console.log(timezone, timezoneP);
useEffect(() => {
if (timezone) {
setTimezoneP(timezone);
} else {
const _countryTimezones = Object.values(ct.getTimezonesForCountry(region || 'CN')).map((tz) => {
const date = new Date();
const options = { timeZone: tz.name, timeZoneName: 'short' };
const shortName = date.toLocaleTimeString('en-US', options).split(' ')[2];
return { ...tz, fullName: `${tz.name} (${shortName})`, shortName };
});
// console.log(_countryTimezones);
setCountryTimezones(_countryTimezones);
setTimezoneP(_countryTimezones[0].name);
}
return () => {};
}, [region, timezone]);
// todo: dayjs
useEffect(() => { useEffect(() => {
const intervalId = setInterval(() => { let interval;
// if (customerProfile && customerProfile.timezone) { if (isVisible) {
const date = new Date(); interval = setInterval(() => {
const options = { const options = {
year: 'numeric', timeZone: timezoneP,
month: 'long', timeZoneName: 'short',
day: 'numeric', hour12: false,
hour: 'numeric', month: '2-digit',
minute: 'numeric', day: '2-digit',
second: 'numeric', hour: '2-digit',
hour12: true, minute: '2-digit',
}; // second: '2-digit',
const formatter = new Intl.DateTimeFormat('cn-ZH', options); // todo: };
setCustomerDateTime(formatter.format(date)); // const date = new Date();
// } // const formatter = new Intl.DateTimeFormat('en-US', options);
}, 1000); // Update every second // setCustomerDateTime(formatter.format(date));
setCustomerDateTime(new Date().toLocaleTimeString('cn-ZH', options));
}, 1000);
} else {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [isVisible, timezoneP]);
// Cleanup function to clear the interval when the component is unmounted return region ? (
return () => clearInterval(intervalId);
}, []);
return (
<> <>
<Typography.Text>{customerDateTime}</Typography.Text> {/* 🌏🌐🧭 */}
<Typography.Text>🌐{region}</Typography.Text>
{countryTimezones.length > 1 ? (
<Select
size={'small'}
style={{ width: 150 }}
dropdownStyle={{ width: 250 }}
variant='borderless'
onSelect={(value) => {
setTimezoneP(value);
// setOrderPropValue(currentOrder, 'orderlabel', value)
// .then(() => {
// message.success('')
// })
// .catch(reason => {
// notification.error({
// message: '',
// description: reason.message,
// placement: 'top',
// duration: 60,
// })
// })
}}
value={timezoneP}
options={countryTimezones}
fieldNames={{ label: 'fullName', value: 'name' }}
/>
) : (
<>
{/* <Typography.Text>{timezoneP}</Typography.Text> */}
</>
)}
<Typography.Text>{customerDateTime}</Typography.Text>
</> </>
); ) : null;
}); };
export default LocalTimeClock; export default LocalTimeClock;

@ -4,6 +4,7 @@ import { Flex, Typography, Avatar, Alert, Button, Tooltip, Spin } from 'antd';
import { ReloadOutlined, ApiOutlined } from '@ant-design/icons'; import { ReloadOutlined, ApiOutlined } from '@ant-design/icons';
import { LoadingOutlined } from '@ant-design/icons'; import { LoadingOutlined } from '@ant-design/icons';
import ExpireTimeClock from './ExpireTimeClock'; import ExpireTimeClock from './ExpireTimeClock';
import LocalTimeClock from './LocalTimeClock';
const MessagesHeader = () => { const MessagesHeader = () => {
const userId = useAuthStore(state => state.loginUser.userId); const userId = useAuthStore(state => state.loginUser.userId);
@ -39,7 +40,11 @@ const MessagesHeader = () => {
<> <>
<Typography.Text strong>{currentConversation.customer_name}</Typography.Text> <Typography.Text strong>{currentConversation.customer_name}</Typography.Text>
{currentConversation.whatsapp_phone_number ? ( {currentConversation.whatsapp_phone_number ? (
<>
<Typography.Text>{currentConversation.whatsapp_phone_number}</Typography.Text> <Typography.Text>{currentConversation.whatsapp_phone_number}</Typography.Text>
{/* todo: regionCode */}
<LocalTimeClock region={'US'} timezone={'America/New_York'} />
</>
) : ( ) : (
<Typography.Text strong type='danger'> <Typography.Text strong type='danger'>
没有WhatsApp号码 没有WhatsApp号码

Loading…
Cancel
Save