index.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { useEffect, useRef, useState } from "react";
  2. import { Image, View, ScrollView, Video } from "@tarojs/components";
  3. import { formatSeconds } from "@/utils/index";
  4. import PageCustom from "@/components/page-custom/index";
  5. import NavBarNormal from "@/components/NavBarNormal/index";
  6. import { uploadAndNavToGenNewAvatar } from "@/utils/avatar";
  7. import IconPlusBig from "@/components/icon/icon-plus-big";
  8. import { editAgentAvatar } from "@/service/agent";
  9. import { deleteAvatar, fetchMyAvatars } from "@/service/storage";
  10. import style from "./index.module.less";
  11. import { TAvatarItem } from "@/service/storage";
  12. import { useAgentStore } from "@/store/agentStore";
  13. import Taro, { useDidShow } from "@tarojs/taro";
  14. import { isSuccess } from "@/utils";
  15. import IconDeleteGray16 from "@/components/icon/IconDeleteGray16";
  16. import { useModalStore } from "@/store/modalStore";
  17. import { useLoadMoreInfinite, createKey } from "@/utils/loadMoreInfinite";
  18. export default function Index() {
  19. const { agent, fetchAgent } = useAgentStore();
  20. const [scrollTop, setScrollTop] = useState(0);
  21. const scrollPositionRef = useRef(0);
  22. const { showModal } = useModalStore();
  23. const fetcher = async ([_url, { pageIndex, pageSize }]) => {
  24. const res = await fetchMyAvatars({ pageIndex: pageIndex, pageSize });
  25. return res.data;
  26. };
  27. const { list, loadMore, mutate } = useLoadMoreInfinite<TAvatarItem[]>(
  28. createKey("fetchMyAvatars"),
  29. fetcher
  30. );
  31. const [current, setCurrent] = useState<TAvatarItem | null>(null);
  32. const handleClick = async (item: TAvatarItem) => {
  33. console.log(item);
  34. if (!agent?.agentId) {
  35. return;
  36. }
  37. Taro.showLoading();
  38. const result = await editAgentAvatar(agent.agentId, item.avatarId, true);
  39. await fetchAgent(agent.agentId);
  40. Taro.hideLoading();
  41. setCurrent(item);
  42. if (isSuccess(result.status)) {
  43. Taro.navigateBack();
  44. }
  45. };
  46. const onScrollToLower = () => {
  47. loadMore();
  48. console.log("lower");
  49. };
  50. const handleCreate = () => {
  51. uploadAndNavToGenNewAvatar();
  52. };
  53. const handleDelete = async (e: any, avatar: TAvatarItem) => {
  54. e.stopPropagation();
  55. showModal({
  56. content: <>确认删除该形象?</>,
  57. async onConfirm() {
  58. const response = await deleteAvatar(avatar.avatarId);
  59. if (isSuccess(response.status)) {
  60. mutate();
  61. }
  62. },
  63. });
  64. };
  65. useDidShow(()=> {
  66. mutate()
  67. })
  68. const renderMedia = (avatar: TAvatarItem) => {
  69. if (avatar.isVideo) {
  70. return <>
  71. <View className={style.videoContainer}>
  72. <Video
  73. controls={false}
  74. showCenterPlayBtn={false}
  75. loop={true}
  76. muted={true}
  77. objectFit="cover"
  78. src={avatar.avatarUrl}
  79. className="w-full h-full"
  80. />
  81. <View className={style.durationStatus}>
  82. <View className={style.playBtn}></View>
  83. <View>{formatSeconds(Math.round(avatar.videoSeconds))}</View>
  84. </View>
  85. </View>
  86. </>
  87. }
  88. return <Image src={avatar.avatarUrl} mode="widthFix" className="w-full" />;
  89. };
  90. const renderList = () => {
  91. if (!list.length) {
  92. return (
  93. <>
  94. {/* <EmptyData type={"search"}></EmptyData> */}
  95. </>
  96. );
  97. }
  98. return list.map((avatar) => {
  99. const isCurrent = agent?.avatarUrl === avatar.avatarUrl;
  100. return (
  101. <View
  102. className={`${isCurrent ? style.gridItemActived : style.gridItem}`}
  103. onClick={() => handleClick(avatar)}
  104. >
  105. {avatar.canDel && (
  106. <View
  107. className={style.deleteButton}
  108. onClick={(e) => handleDelete(e, avatar)}
  109. >
  110. <IconDeleteGray16 />
  111. </View>
  112. )}
  113. {renderMedia(avatar)}
  114. </View>
  115. );
  116. });
  117. };
  118. return (
  119. <PageCustom>
  120. <NavBarNormal>历史形象</NavBarNormal>
  121. <View className={style.container}>
  122. <ScrollView
  123. scrollY
  124. onScrollToLower={onScrollToLower}
  125. scrollTop={scrollTop}
  126. onScroll={(e) => {
  127. scrollPositionRef.current = e.detail.scrollTop;
  128. }}
  129. style={{
  130. flex: 1,
  131. height: "100%", // 高度自适应
  132. }}
  133. >
  134. <View className="w-full p-16 pb-120">
  135. <View className={style.grid}>
  136. <View className={style.gridItem} onClick={handleCreate}>
  137. <View className={style.icon}>
  138. <IconPlusBig></IconPlusBig>
  139. </View>
  140. <View className="pt-8 text-12 leading-20 text-gray-45">
  141. 创建新形象
  142. </View>
  143. </View>
  144. {renderList()}
  145. </View>
  146. </View>
  147. </ScrollView>
  148. </View>
  149. </PageCustom>
  150. );
  151. }