Last active: a year ago
import { getPhoneMsg, GetPhoneMsgDatum } from '@/utils/api/sale-comments';
import { useRequest } from 'ahooks';
import { lazy, Suspense, useEffect, useMemo, useRef, useState } from 'react';
import Scrollbars from 'react-custom-scrollbars-2';
import { useImmer } from 'use-immer';
import SaleCard from './SaleCard';
import * as S from './SaleList.styles';
type Props = {
phone: string;
};
const SaleDetail = lazy(() => import('./SaleDetail'));
const SaleList = ({ phone }: Props) => {
const [page, setPage] = useImmer({
phone,
pageCount: 24,
page: 1,
});
const [list, setList] = useImmer<GetPhoneMsgDatum[]>([]);
const { data, loading } = useRequest(
() => getPhoneMsg(page.phone, page.pageCount, page.page),
{
refreshDeps: [page],
onSuccess: (data) => {
setList((d) => [...d, ...data.data]);
},
}
);
// 滚动加载
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const cb: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
if (!list.length || loading || msg) return;
if (entry.isIntersecting && data?.current_page !== data?.last_page) {
setPage((d) => {
d.page++;
});
}
});
};
const observe = new IntersectionObserver(cb);
ref.current && observe.observe(ref.current);
const target = ref.current;
return () => {
target && observe.unobserve(target);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data?.data.length, list.length, loading]);
// 留言详情
const [msgPage, setMsgPage] = useState(-1);
const [msgID, setMsgID] = useState(-1);
const msg = useMemo(() => list.find((m) => m.id === msgID), [list, msgID]);
/**
* 根据点击的留言所在的分页
* 请求新的数据,并合并到已有状态
*/
const refresh = async () => {
try {
const result = await getPhoneMsg(page.phone, page.pageCount, msgPage);
setList((d) => {
// 可以重新索引更新的分页,再更新数据,以减少 findIndex 搜索时间
// d.slice(page.pageCount * msgPage - page.pageCount, page.pageCount * msgPage)
result.data.forEach((res) => {
const index = d.findIndex((d) => d.id === res.id);
if (!~index) return;
d[index] = res;
});
});
} catch (err) {}
};
return (
<S.Wrapper>
<S.TitleBar>
{!!msg && (
<svg
viewBox="0 0 19 34"
fill="none"
xmlns="http://www.w3.org/2000/svg"
onClick={() => setMsgID(-1)}
>
<path
d="M16 31L3 17L16 3"
stroke="white"
strokeWidth="4"
strokeLinecap="square"
/>
</svg>
)}
<div>留言回复</div>
</S.TitleBar>
<S.Body>
<Scrollbars>
<div className="content">
{list.map((m, i) => (
<SaleCard
key={m.id}
phone={m.phone}
content={m.content}
onClick={() => {
setMsgID(m.id);
setMsgPage(Math.ceil(i / page.pageCount));
}}
replyed={!!m.reply}
/>
))}
{loading ? (
<div>加载中...</div>
) : (
<div ref={ref} style={{ height: 1 }}></div>
)}
</div>
</Scrollbars>
{!!msg && (
<Suspense fallback>
<SaleDetail msg={msg} refresh={refresh} />
</Suspense>
)}
</S.Body>
</S.Wrapper>
);
};
export default SaleList;