index.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { useState, useEffect } from "react";
  2. import ItemCard from "@/components/ItemCard";
  3. import { APPLICATION_SCENARIOS_OPTIONS } from "@/constants";
  4. import { useRequest } from "umi";
  5. import { GetTemplatePublicList } from "@/api/templateStore";
  6. import { Input, Spin, Empty } from "antd";
  7. import { MODULE_TEMPLATE_TYPE } from "@/constants";
  8. import noDataImg from "@/assets/no-data.svg";
  9. type OptionItem = {
  10. label: string;
  11. value: string;
  12. icon?: JSX.Element;
  13. };
  14. const scenes: OptionItem[] = [
  15. {
  16. label: "推荐",
  17. icon: <i className="iconfont icon-tuijian mr-1" />,
  18. value: "recommend",
  19. },
  20. ...APPLICATION_SCENARIOS_OPTIONS,
  21. ];
  22. const categorys: OptionItem[] = [
  23. { label: "全部类型", value: "all" },
  24. ...MODULE_TEMPLATE_TYPE,
  25. ];
  26. export default function Template() {
  27. const [search, setSearch] = useState("");
  28. const [industryFilter, setIndustryFilter] = useState("all");
  29. const [sceneFilter, setSceneFilter] = useState("recommend");
  30. const { data, run, loading } = useRequest(GetTemplatePublicList, {
  31. defaultParams: [
  32. {
  33. currentPage: 1,
  34. pageSize: 1000,
  35. filters: [
  36. { name: "isDel", value: 0 },
  37. { name: "isOnMarket", value: 1 },
  38. ],
  39. },
  40. ],
  41. });
  42. useEffect(() => {
  43. run({
  44. currentPage: 1,
  45. pageSize: 1000,
  46. filters: [
  47. { name: "isDel", value: 0 },
  48. { name: "isOnMarket", value: 1 },
  49. { name: "name", value: search },
  50. {
  51. name: "industries",
  52. value: industryFilter === "all" ? "" : industryFilter,
  53. },
  54. {
  55. name: "applicationScenarios",
  56. value: sceneFilter === "recommend" ? "" : sceneFilter,
  57. },
  58. ],
  59. });
  60. }, [industryFilter, sceneFilter, search]);
  61. const handleToAppDetail = (id: string) => {
  62. window.open(`#/detail/template/${id}`, "_blank");
  63. };
  64. return (
  65. <div className="flex h-full">
  66. <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">
  67. <ul className="flex flex-col gap-y-2">
  68. {categorys.map((item) => (
  69. <li
  70. key={item.value}
  71. 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" : ""}`}
  72. onClick={() => setIndustryFilter(item.value)}
  73. >
  74. <span>{item.label}</span>
  75. </li>
  76. ))}
  77. </ul>
  78. </div>
  79. <div className="right flex-1 pt-6 px-4 h-full flex flex-col">
  80. <div className="shrink-0 pt-6 px-12">
  81. <div className="mb-1 text-primary text-xl font-semibold">
  82. 探索模块模版
  83. </div>
  84. <div className="text-gray-500 text-sm">
  85. 使用这些内容模块,可以快速完善你的系统功能模块。
  86. </div>
  87. </div>
  88. <div className="flex items-center justify-between mt-6 px-12">
  89. <div className="flex space-x-1 text-[13px] flex-wrap">
  90. {scenes.map((scene) => (
  91. <div
  92. key={scene.value}
  93. 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"}`}
  94. onClick={() => setSceneFilter(scene.value)}
  95. >
  96. {scene.icon}
  97. {scene.label}
  98. </div>
  99. ))}
  100. </div>
  101. <div>
  102. <Input
  103. value={search}
  104. onChange={(e) => setSearch(e.target.value)}
  105. placeholder="搜索"
  106. prefix={<i className="iconfont icon-sousuo" />}
  107. allowClear
  108. ></Input>
  109. </div>
  110. </div>
  111. <div className="relative flex flex-1 pb-6 flex-col overflow-auto bg-gray-100 shrink-0 grow mt-4">
  112. <nav
  113. className="grid content-start shrink-0 gap-4 px-6 sm:px-12"
  114. style={{ gridTemplateColumns: "repeat(3,minmax(0,1fr))" }}
  115. >
  116. {(data?.result?.model || []).map((item: any, index: number) => (
  117. <ItemCard data={item} key={index} onClick={handleToAppDetail} />
  118. ))}
  119. </nav>
  120. {!data?.result.model.length && !loading && (
  121. <Empty description="暂无数据" image={noDataImg} />
  122. )}
  123. <div className="h-200px w-full absolute left-0 top0 flex items-center justify-center">
  124. <Spin spinning={loading} />
  125. </div>
  126. </div>
  127. </div>
  128. </div>
  129. );
  130. }