index.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import Taro, { useDidShow, useReachBottom } from "@tarojs/taro";
  2. import { View, Text, ScrollView } from "@tarojs/components";
  3. import EmptyData from "@/components/empty-data";
  4. import NavBarNormal from "@/components/NavBarNormal/index";
  5. import SearchBar from "@/components/search-bar/index";
  6. import style from "./index.module.less";
  7. import { useEffect, useState } from "react";
  8. import ContactCard from "./components/contact-card/index";
  9. import { getContactList, setContactToTop } from "@/service/contact";
  10. import { useLoadMoreInfinite, type TResponseData } from "@/utils/loadMoreInfinite";
  11. import PageCustom from "@/components/page-custom/index";
  12. import { TContactItem } from "@/types/contact";
  13. import { isSuccess } from "@/utils";
  14. import { delContact } from "@/service/contact";
  15. export default function Index() {
  16. const [searchValue, setSearchValue] = useState("");
  17. const fetcher = async ([_url, params, keyword]) => {
  18. params = params || {};
  19. console.log("fetcher", _url, params);
  20. const res = await getContactList({
  21. startId: params.nextId,
  22. pageSize: params.pageSize,
  23. keyword: keyword,
  24. });
  25. return res.data;
  26. };
  27. const getKey = (pageIndex:number, previousPageData) => {
  28. if (pageIndex === 0)
  29. return [
  30. "/my/contacts",
  31. { nextId: undefined, pageSize: 10},
  32. searchValue,
  33. ];
  34. if (previousPageData && previousPageData.nextId) {
  35. return [
  36. "/my/contacts",
  37. { pageSize: 10, nextId: previousPageData.nextId },
  38. searchValue,
  39. ];
  40. }
  41. return null;
  42. };
  43. const {list, setSize, mutate} = useLoadMoreInfinite<TContactItem[]>(getKey, fetcher)
  44. const resetFetchList = () => {
  45. setSize(1);
  46. };
  47. const handleSearchBarChanged = (v: string) => {
  48. setSearchValue(v);
  49. };
  50. const handleClear = () => {
  51. setSearchValue("");
  52. };
  53. const onScrollToUpper = () => {
  54. // 加载更多数据
  55. // 如果搜索框中有数据由不加载更多数据
  56. if (searchValue.length) {
  57. return;
  58. }
  59. setSize((prevSize) => prevSize + 1);
  60. };
  61. const handleHello = async (e: any) => {
  62. const detail = e.detail as { type: string; id: string };
  63. console.log(detail);
  64. // 置顶与取消置顶
  65. if (detail.type === "pin" || detail.type === "unpin") {
  66. const reseponse = await setContactToTop({
  67. isTop: detail.type === "pin",
  68. contactId: detail.id,
  69. });
  70. if (isSuccess(reseponse.status)) {
  71. mutate()
  72. return;
  73. }
  74. }
  75. if(detail.type === 'delete'){
  76. handleDelete(detail.id)
  77. }
  78. };
  79. useDidShow(() => {
  80. mutate(undefined, {revalidate:true})
  81. })
  82. const handleDelete = (contactId: string|number) => {
  83. Taro.showModal({
  84. content: "😭 确认删除该联系人吗?",
  85. async success(result) {
  86. if (result.confirm) {
  87. const response = await delContact(contactId);
  88. if(isSuccess(response.status)) {
  89. Taro.showToast({
  90. title: "删除成功",
  91. icon: 'none',
  92. });
  93. mutate()
  94. }
  95. }
  96. },
  97. });
  98. };
  99. const renderItem = (item)=> {
  100. // @ts-ignore
  101. return <slide-contact
  102. pid={item.contactId}
  103. pinned={item.isTop}
  104. onAction={handleHello}
  105. >
  106. <View className={`rounded-12 overflow-hidden ${item.isTop ? "bg-[#EDF1FF]" : "bg-white"}`}>
  107. <ContactCard
  108. refresh={mutate}
  109. deleteable={true}
  110. key={item.contactId}
  111. data={item}
  112. fromContact
  113. ></ContactCard>
  114. </View>
  115. </slide-contact>
  116. }
  117. const renderContent = () => {
  118. if (list?.length) {
  119. return list.map((item) => (
  120. <View className="rounded-24 bg-white">
  121. {renderItem(item)}
  122. </View>
  123. ));
  124. }
  125. return <EmptyData type={'search'} />;
  126. };
  127. return (
  128. <PageCustom fullPage>
  129. <NavBarNormal
  130. scrollFadeIn
  131. leftColumn={() => <Text className="text-16 font-medium">联系人</Text>}
  132. ></NavBarNormal>
  133. <View className="flex flex-col w-full">
  134. <View className="px-16 pb-14">
  135. <SearchBar
  136. value={searchValue}
  137. onChange={(e) => handleSearchBarChanged(e)}
  138. onClear={() => handleClear()}
  139. ></SearchBar>
  140. </View>
  141. <View className="rounded-container-header"></View>
  142. <View className="px-16 text-gray-45 text-12 leading-20 mb-20">
  143. 共 4 个联系人
  144. </View>
  145. <ScrollView
  146. scrollY
  147. onScrollToUpper={onScrollToUpper}
  148. style={{
  149. flex: 1,
  150. height: "100%", // 高度自适应
  151. }}
  152. >
  153. <View className={style.contactContent}>{renderContent()}</View>
  154. </ScrollView>
  155. </View>
  156. </PageCustom>
  157. );
  158. }