index.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import { Checkbox } from "antd";
  2. import {
  3. forwardRef,
  4. useCallback,
  5. useEffect,
  6. useImperativeHandle,
  7. useMemo,
  8. useState,
  9. } from "react";
  10. import { CheckboxValueType } from "antd/es/checkbox/Group";
  11. import { DAGE_FILE_CHECKBOX_OPTIONS } from "./constants";
  12. import { DageFileCheckboxMethods, DageFileCheckboxProps } from "./types";
  13. import {
  14. DageFileResponseType,
  15. DageUpload,
  16. DageUploadType,
  17. } from "../DageUpload";
  18. import { FileCheckboxItem } from "./style";
  19. export const DageFileCheckbox = forwardRef<
  20. DageFileCheckboxMethods,
  21. DageFileCheckboxProps
  22. >(
  23. (
  24. {
  25. value,
  26. action,
  27. disabled,
  28. hasMobileModel,
  29. maxAudioCount = 1,
  30. maxImgCount = 9,
  31. maxMobileModelCount = 1,
  32. maxModelCount = 1,
  33. maxVideoCount = 1,
  34. onChange,
  35. onFileChange,
  36. },
  37. ref
  38. ) => {
  39. const checkboxVal = useMemo(() => (value ? value.split(",") : []), [value]);
  40. const [modelFiles, setModelFiles] = useState<DageFileResponseType[]>([]);
  41. const [mobileModelFiles, setMobileModelFiles] = useState<
  42. DageFileResponseType[]
  43. >([]);
  44. const [imgFiles, setImgFiles] = useState<DageFileResponseType[]>([]);
  45. const [videoFiles, setVideoFiles] = useState<DageFileResponseType[]>([]);
  46. const [audioFiles, setAudioFiles] = useState<DageFileResponseType[]>([]);
  47. const hasModel = useMemo(
  48. () => checkboxVal.includes(DageUploadType.MODEL),
  49. [checkboxVal]
  50. );
  51. const hasImg = useMemo(
  52. () => checkboxVal.includes(DageUploadType.IMG),
  53. [checkboxVal]
  54. );
  55. const hasAudio = useMemo(
  56. () => checkboxVal.includes(DageUploadType.AUDIO),
  57. [checkboxVal]
  58. );
  59. const hasVideo = useMemo(
  60. () => checkboxVal.includes(DageUploadType.VIDEO),
  61. [checkboxVal]
  62. );
  63. useImperativeHandle(ref, () => ({
  64. validate(rule, val, callback) {
  65. if (!val) {
  66. callback("请选择文件类型");
  67. } else if (
  68. hasModel &&
  69. (!modelFiles.length || !modelFiles.some((i) => i.status === "done"))
  70. ) {
  71. callback("PC端模型文件不能为空");
  72. } else if (
  73. hasModel &&
  74. hasMobileModel &&
  75. (!mobileModelFiles.length ||
  76. !mobileModelFiles.some((i) => i.status === "done"))
  77. ) {
  78. callback("移动端模型文件不能为空");
  79. } else if (
  80. hasImg &&
  81. (!imgFiles.length || !imgFiles.some((i) => i.status === "done"))
  82. ) {
  83. callback("图片文件不能为空");
  84. } else if (
  85. hasVideo &&
  86. (!videoFiles.length || !videoFiles.some((i) => i.status === "done"))
  87. ) {
  88. callback("视频文件不能为空");
  89. } else if (
  90. hasAudio &&
  91. (!audioFiles.length || !audioFiles.some((i) => i.status === "done"))
  92. ) {
  93. callback("音频文件不能为空");
  94. }
  95. callback();
  96. },
  97. setFileList(list) {
  98. const stack: Record<string, DageFileResponseType[]> = {
  99. [DageUploadType.MODEL]: [],
  100. [DageUploadType.MOBILE_MODEL]: [],
  101. [DageUploadType.IMG]: [],
  102. [DageUploadType.AUDIO]: [],
  103. [DageUploadType.VIDEO]: [],
  104. };
  105. list.forEach((item) => {
  106. stack[item.dType].push(item);
  107. });
  108. Object.keys(stack).forEach((key) => {
  109. const list = stack[key];
  110. if (!list.length) return;
  111. switch (key) {
  112. case DageUploadType.MODEL:
  113. setModelFiles(list);
  114. break;
  115. case DageUploadType.MOBILE_MODEL:
  116. setMobileModelFiles(list);
  117. break;
  118. case DageUploadType.IMG:
  119. setImgFiles(list);
  120. break;
  121. case DageUploadType.AUDIO:
  122. setAudioFiles(list);
  123. break;
  124. case DageUploadType.VIDEO:
  125. setVideoFiles(list);
  126. break;
  127. }
  128. });
  129. },
  130. }));
  131. const handleCheckbox = useCallback(
  132. (val: CheckboxValueType[]) => {
  133. onChange?.(val.join(","));
  134. },
  135. [onChange]
  136. );
  137. const handleFileChange = useCallback(
  138. (
  139. method: (v: DageFileResponseType[]) => void,
  140. list: DageFileResponseType[]
  141. ) => {
  142. method(list);
  143. },
  144. []
  145. );
  146. useEffect(() => {
  147. if (!onFileChange) return;
  148. onFileChange([
  149. ...(hasModel ? modelFiles : []),
  150. ...(hasModel && hasMobileModel ? mobileModelFiles : []),
  151. ...(hasImg ? imgFiles : []),
  152. ...(hasVideo ? videoFiles : []),
  153. ...(hasAudio ? audioFiles : []),
  154. ]);
  155. }, [
  156. hasMobileModel,
  157. modelFiles,
  158. mobileModelFiles,
  159. imgFiles,
  160. videoFiles,
  161. audioFiles,
  162. hasModel,
  163. hasImg,
  164. hasVideo,
  165. hasAudio,
  166. onFileChange,
  167. ]);
  168. return (
  169. <div className="dage-file-checkbox">
  170. <Checkbox.Group
  171. disabled={disabled}
  172. value={checkboxVal}
  173. options={DAGE_FILE_CHECKBOX_OPTIONS}
  174. style={{
  175. display: "flex",
  176. alignItems: "center",
  177. height: "32px",
  178. }}
  179. onChange={handleCheckbox}
  180. />
  181. {hasModel && (
  182. <>
  183. <FileCheckboxItem className="dage-file-checkbox__item">
  184. <p>PC端模型:</p>
  185. <DageUpload
  186. disabled={disabled}
  187. value={modelFiles}
  188. action={action}
  189. dType={DageUploadType.MODEL}
  190. maxCount={maxModelCount}
  191. maxSize={500}
  192. tips="仅支持4dage格式的模型文件,大小不能超过500M"
  193. onChange={handleFileChange.bind(undefined, setModelFiles)}
  194. />
  195. </FileCheckboxItem>
  196. {hasMobileModel && (
  197. <FileCheckboxItem className="dage-file-checkbox__item">
  198. <p>移动端模型:</p>
  199. <DageUpload
  200. disabled={disabled}
  201. value={mobileModelFiles}
  202. action={action}
  203. dType={DageUploadType.MOBILE_MODEL}
  204. maxCount={maxMobileModelCount}
  205. maxSize={1000}
  206. tips="仅支持zip格式的压缩包,大小不能超过1000M"
  207. onChange={handleFileChange.bind(
  208. undefined,
  209. setMobileModelFiles
  210. )}
  211. />
  212. </FileCheckboxItem>
  213. )}
  214. </>
  215. )}
  216. {hasImg && (
  217. <FileCheckboxItem className="dage-file-checkbox__item">
  218. <p>图片:</p>
  219. <DageUpload
  220. disabled={disabled}
  221. value={imgFiles}
  222. action={action}
  223. dType={DageUploadType.IMG}
  224. maxCount={maxImgCount}
  225. maxSize={20}
  226. tips="支持png、jpg和jpeg格式;最大20M,最多9张"
  227. onChange={handleFileChange.bind(undefined, setImgFiles)}
  228. />
  229. </FileCheckboxItem>
  230. )}
  231. {hasAudio && (
  232. <FileCheckboxItem className="dage-file-checkbox__item">
  233. <p>音频:</p>
  234. <DageUpload
  235. disabled={disabled}
  236. value={audioFiles}
  237. action={action}
  238. dType={DageUploadType.AUDIO}
  239. maxCount={maxAudioCount}
  240. maxSize={10}
  241. tips="仅支持MP3格式的音频文件,大小不得超过10MB"
  242. onChange={handleFileChange.bind(undefined, setAudioFiles)}
  243. />
  244. </FileCheckboxItem>
  245. )}
  246. {hasVideo && (
  247. <FileCheckboxItem className="dage-file-checkbox__item">
  248. <p>视频:</p>
  249. <DageUpload
  250. disabled={disabled}
  251. value={videoFiles}
  252. action={action}
  253. dType={DageUploadType.VIDEO}
  254. maxCount={maxVideoCount}
  255. maxSize={500}
  256. tips="仅支持MP4格式的视频文件,大小不得超过500MB"
  257. onChange={handleFileChange.bind(undefined, setVideoFiles)}
  258. />
  259. </FileCheckboxItem>
  260. )}
  261. </div>
  262. );
  263. }
  264. );
  265. export * from "./types";
  266. export * from "./constants";