index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { useEffect, useState } from "react";
  2. import ItemCard from "@/components/ItemCard";
  3. import { Input, Empty, Spin, Pagination } from "antd";
  4. import { GetAppPublicList } from "@/api/appStore";
  5. import { useRequest } from "umi";
  6. import { INDUSTRIE_OPTIONS, APPLICATION_SCENARIOS_OPTIONS } from "@/constants";
  7. import noDataImg from "@/assets/no-data.svg";
  8. import "@/style/index.less";
  9. type SceneItem = {
  10. label: string;
  11. value: string;
  12. icon?: JSX.Element;
  13. };
  14. const industrys = [{ label: "全部行业", value: "all" }, ...INDUSTRIE_OPTIONS];
  15. const scenes: SceneItem[] = [
  16. {
  17. label: "推荐",
  18. icon: <i className="iconfont icon-tuijian mr-1" />,
  19. value: "recommend",
  20. },
  21. ...APPLICATION_SCENARIOS_OPTIONS,
  22. ];
  23. export default function Home() {
  24. const [search, setSearch] = useState("");
  25. const [industryFilter, setIndustryFilter] = useState("all");
  26. const [sceneFilter, setSceneFilter] = useState("recommend");
  27. const [currentPage, setCurrentPage] = useState(1);
  28. const { data, run, loading } = useRequest(GetAppPublicList, {
  29. defaultParams: [
  30. {
  31. currentPage: 1,
  32. pageSize: 20,
  33. filters: [
  34. { name: "isDel", value: 0 },
  35. { name: "isOnMarket", value: 1 },
  36. ],
  37. },
  38. ],
  39. });
  40. useEffect(() => {
  41. setCurrentPage(1);
  42. run({
  43. currentPage: 1,
  44. pageSize: 20,
  45. filters: [
  46. { name: "isDel", value: 0 },
  47. { name: "isOnMarket", value: 1 },
  48. { name: "name", value: search },
  49. {
  50. name: "industries",
  51. value: industryFilter === "all" ? "" : industryFilter,
  52. },
  53. {
  54. name: "applicationScenarios",
  55. value: sceneFilter === "recommend" ? "" : sceneFilter,
  56. },
  57. ],
  58. });
  59. }, [industryFilter, sceneFilter, search]);
  60. const handleChangePage = (page: number) => {
  61. setCurrentPage(page);
  62. run({
  63. currentPage: page,
  64. pageSize: 20,
  65. filters: [
  66. { name: "isDel", value: 0 },
  67. { name: "isOnMarket", value: 1 },
  68. { name: "name", value: search },
  69. {
  70. name: "industries",
  71. value: industryFilter === "all" ? "" : industryFilter,
  72. },
  73. {
  74. name: "applicationScenarios",
  75. value: sceneFilter === "recommend" ? "" : sceneFilter,
  76. },
  77. ],
  78. });
  79. };
  80. const handleToAppDetail = (id: string) => {
  81. window.open(`#/detail/application/${id}`, "_blank");
  82. };
  83. return (
  84. <div className="flex h-full">
  85. <div className="left w-fit sm:w-[216px] shrink-0 pt-6 px-4 border-gray-200 border-0 border-r border-solid border-gray-200">
  86. <ul className="flex flex-col gap-y-2">
  87. {industrys.map((item) => (
  88. <li
  89. key={item.value}
  90. className={`cursor-pointer text-14px text-secondary gap-2 flex items-center pc:justify-start pc:w-full mobile:justify-center mobile:w-fit h-9 px-3 mobile:px-2 rounded-lg ${industryFilter === item.value ? "bg-white font-semibold !text-primary shadow-xs" : ""}`}
  91. onClick={() => setIndustryFilter(item.value)}
  92. >
  93. <span>{item.label}</span>
  94. </li>
  95. ))}
  96. </ul>
  97. </div>
  98. <div className="right flex-1 pt-6 px-4 h-full flex flex-col">
  99. <div className="shrink-0 pt-6 px-12">
  100. <div className="mb-1 text-primary text-xl font-semibold">
  101. 探索应用模版
  102. </div>
  103. <div className="text-gray-500 text-sm">
  104. 使用这些模板应用程序,或根据模板自定义您自己的应用程序。
  105. </div>
  106. </div>
  107. <div className="flex items-center justify-between mt-6 px-12">
  108. <div className="flex space-x-1 text-[13px] flex-wrap">
  109. {scenes.map((scene) => (
  110. <div
  111. key={scene.value}
  112. className={`cursor-pointer px-3 py-[7px] h-[32px] rounded-lg font-medium leading-[18px] cursor-pointer ${scene.value === sceneFilter ? "bg-white shadow-xs text-primary-600 text-primary" : "border-transparent text-gray-700 hover:bg-gray-200"}`}
  113. onClick={() => setSceneFilter(scene.value)}
  114. >
  115. {scene?.icon}
  116. {scene.label}
  117. </div>
  118. ))}
  119. </div>
  120. <div>
  121. <Input
  122. value={search}
  123. onChange={(e) => setSearch(e.target.value)}
  124. placeholder="搜索"
  125. prefix={<i className="iconfont icon-sousuo" />}
  126. allowClear
  127. ></Input>
  128. </div>
  129. </div>
  130. <div className="relative flex flex-1 pb-6 flex-col overflow-auto bg-gray-100 shrink-0 grow mt-4 relative">
  131. <nav className="style_appList grid content-start shrink-0 gap-4 px-6 sm:px-12">
  132. {(data?.result?.model || []).map((item: any, index: number) => (
  133. <ItemCard data={item} key={index} onClick={handleToAppDetail} />
  134. ))}
  135. </nav>
  136. <Pagination
  137. className="mt-6"
  138. align="center"
  139. hideOnSinglePage
  140. current={currentPage}
  141. pageSize={20}
  142. total={data?.result?.totalCount || 0}
  143. onChange={handleChangePage}
  144. />
  145. {!data?.result.model.length && !loading && (
  146. <Empty description="暂无数据" image={noDataImg} />
  147. )}
  148. <div className="h-200px w-full absolute left-0 top0 flex items-center justify-center pointer-events-none">
  149. <Spin spinning={loading} />
  150. </div>
  151. </div>
  152. </div>
  153. </div>
  154. );
  155. }