feat: 添加图片裁剪组件
This commit is contained in:
parent
bb62983d6e
commit
b3e10b1781
|
@ -41,6 +41,7 @@
|
|||
"v-clipboard3": "^0.1.4",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vue": "^3.2.45",
|
||||
"vue-cropper": "^1.0.9",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue3-json-viewer": "^2.2.2",
|
||||
|
|
|
@ -34,4 +34,6 @@ export const systemVersion = () => server.get<{edition?: string}>('/system/versi
|
|||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const queryDashboard = (data: Record<string, any>) => server.post(`/dashboard/_multi`, data)
|
||||
export const queryDashboard = (data: Record<string, any>) => server.post(`/dashboard/_multi`, data)
|
||||
|
||||
export const fileUpload = (data: any) => server.post('/file/static', data)
|
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<j-modal
|
||||
title="图片编辑"
|
||||
visible
|
||||
:width="400"
|
||||
@cancel="cancel"
|
||||
@ok="ok"
|
||||
:confirmLoading="loading"
|
||||
>
|
||||
<div style="height: 300px; width: 100%;">
|
||||
<vue-cropper
|
||||
ref="cropper"
|
||||
:img="img"
|
||||
:fixed-box="true"
|
||||
:autoCrop="true"
|
||||
:auto-crop-width="200"
|
||||
:auto-crop-height="200"
|
||||
outputType="jpg"
|
||||
></vue-cropper>
|
||||
</div>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="UploadCropper">
|
||||
import 'vue-cropper/dist/index.css'
|
||||
import { VueCropper } from 'vue-cropper';
|
||||
import { fileUpload } from '@/api/comm';
|
||||
|
||||
const props = defineProps({
|
||||
img: {
|
||||
type: String
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['cancel', 'ok'])
|
||||
|
||||
const imgUrl = ref()
|
||||
const cropper = ref()
|
||||
const loading = ref(false)
|
||||
|
||||
const ok = () => {
|
||||
cropper.value.getCropBlob(async (data: Blob) => {
|
||||
console.log(data)
|
||||
let formData = new FormData()
|
||||
formData.append('file', data, new Date().getTime() + '.jpg')
|
||||
|
||||
imgUrl.value = data
|
||||
loading.value = true
|
||||
fileUpload(formData).then(res => {
|
||||
if (res.success) {
|
||||
emit('ok', res.result)
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -16,12 +16,6 @@
|
|||
>
|
||||
<div class="upload-image-content" :style="props.style">
|
||||
<template v-if="imageUrl">
|
||||
<!-- <div class="upload-image"
|
||||
:style="{
|
||||
backgroundSize: props.backgroundSize,
|
||||
backgroundImage: `url(${imageUrl})`
|
||||
}"
|
||||
></div> -->
|
||||
<img :src="imageUrl" class="upload-image" />
|
||||
<div class="upload-image-mask">点击修改</div>
|
||||
</template>
|
||||
|
@ -52,6 +46,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ImageCropper
|
||||
v-if="cropperVisible"
|
||||
:img="cropperImg"
|
||||
@cancel="cropperVisible = false"
|
||||
@ok="saveImage"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name='JProUpload'>
|
||||
|
@ -59,8 +59,9 @@ import { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
|||
import { message } from 'jetlinks-ui-components';
|
||||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import {getBase64, LocalStore} from '@/utils/comm';
|
||||
import { CSSProperties } from 'vue';
|
||||
import ImageCropper from './Cropper.vue'
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: string): void;
|
||||
|
@ -100,6 +101,9 @@ const loading = ref<boolean>(false);
|
|||
const imageUrl = ref<string>(props?.modelValue || '');
|
||||
const imageTypes = props.types ? props.types : ['image/jpeg', 'image/png'];
|
||||
|
||||
const cropperImg = ref()
|
||||
const cropperVisible = ref(false)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
|
@ -129,6 +133,7 @@ const handleChange = (info: UploadChangeParam) => {
|
|||
|
||||
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||
const isType = imageTypes.includes(file.type);
|
||||
const maxSize = props.size || 4
|
||||
if (!isType) {
|
||||
if (props.errorMessage) {
|
||||
message.error(props.errorMessage);
|
||||
|
@ -137,12 +142,25 @@ const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
const isSize = file.size / 1024 / 1024 < (props.size || 4);
|
||||
const isSize = file.size / 1024 / 1024 < maxSize;
|
||||
if (!isSize) {
|
||||
message.error(`图片大小必须小于${props.size || 4}M`);
|
||||
message.error(`图片大小必须小于${maxSize}M`);
|
||||
}
|
||||
return isType && isSize;
|
||||
|
||||
getBase64(file, (base64Url) => {
|
||||
cropperImg.value = base64Url
|
||||
cropperVisible.value = true
|
||||
})
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
const saveImage = (url: string) => {
|
||||
cropperVisible.value = false
|
||||
imageUrl.value = url
|
||||
emit('update:modelValue', url);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -174,4 +174,14 @@ export const openKeysByTree = (data: any[], search: any, searchKey: string = 'id
|
|||
|
||||
findKey(filterTree)
|
||||
return openKeys
|
||||
}
|
||||
|
||||
export const getBase64 = (img: File, callback: (base64Url: string) => void) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(img);
|
||||
|
||||
reader.onload = (result: any) => {
|
||||
console.log(result)
|
||||
callback(result.target.result)
|
||||
}
|
||||
}
|
|
@ -6945,6 +6945,11 @@ vite@^4.0.0:
|
|||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vue-cropper@^1.0.9:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.jetlinks.cn/vue-cropper/-/vue-cropper-1.0.9.tgz#de402c57cadc221e9a2063399ff35bb04220ef22"
|
||||
integrity sha512-JhQwxmjqmQohzI7sAp5O/Rfdxuw5HOEYkKjnp/De7iCi6c8Mv6M3N9HpMt9xgWCFchX3/DfXBv2axCZOCg3G8Q==
|
||||
|
||||
vue-demi@*:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz"
|
||||
|
|
Loading…
Reference in New Issue