From a2b5df22f821ad916dbba441a56df6e3f319f1d9 Mon Sep 17 00:00:00 2001 From: callmeyan Date: Wed, 16 Apr 2025 18:32:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=EF=B8=8F=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0=E7=B1=BB=E5=9E=8B=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E5=8F=8A=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierignore | 12 +++++++++++ .prettierrc | 7 +++++++ src/components/article/item.tsx | 34 +++++++++++++++++++++----------- src/i18n/translations/en-US.json | 1 + src/i18n/translations/zh-CN.json | 1 + src/pages/news/edit.tsx | 9 ++++----- src/pages/news/index.tsx | 8 ++++---- 7 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6d51cc5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,12 @@ +/node_modules +package*.json +.gitignore +*.local +*_local +__test__ +.ide +.vscode +.idea +test +dist +public \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7530022 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "useTabs": true, + "tabWidth": 2, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100 +} diff --git a/src/components/article/item.tsx b/src/components/article/item.tsx index 9c3cc31..739154e 100644 --- a/src/components/article/item.tsx +++ b/src/components/article/item.tsx @@ -2,12 +2,14 @@ import React, {useState} from "react"; import {Input, Popconfirm, Spin, Upload, UploadProps} from "antd"; import {CloseOutlined} from "@ant-design/icons"; import {clsx} from "clsx"; +import {useTranslation} from "react-i18next"; import styles from './article.module.scss' import {getOssPolicy} from "@/service/api/common.ts"; import {showToast} from "@/components/message.ts"; -import {IconAddImage, IconWarningCircle} from "@/components/icons"; -import {useTranslation} from "react-i18next"; +import {IconAddImage} from "@/components/icons"; +import {ModalWarningIcon, ModalWarningTitle} from "@/components/icons/ModalWarning.tsx"; +import { BizError } from '@/service/types.ts'; type Props = { children?: React.ReactNode; @@ -37,6 +39,10 @@ export function BlockImage({data, editable, onChange, onlyUpload, onRemove}: Ima }); const beforeUpload = async (file: any) => { try { + // 判断文件类型 + if (!MimeTypes.includes(file.type)) { + throw new Error('upload_file_type_error') + } // 因为有超时问题,所以每次上传都重新获取参数 Data.uploadConfig = await getOssPolicy(); const suffix = file.name.slice(file.name.lastIndexOf('.')); @@ -52,17 +58,22 @@ export function BlockImage({data, editable, onChange, onlyUpload, onRemove}: Ima const onUploadChange = async (info) => { if (info.fileList.length == 0) return; const file = info.fileList[0]; - console.log('onChange', file); + console.log('onUploadChange', file); if (file.status == 'done') { - setLoading(-1) - onChange?.({type: 'image', content: Data.uploadConfig?.host + '/' + file.url}) + setLoading(-1); + onChange?.({ type: 'image', content: Data.uploadConfig?.host + '/' + file.url }); } else if (file.status == 'error') { - setLoading(-1) - showToast(t('upload.upload_failed'), 'warning') + + if (!MimeTypes.includes(file.type)) { + showToast(t('upload.upload_file_type_error'), 'warning'); + return; + } + setLoading(-1); + showToast(t('upload.upload_failed'), 'warning'); } else if (file.status == 'uploading') { - setLoading(file.percent) + setLoading(file.percent); } - } + }; // return
{editable && onlyUpload ?
@@ -104,8 +115,9 @@ export function BlockImage({data, editable, onChange, onlyUpload, onRemove}: Ima rootClassName={'popconfirm-main'} placement={'right'} arrow={false} - icon={} - title={
{t('upload.delete_confirm')}
} + icon={} + title={} + description={
{t('upload.delete_confirm')}
} onConfirm={onRemove} okText={t('delete')} cancelText={t('cancel')} diff --git a/src/i18n/translations/en-US.json b/src/i18n/translations/en-US.json index 0c8c6dc..7490cc3 100644 --- a/src/i18n/translations/en-US.json +++ b/src/i18n/translations/en-US.json @@ -185,6 +185,7 @@ "upload": { "delete_confirm": "Are you sure delete the picture?", "upload_failed": "Upload failed", + "upload_file_type_error": "Only support upload image", "upload_image": "Upload Image" }, "user": { diff --git a/src/i18n/translations/zh-CN.json b/src/i18n/translations/zh-CN.json index 0e8e838..c41726e 100644 --- a/src/i18n/translations/zh-CN.json +++ b/src/i18n/translations/zh-CN.json @@ -185,6 +185,7 @@ "upload": { "delete_confirm": "请确认删除此图片?", "upload_failed": "上传图片失败,请重试", + "upload_file_type_error": "仅支持上传图片", "upload_image": "上传图片" }, "user": { diff --git a/src/pages/news/edit.tsx b/src/pages/news/edit.tsx index 7ebd265..d7245d9 100644 --- a/src/pages/news/edit.tsx +++ b/src/pages/news/edit.tsx @@ -1,4 +1,4 @@ -import {Checkbox, Popconfirm, Space} from "antd"; +import {Checkbox, Space} from "antd"; import React, {useRef, useState} from "react"; import {useRequest} from "ahooks"; @@ -10,13 +10,12 @@ import ButtonPush2Video, {ProcessResult} from "@/pages/news/components/button-pu import styles from './components/style.module.scss' import InfiniteScroller, {InfiniteScrollerRef} from "@/components/scoller/infinite-scroller.tsx"; -import {IconDelete, IconEdit, IconWarningCircle} from "@/components/icons"; +import {IconDelete, IconEdit} from "@/components/icons"; import {clsx} from "clsx"; import ButtonToTop from "@/components/scoller/button-to-top.tsx"; import ButtonDeleteBatch from "@/pages/news/components/button-delete-batch.tsx"; import {showErrorToast, showToast} from "@/components/message.ts"; import {useTranslation} from "react-i18next"; -import {ModalWarningTitle,ModalWarningIcon} from "@/components/icons/ModalWarning.tsx"; import {DeleteItemPopoverConfirm} from "@/components/message/confirm.tsx"; const FilterCache: Partial = { @@ -125,12 +124,12 @@ export default function NewEdit() { ...prev, pagination: {page, limit: 10} })) - }} onScroll={(top) => setState({showToTop: top > 30})} loading={loading} + }} onScroll={(top) => setState(s=>({...s,showToTop: top > 30}))} loading={loading} pagination={data?.pagination}>
{data?.list?.map((item, i) => { const checked = selectedRowKeys.includes(item.id) - return
+ return
setEditId(item.id)}>
{item.title}
diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 638a388..328ddd6 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -1,6 +1,6 @@ import React, {useMemo, useRef, useState} from "react"; import {Checkbox, Divider, Empty, Modal, Space} from "antd"; -import {useRequest} from "ahooks"; +import { useRequest, useSetState } from 'ahooks'; import {CloseOutlined} from "@ant-design/icons" import {clsx} from "clsx"; @@ -30,7 +30,7 @@ export default function NewsIndex() { const [activeNews, setActiveNews] = useState() - const [state, setState] = useState<{ + const [state, setState] = useSetState<{ checkAll?: boolean; showToTop?: boolean; }>({}) @@ -43,10 +43,10 @@ export default function NewsIndex() { FilterCache.tag_level_2_id = params.tag_level_2_id; FilterCache.title = params.title; FilterCache.time_flag = params.time_flag; - setCheckedId([]) if (params.pagination.page === 1) { + setCheckedId([]) setData(_data) - setState({checkAll: checkedId && _data.list && checkedId.length === _data.list.length}) + setState({checkAll: false,showToTop: false}) } else { setData({ pagination: _data.pagination,