完成图片压缩功能
This commit is contained in:
29
package-lock.json
generated
29
package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"antd": "^5.19.3",
|
||||
"apexcharts": "^3.41.0",
|
||||
"axios": "^1.7.2",
|
||||
"compressorjs": "^1.2.1",
|
||||
"dicebear": "^9.2.1",
|
||||
"flatpickr": "^4.6.13",
|
||||
"headlessui": "^0.0.0",
|
||||
@@ -2770,6 +2771,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/blueimp-canvas-to-blob": {
|
||||
"version": "3.29.0",
|
||||
"resolved": "https://registry.npmmirror.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
|
||||
"integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/boxen": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/boxen/-/boxen-7.1.1.tgz",
|
||||
@@ -3264,6 +3271,16 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/compressorjs": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/compressorjs/-/compressorjs-1.2.1.tgz",
|
||||
"integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"blueimp-canvas-to-blob": "^3.29.0",
|
||||
"is-blob": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/compute-gcd": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/compute-gcd/-/compute-gcd-1.2.1.tgz",
|
||||
@@ -4230,6 +4247,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-blob": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/is-blob/-/is-blob-2.1.0.tgz",
|
||||
"integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-ci": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/is-ci/-/is-ci-3.0.1.tgz",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"antd": "^5.19.3",
|
||||
"apexcharts": "^3.41.0",
|
||||
"axios": "^1.7.2",
|
||||
"compressorjs": "^1.2.1",
|
||||
"dicebear": "^9.2.1",
|
||||
"flatpickr": "^4.6.13",
|
||||
"headlessui": "^0.0.0",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { FileDir } from '@/types/app/file';
|
||||
import { InboxOutlined } from '@ant-design/icons';
|
||||
import type { UploadProps } from 'antd';
|
||||
import { message, Modal, Upload } from 'antd';
|
||||
import { useUserStore } from '@/stores'
|
||||
import { baseURL } from '@/utils/request'
|
||||
import { message, Modal, Radio, Select, Upload } from 'antd';
|
||||
import { useUserStore } from '@/stores';
|
||||
import { baseURL } from '@/utils/request';
|
||||
import Compressor from 'compressorjs';
|
||||
import { useState } from 'react';
|
||||
|
||||
const { Dragger } = Upload;
|
||||
|
||||
@@ -15,7 +17,9 @@ interface UploadFileProps {
|
||||
}
|
||||
|
||||
export default ({ dir, open, onCancel, onSuccess }: UploadFileProps) => {
|
||||
const store = useUserStore()
|
||||
const store = useUserStore();
|
||||
const [quality, setQuality] = useState(1000);
|
||||
const [isCompressionUpload, setIsCompressionUpload] = useState(false);
|
||||
|
||||
const uploadProps: UploadProps = {
|
||||
name: 'files',
|
||||
@@ -25,28 +29,80 @@ export default ({ dir, open, onCancel, onSuccess }: UploadFileProps) => {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${store.token}`
|
||||
},
|
||||
// 上传之前触发
|
||||
beforeUpload: async (file) => {
|
||||
if (quality === 1000) return file
|
||||
|
||||
// 对图片进行压缩处理
|
||||
return new Promise((resolve, reject) => {
|
||||
new Compressor(file, {
|
||||
quality,
|
||||
success: (file) => {
|
||||
resolve(file);
|
||||
},
|
||||
error: (err) => {
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
})
|
||||
},
|
||||
onChange(info) {
|
||||
const { status } = info.file;
|
||||
|
||||
let res;
|
||||
if (status !== 'uploading') {
|
||||
res = info?.file?.response
|
||||
res = info?.file?.response;
|
||||
|
||||
if (res.code === 400) return message.error(res.message)
|
||||
if (res?.code === 400) return message.error(res.message);
|
||||
}
|
||||
if (status === 'done') {
|
||||
message.success(`文件上传成功`);
|
||||
onSuccess()
|
||||
onSuccess();
|
||||
} else if (status === 'error') {
|
||||
message.error(`文件上传失败:${res.message}`);
|
||||
message.error(`文件上传失败:${res?.message}`);
|
||||
}
|
||||
},
|
||||
className: "py-4"
|
||||
};
|
||||
|
||||
// 初始化操作
|
||||
const onCloseModel = () => {
|
||||
setIsCompressionUpload(false);
|
||||
setQuality(1000);
|
||||
onCancel();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal title="文件上传" open={open} onCancel={onCancel} footer={null}>
|
||||
<Modal title="文件上传" open={open} onCancel={onCloseModel} footer={null}>
|
||||
<div className='my-4'>
|
||||
<Radio.Group defaultValue={0} onChange={(e) => setIsCompressionUpload(e.target.value ? true : false)}>
|
||||
<Radio value={0}>无损上传</Radio>
|
||||
<Radio value={1}>压缩上传</Radio>
|
||||
</Radio.Group>
|
||||
|
||||
{
|
||||
isCompressionUpload && <Select
|
||||
onChange={setQuality}
|
||||
options={[
|
||||
{ value: NaN, label: '自适应压缩(推荐)' },
|
||||
{ value: 1, label: '轻量压缩' },
|
||||
{ value: 0.9, label: '0.9' },
|
||||
{ value: 0.8, label: '0.8' },
|
||||
{ value: 0.7, label: '0.7' },
|
||||
{ value: 0.6, label: '0.6' },
|
||||
{ value: 0.5, label: '0.5' },
|
||||
{ value: 0.4, label: '0.4' },
|
||||
{ value: 0.3, label: '0.3' },
|
||||
{ value: 0.2, label: '0.2' },
|
||||
{ value: 0.1, label: '0.1' },
|
||||
]}
|
||||
placeholder="请选择图片压缩质量"
|
||||
className='min-w-44'
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<Dragger {...uploadProps}>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<InboxOutlined />
|
||||
@@ -56,5 +112,5 @@ export default ({ dir, open, onCancel, onSuccess }: UploadFileProps) => {
|
||||
</Dragger>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getSwiperListAPI, addSwiperDataAPI, editSwiperDataAPI, delSwiperDataAPI
|
||||
import { Swiper } from '@/types/app/swiper';
|
||||
import Title from '@/components/Title';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import { CloudUploadOutlined } from '@ant-design/icons';
|
||||
|
||||
const SwiperPage = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -14,13 +15,13 @@ const SwiperPage = () => {
|
||||
const [tab, setTab] = useState<string>('list');
|
||||
|
||||
const columns: ColumnsType<Swiper> = [
|
||||
{ title: 'ID', dataIndex: 'id', key: 'id' },
|
||||
{ title: 'ID', dataIndex: 'id', key: 'id', align: 'center' },
|
||||
{
|
||||
title: '图片', dataIndex: 'image', key: 'image', width: 200,
|
||||
render: (text: string) => <img src={text} alt="swiper" className="w-full rounded cursor-pointer" onClick={() => { setViewImage(text); setIsModelOpen(true) }} />
|
||||
},
|
||||
{ title: '标题', dataIndex: 'title', key: 'title' },
|
||||
{ title: '描述', dataIndex: 'description', key: 'description' },
|
||||
{ title: '描述', dataIndex: 'description', key: 'description', width: 500, },
|
||||
{
|
||||
title: '操作', key: 'action', align: 'center',
|
||||
render: (text: string, record: Swiper) => (
|
||||
@@ -84,6 +85,11 @@ const SwiperPage = () => {
|
||||
setSwiper({} as Swiper);
|
||||
};
|
||||
|
||||
// 文件上传
|
||||
const UploadBtn = () => (
|
||||
<CloudUploadOutlined className='text-xl cursor-pointer'/>
|
||||
)
|
||||
|
||||
const tabItems = [
|
||||
{
|
||||
label: '轮播图列表',
|
||||
@@ -131,7 +137,7 @@ const SwiperPage = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="图片" name="image" rules={[{ required: true, message: '轮播图不能为空' }]}>
|
||||
<Input placeholder="https://blog.liuyuyang.net/swiper.jpg" />
|
||||
<Input placeholder="https://blog.liuyuyang.net/swiper.jpg" addonAfter={<UploadBtn />} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
|
||||
Reference in New Issue
Block a user