You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ui.tsx 6.5 kB

1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * @Author: 赵伟
  3. * @Date: 2024-04-19 14:42:51
  4. * @Description: UI 公共方法
  5. */
  6. import { PageEnum } from '@/enums/pagesEnums';
  7. import { removeAllPageCacheState } from '@/hooks/useCacheState';
  8. import { deleteUploadFileReq } from '@/services/dataset/index.js';
  9. import themes from '@/styles/theme.less';
  10. import { type AppResponse, type ClientInfo, type UploadFileRes } from '@/types';
  11. import { to } from '@/utils/promise';
  12. import { history } from '@umijs/max';
  13. import {
  14. Modal,
  15. Upload,
  16. message,
  17. type FormInstance,
  18. type ModalFuncProps,
  19. type UploadFile,
  20. } from 'antd';
  21. import { NamePath } from 'antd/es/form/interface';
  22. import { isEmpty } from './index';
  23. import { closeAllModals } from './modal';
  24. import SessionStorage from './sessionStorage';
  25. type ModalConfirmProps = ModalFuncProps & {
  26. isDelete?: boolean;
  27. };
  28. /**
  29. * 自定义 Confirm 弹框
  30. */
  31. export function modalConfirm({
  32. title,
  33. content,
  34. okText = '确认',
  35. cancelText = '取消',
  36. isDelete = true,
  37. onOk,
  38. ...rest
  39. }: ModalConfirmProps) {
  40. Modal.confirm({
  41. ...rest,
  42. width: 600,
  43. centered: true,
  44. title: (
  45. <div>
  46. <img
  47. src={
  48. isDelete
  49. ? require('@/assets/img/delete-icon.png')
  50. : require('@/assets/img/confirm-icon.png')
  51. }
  52. style={{ width: '120px', marginBottom: '24px' }}
  53. draggable={false}
  54. alt=""
  55. />
  56. <div style={{ color: themes.textColor, fontSize: '16px', fontWeight: 500 }}>{title}</div>
  57. </div>
  58. ),
  59. content: content && <div style={{ color: themes.textColor, fontSize: '15px' }}>{content}</div>,
  60. okText: okText,
  61. cancelText: cancelText,
  62. onOk: onOk,
  63. });
  64. }
  65. /**
  66. * 跳转到登录页
  67. * @param toHome - 是否跳转到首页
  68. */
  69. export const gotoLoginPage = (toHome: boolean = true) => {
  70. const { pathname, search } = location;
  71. const urlParams = new URLSearchParams();
  72. urlParams.append('redirect', pathname + search);
  73. const newSearch = toHome || pathname === '/' ? '' : urlParams.toString();
  74. if (pathname !== PageEnum.LOGIN) {
  75. closeAllModals();
  76. removeAllPageCacheState();
  77. history.replace({
  78. pathname: PageEnum.LOGIN,
  79. search: newSearch,
  80. });
  81. }
  82. };
  83. /**
  84. * 跳转到 OAuth2 登录页
  85. */
  86. export const gotoOAuth2 = () => {
  87. const clientInfo = SessionStorage.getItem(SessionStorage.clientInfoKey, true) as ClientInfo;
  88. if (clientInfo) {
  89. const { clientId, userAuthorizationUri } = clientInfo;
  90. const url = `${userAuthorizationUri}?client_id=${clientId}&response_type=code&grant_type=authorization_code`;
  91. location.replace(url);
  92. }
  93. };
  94. /**
  95. * 从事件中获取上传文件列表,用于 Upload + Form 中
  96. * @param e - 事件,包含文件列表 fileList
  97. */
  98. export const getFileListFromEvent = (e: any) => {
  99. const fileList: UploadFile[] = (Array.isArray(e) ? e : e?.fileList) || [];
  100. return fileList.map((item) => {
  101. if (item.status === 'done') {
  102. const { response } = item;
  103. if (response?.code !== 200) {
  104. return {
  105. ...item,
  106. status: 'error',
  107. };
  108. }
  109. }
  110. return item;
  111. });
  112. };
  113. /**
  114. * 验证文件上传
  115. *
  116. * @param {UploadFile[]} files - The array of uploaded files.
  117. * @param {boolean} [required=true] - Flag indicating if files are required.
  118. * @return {boolean} Returns true if all files are valid, false otherwise.
  119. */
  120. export const validateUploadFiles = (files: UploadFile[], required: boolean = true): boolean => {
  121. if (required && files.length === 0) {
  122. message.error('请上传文件');
  123. return false;
  124. }
  125. const hasError = files.some((file) => {
  126. if (file.status === 'uploading') {
  127. message.error('请等待文件上传完成');
  128. return true;
  129. }
  130. if (file.status === 'error') {
  131. message.error('存在上传失败的文件,请删除后重新上传');
  132. return true;
  133. }
  134. if (!file.response || file.response.code !== 200 || !file.response.data) {
  135. message.error('存在上传失败的文件,请删除后重新上传');
  136. return true;
  137. }
  138. return false;
  139. });
  140. return !hasError;
  141. };
  142. /**
  143. * 限制上传文件类型
  144. * @param type - 只允许上次的的文件类型
  145. */
  146. export const limitUploadFileType = (type: string) => {
  147. return (file: UploadFile): boolean | string => {
  148. const acceptTypes = type.split(',').map((item) => item.trim());
  149. const fileType = file.name.split('.').pop()?.trim();
  150. if (!(fileType && acceptTypes.includes(fileType))) {
  151. message.error(`文件类型不正确,只支持 "${acceptTypes.join('、')}" 类型的文件`);
  152. file.status = 'error';
  153. return Upload.LIST_IGNORE;
  154. }
  155. return true;
  156. };
  157. };
  158. /**
  159. * 删除已上传的文件
  160. * @param file - 已上传的文件
  161. */
  162. export const removeUploadedFile = async (file: UploadFile<AppResponse<UploadFileRes[]>>) => {
  163. const { status, response } = file;
  164. const { code, data } = response ?? {};
  165. if (status === 'done' && code === 200 && Array.isArray(data) && data.length > 0) {
  166. const uploadRes = data[0];
  167. const { fileName, url } = uploadRes;
  168. const [res] = await to(
  169. deleteUploadFileReq({
  170. fileName,
  171. url,
  172. }),
  173. );
  174. if (res) {
  175. return true;
  176. } else {
  177. return false;
  178. }
  179. }
  180. return true;
  181. };
  182. /**
  183. * 删除 FormList 表单项,如果表单项没有值,则直接删除,否则弹出确认框
  184. * @param form - From实例
  185. * @param listName - FormList 的 name
  186. * @param name - FormList 的其中一项
  187. * @param remove - FormList 的删除方法
  188. * @param fieldNames - FormList 的子项名称数组
  189. * @param confirmTitle - 弹出确认框的标题
  190. */
  191. export const removeFormListItem = (
  192. form: FormInstance,
  193. listName: NamePath,
  194. name: number,
  195. remove: (name: number) => void,
  196. fieldNames: NamePath[],
  197. confirmTitle: string,
  198. ) => {
  199. const fields = fieldNames.map((item) => [listName, name, item].flat());
  200. const isEmptyField = fields.every((item) => {
  201. const value = form.getFieldValue(item);
  202. return isEmpty(value);
  203. });
  204. if (isEmptyField) {
  205. remove(name);
  206. return;
  207. }
  208. modalConfirm({
  209. title: confirmTitle,
  210. content: '是否确认删除?',
  211. onOk: () => {
  212. remove(name);
  213. },
  214. });
  215. };
  216. /**
  217. * 退出子系统
  218. * @param url - 退出登录的地址
  219. */
  220. export const oauthLogout = (url: string) => {
  221. const iframe = document.createElement('iframe');
  222. iframe.style.display = 'none';
  223. iframe.src = url;
  224. document.body.appendChild(iframe);
  225. };