update pay function
This commit is contained in:
127
src/views/AgentChat/components/LeftSidebar/DateGroup.js
Normal file
127
src/views/AgentChat/components/LeftSidebar/DateGroup.js
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// src/views/AgentChat/components/LeftSidebar/DateGroup.js
|
||||||
|
// 可折叠的日期分组组件
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import { Box, Text, HStack, VStack, Badge } from '@chakra-ui/react';
|
||||||
|
import { ChevronDown, ChevronRight, Calendar } from 'lucide-react';
|
||||||
|
import SessionCard from './SessionCard';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DateGroup - 可折叠的日期分组组件
|
||||||
|
*
|
||||||
|
* @param {Object} props
|
||||||
|
* @param {string} props.label - 日期标签(如"今天"、"昨天"、"11月28日")
|
||||||
|
* @param {Array} props.sessions - 该日期下的会话列表
|
||||||
|
* @param {string|null} props.currentSessionId - 当前选中的会话 ID
|
||||||
|
* @param {Function} props.onSessionSwitch - 切换会话回调
|
||||||
|
* @param {boolean} props.defaultExpanded - 默认是否展开
|
||||||
|
* @param {number} props.index - 分组索引(用于动画延迟)
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
const DateGroup = ({
|
||||||
|
label,
|
||||||
|
sessions,
|
||||||
|
currentSessionId,
|
||||||
|
onSessionSwitch,
|
||||||
|
defaultExpanded = true,
|
||||||
|
index = 0,
|
||||||
|
}) => {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
||||||
|
const hasActiveSession = sessions.some((s) => s.session_id === currentSessionId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 10 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: index * 0.05, duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Box mb={2}>
|
||||||
|
{/* 分组标题 - 可点击折叠 */}
|
||||||
|
<HStack
|
||||||
|
as="button"
|
||||||
|
w="100%"
|
||||||
|
px={2}
|
||||||
|
py={1.5}
|
||||||
|
spacing={2}
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={hasActiveSession ? 'rgba(139, 92, 246, 0.1)' : 'transparent'}
|
||||||
|
_hover={{
|
||||||
|
bg: 'rgba(255, 255, 255, 0.05)',
|
||||||
|
}}
|
||||||
|
transition="all 0.2s"
|
||||||
|
>
|
||||||
|
{/* 折叠图标 */}
|
||||||
|
<motion.div
|
||||||
|
animate={{ rotate: isExpanded ? 0 : -90 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<ChevronDown className="w-3.5 h-3.5" color="#9CA3AF" />
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* 日历图标 */}
|
||||||
|
<Calendar className="w-3.5 h-3.5" color={hasActiveSession ? '#A78BFA' : '#6B7280'} />
|
||||||
|
|
||||||
|
{/* 日期标签 */}
|
||||||
|
<Text
|
||||||
|
fontSize="xs"
|
||||||
|
fontWeight="semibold"
|
||||||
|
color={hasActiveSession ? 'purple.300' : 'gray.500'}
|
||||||
|
flex={1}
|
||||||
|
textAlign="left"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{/* 会话数量徽章 */}
|
||||||
|
<Badge
|
||||||
|
size="sm"
|
||||||
|
bg={hasActiveSession ? 'rgba(139, 92, 246, 0.2)' : 'rgba(255, 255, 255, 0.1)'}
|
||||||
|
color={hasActiveSession ? 'purple.300' : 'gray.500'}
|
||||||
|
borderRadius="full"
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
fontSize="10px"
|
||||||
|
fontWeight="semibold"
|
||||||
|
>
|
||||||
|
{sessions.length}
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* 会话列表 - 折叠动画 */}
|
||||||
|
<AnimatePresence initial={false}>
|
||||||
|
{isExpanded && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ height: 0, opacity: 0 }}
|
||||||
|
animate={{ height: 'auto', opacity: 1 }}
|
||||||
|
exit={{ height: 0, opacity: 0 }}
|
||||||
|
transition={{ duration: 0.2, ease: 'easeInOut' }}
|
||||||
|
style={{ overflow: 'hidden' }}
|
||||||
|
>
|
||||||
|
<VStack spacing={1.5} align="stretch" mt={1.5} pl={2}>
|
||||||
|
{sessions.map((session, idx) => (
|
||||||
|
<motion.div
|
||||||
|
key={session.session_id}
|
||||||
|
initial={{ opacity: 0, x: -10 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: idx * 0.03 }}
|
||||||
|
>
|
||||||
|
<SessionCard
|
||||||
|
session={session}
|
||||||
|
isActive={currentSessionId === session.session_id}
|
||||||
|
onPress={() => onSessionSwitch(session.session_id)}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</VStack>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</Box>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DateGroup;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/views/AgentChat/components/LeftSidebar/index.js
|
// src/views/AgentChat/components/LeftSidebar/index.js
|
||||||
// 左侧栏组件 - 对话历史列表
|
// 左侧栏组件 - 对话历史列表
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useMemo } from 'react';
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -15,11 +15,12 @@ import {
|
|||||||
HStack,
|
HStack,
|
||||||
VStack,
|
VStack,
|
||||||
Flex,
|
Flex,
|
||||||
|
Button,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { MessageSquare, Plus, Search, ChevronLeft } from 'lucide-react';
|
import { MessageSquare, Plus, Search, ChevronLeft, ChevronDown, MoreHorizontal } from 'lucide-react';
|
||||||
import { animations } from '../../constants/animations';
|
import { animations } from '../../constants/animations';
|
||||||
import { groupSessionsByDate } from '../../utils/sessionUtils';
|
import { groupSessionsByDate } from '../../utils/sessionUtils';
|
||||||
import SessionCard from './SessionCard';
|
import DateGroup from './DateGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LeftSidebar - 左侧栏组件
|
* LeftSidebar - 左侧栏组件
|
||||||
@@ -35,6 +36,9 @@ import SessionCard from './SessionCard';
|
|||||||
* @param {Object} props.user - 用户信息
|
* @param {Object} props.user - 用户信息
|
||||||
* @returns {JSX.Element|null}
|
* @returns {JSX.Element|null}
|
||||||
*/
|
*/
|
||||||
|
// 最多显示的日期分组数量
|
||||||
|
const MAX_VISIBLE_GROUPS = 10;
|
||||||
|
|
||||||
const LeftSidebar = ({
|
const LeftSidebar = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
@@ -46,18 +50,33 @@ const LeftSidebar = ({
|
|||||||
user,
|
user,
|
||||||
}) => {
|
}) => {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
|
const [showAllGroups, setShowAllGroups] = useState(false);
|
||||||
// 按日期分组会话
|
|
||||||
const sessionGroups = groupSessionsByDate(sessions);
|
|
||||||
|
|
||||||
// 搜索过滤
|
// 搜索过滤
|
||||||
const filteredSessions = searchQuery
|
const filteredSessions = useMemo(() => {
|
||||||
? sessions.filter(
|
if (!searchQuery) return sessions;
|
||||||
|
return sessions.filter(
|
||||||
(s) =>
|
(s) =>
|
||||||
s.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
s.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
s.session_id?.toLowerCase().includes(searchQuery.toLowerCase())
|
s.session_id?.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
)
|
);
|
||||||
: sessions;
|
}, [sessions, searchQuery]);
|
||||||
|
|
||||||
|
// 按日期分组会话(新版本返回数组)
|
||||||
|
const sessionGroups = useMemo(() => {
|
||||||
|
return groupSessionsByDate(filteredSessions);
|
||||||
|
}, [filteredSessions]);
|
||||||
|
|
||||||
|
// 控制显示的分组数量
|
||||||
|
const visibleGroups = useMemo(() => {
|
||||||
|
if (showAllGroups || sessionGroups.length <= MAX_VISIBLE_GROUPS) {
|
||||||
|
return sessionGroups;
|
||||||
|
}
|
||||||
|
return sessionGroups.slice(0, MAX_VISIBLE_GROUPS);
|
||||||
|
}, [sessionGroups, showAllGroups]);
|
||||||
|
|
||||||
|
const hasMoreGroups = sessionGroups.length > MAX_VISIBLE_GROUPS;
|
||||||
|
const hiddenGroupsCount = sessionGroups.length - MAX_VISIBLE_GROUPS;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
@@ -170,86 +189,97 @@ const LeftSidebar = ({
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 会话列表 */}
|
{/* 会话列表 - 滚动容器 */}
|
||||||
<Box flex={1} p={3} overflowY="auto">
|
<Box
|
||||||
{/* 按日期分组显示会话 */}
|
flex={1}
|
||||||
{sessionGroups.today.length > 0 && (
|
p={3}
|
||||||
<Box mb={4}>
|
overflowY="auto"
|
||||||
<Text fontSize="xs" fontWeight="semibold" color="gray.500" mb={2} px={2}>
|
overflowX="hidden"
|
||||||
今天
|
css={{
|
||||||
</Text>
|
'&::-webkit-scrollbar': {
|
||||||
<VStack spacing={2} align="stretch">
|
width: '6px',
|
||||||
{sessionGroups.today.map((session, idx) => (
|
},
|
||||||
<motion.div
|
'&::-webkit-scrollbar-track': {
|
||||||
key={session.session_id}
|
background: 'rgba(255, 255, 255, 0.05)',
|
||||||
custom={idx}
|
borderRadius: '3px',
|
||||||
initial={{ opacity: 0, x: -20 }}
|
},
|
||||||
animate={{ opacity: 1, x: 0 }}
|
'&::-webkit-scrollbar-thumb': {
|
||||||
transition={{ delay: idx * 0.05 }}
|
background: 'rgba(139, 92, 246, 0.3)',
|
||||||
|
borderRadius: '3px',
|
||||||
|
'&:hover': {
|
||||||
|
background: 'rgba(139, 92, 246, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SessionCard
|
{/* 按日期分组显示会话 */}
|
||||||
session={session}
|
{visibleGroups.map((group, index) => (
|
||||||
isActive={currentSessionId === session.session_id}
|
<DateGroup
|
||||||
onPress={() => onSessionSwitch(session.session_id)}
|
key={group.dateKey}
|
||||||
|
label={group.label}
|
||||||
|
sessions={group.sessions}
|
||||||
|
currentSessionId={currentSessionId}
|
||||||
|
onSessionSwitch={onSessionSwitch}
|
||||||
|
defaultExpanded={index < 3} // 前3个分组默认展开
|
||||||
|
index={index}
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* 查看更多按钮 */}
|
||||||
|
{hasMoreGroups && !showAllGroups && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ delay: 0.3 }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
w="100%"
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
leftIcon={<MoreHorizontal className="w-4 h-4" />}
|
||||||
|
onClick={() => setShowAllGroups(true)}
|
||||||
|
bg="rgba(255, 255, 255, 0.05)"
|
||||||
|
color="gray.400"
|
||||||
|
border="1px dashed"
|
||||||
|
borderColor="rgba(255, 255, 255, 0.1)"
|
||||||
|
_hover={{
|
||||||
|
bg: 'rgba(139, 92, 246, 0.1)',
|
||||||
|
borderColor: 'purple.400',
|
||||||
|
color: 'purple.300',
|
||||||
|
}}
|
||||||
|
mt={2}
|
||||||
|
>
|
||||||
|
查看更多 ({hiddenGroupsCount} 个日期)
|
||||||
|
</Button>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{sessionGroups.yesterday.length > 0 && (
|
{/* 收起按钮 */}
|
||||||
<Box mb={4}>
|
{showAllGroups && hasMoreGroups && (
|
||||||
<Text fontSize="xs" fontWeight="semibold" color="gray.500" mb={2} px={2}>
|
<motion.div
|
||||||
昨天
|
initial={{ opacity: 0 }}
|
||||||
</Text>
|
animate={{ opacity: 1 }}
|
||||||
<VStack spacing={2} align="stretch">
|
>
|
||||||
{sessionGroups.yesterday.map((session) => (
|
<Button
|
||||||
<SessionCard
|
w="100%"
|
||||||
key={session.session_id}
|
size="sm"
|
||||||
session={session}
|
variant="ghost"
|
||||||
isActive={currentSessionId === session.session_id}
|
leftIcon={<ChevronDown className="w-4 h-4" style={{ transform: 'rotate(180deg)' }} />}
|
||||||
onPress={() => onSessionSwitch(session.session_id)}
|
onClick={() => setShowAllGroups(false)}
|
||||||
/>
|
bg="rgba(255, 255, 255, 0.05)"
|
||||||
))}
|
color="gray.400"
|
||||||
</VStack>
|
border="1px dashed"
|
||||||
</Box>
|
borderColor="rgba(255, 255, 255, 0.1)"
|
||||||
)}
|
_hover={{
|
||||||
|
bg: 'rgba(139, 92, 246, 0.1)',
|
||||||
{sessionGroups.thisWeek.length > 0 && (
|
borderColor: 'purple.400',
|
||||||
<Box mb={4}>
|
color: 'purple.300',
|
||||||
<Text fontSize="xs" fontWeight="semibold" color="gray.500" mb={2} px={2}>
|
}}
|
||||||
本周
|
mt={2}
|
||||||
</Text>
|
>
|
||||||
<VStack spacing={2} align="stretch">
|
收起
|
||||||
{sessionGroups.thisWeek.map((session) => (
|
</Button>
|
||||||
<SessionCard
|
</motion.div>
|
||||||
key={session.session_id}
|
|
||||||
session={session}
|
|
||||||
isActive={currentSessionId === session.session_id}
|
|
||||||
onPress={() => onSessionSwitch(session.session_id)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{sessionGroups.older.length > 0 && (
|
|
||||||
<Box mb={4}>
|
|
||||||
<Text fontSize="xs" fontWeight="semibold" color="gray.500" mb={2} px={2}>
|
|
||||||
更早
|
|
||||||
</Text>
|
|
||||||
<VStack spacing={2} align="stretch">
|
|
||||||
{sessionGroups.older.map((session) => (
|
|
||||||
<SessionCard
|
|
||||||
key={session.session_id}
|
|
||||||
session={session}
|
|
||||||
isActive={currentSessionId === session.session_id}
|
|
||||||
onPress={() => onSessionSwitch(session.session_id)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 加载状态 */}
|
{/* 加载状态 */}
|
||||||
@@ -273,6 +303,15 @@ const LeftSidebar = ({
|
|||||||
<Text fontSize="xs">开始一个新对话吧!</Text>
|
<Text fontSize="xs">开始一个新对话吧!</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 搜索无结果 */}
|
||||||
|
{searchQuery && filteredSessions.length === 0 && sessions.length > 0 && (
|
||||||
|
<VStack textAlign="center" py={8} color="gray.500" fontSize="sm" spacing={2}>
|
||||||
|
<Search className="w-8 h-8" style={{ opacity: 0.5, margin: '0 auto' }} />
|
||||||
|
<Text>未找到匹配的对话</Text>
|
||||||
|
<Text fontSize="xs">尝试其他关键词</Text>
|
||||||
|
</VStack>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 用户信息卡片 */}
|
{/* 用户信息卡片 */}
|
||||||
|
|||||||
@@ -2,17 +2,113 @@
|
|||||||
// 会话管理工具函数
|
// 会话管理工具函数
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按日期分组会话列表
|
* 格式化日期为显示标签
|
||||||
|
* @param {Date} date - 日期对象
|
||||||
|
* @param {Date} today - 今天的日期
|
||||||
|
* @returns {string} 格式化后的日期标签
|
||||||
|
*/
|
||||||
|
const formatDateLabel = (date, today) => {
|
||||||
|
const daysDiff = Math.floor((today - date) / (1000 * 60 * 60 * 24));
|
||||||
|
|
||||||
|
if (daysDiff === 0) {
|
||||||
|
return '今天';
|
||||||
|
} else if (daysDiff === 1) {
|
||||||
|
return '昨天';
|
||||||
|
} else if (daysDiff < 7) {
|
||||||
|
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||||
|
return weekDays[date.getDay()];
|
||||||
|
} else {
|
||||||
|
// 超过一周,显示具体日期
|
||||||
|
return `${date.getMonth() + 1}月${date.getDate()}日`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日期的纯日期字符串(用于分组 key)
|
||||||
|
* @param {Date} date - 日期对象
|
||||||
|
* @returns {string} YYYY-MM-DD 格式的日期字符串
|
||||||
|
*/
|
||||||
|
const getDateKey = (date) => {
|
||||||
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按日期分组会话列表(新版本 - 按具体日期分组)
|
||||||
*
|
*
|
||||||
* @param {Array} sessions - 会话列表
|
* @param {Array} sessions - 会话列表
|
||||||
* @returns {Object} 分组后的会话对象 { today, yesterday, thisWeek, older }
|
* @returns {Array} 分组后的会话数组 [{ dateKey, label, sessions, date }]
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const groups = groupSessionsByDate(sessions);
|
* const groups = groupSessionsByDate(sessions);
|
||||||
* console.log(groups.today); // 今天的会话
|
* // 返回: [
|
||||||
* console.log(groups.yesterday); // 昨天的会话
|
* // { dateKey: '2025-11-30', label: '今天', sessions: [...], date: Date },
|
||||||
|
* // { dateKey: '2025-11-29', label: '昨天', sessions: [...], date: Date },
|
||||||
|
* // ...
|
||||||
|
* // ]
|
||||||
*/
|
*/
|
||||||
export const groupSessionsByDate = (sessions) => {
|
export const groupSessionsByDate = (sessions) => {
|
||||||
|
if (!sessions || sessions.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// 按日期分组到 Map
|
||||||
|
const groupMap = new Map();
|
||||||
|
|
||||||
|
sessions.forEach((session) => {
|
||||||
|
const sessionDate = new Date(session.created_at || session.timestamp);
|
||||||
|
if (isNaN(sessionDate.getTime())) {
|
||||||
|
// 无效日期,归到今天
|
||||||
|
const todayKey = getDateKey(today);
|
||||||
|
if (!groupMap.has(todayKey)) {
|
||||||
|
groupMap.set(todayKey, {
|
||||||
|
dateKey: todayKey,
|
||||||
|
label: '今天',
|
||||||
|
sessions: [],
|
||||||
|
date: today,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
groupMap.get(todayKey).sessions.push(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateOnly = new Date(sessionDate);
|
||||||
|
dateOnly.setHours(0, 0, 0, 0);
|
||||||
|
const dateKey = getDateKey(dateOnly);
|
||||||
|
|
||||||
|
if (!groupMap.has(dateKey)) {
|
||||||
|
groupMap.set(dateKey, {
|
||||||
|
dateKey,
|
||||||
|
label: formatDateLabel(dateOnly, today),
|
||||||
|
sessions: [],
|
||||||
|
date: dateOnly,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
groupMap.get(dateKey).sessions.push(session);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换为数组并按日期降序排序
|
||||||
|
const groups = Array.from(groupMap.values()).sort((a, b) => b.date - a.date);
|
||||||
|
|
||||||
|
// 每个分组内部按时间降序排序
|
||||||
|
groups.forEach((group) => {
|
||||||
|
group.sessions.sort((a, b) => {
|
||||||
|
const dateA = new Date(a.created_at || a.timestamp);
|
||||||
|
const dateB = new Date(b.created_at || b.timestamp);
|
||||||
|
return dateB - dateA;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旧版分组函数(保留兼容性)
|
||||||
|
* @deprecated 请使用 groupSessionsByDate 替代
|
||||||
|
*/
|
||||||
|
export const groupSessionsByDateLegacy = (sessions) => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const yesterday = new Date(today);
|
const yesterday = new Date(today);
|
||||||
yesterday.setDate(yesterday.getDate() - 1);
|
yesterday.setDate(yesterday.getDate() - 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user