|
|
@@ -2,12 +2,12 @@
|
|
|
<section>
|
|
|
<el-upload
|
|
|
list-type="picture-card"
|
|
|
+ accept="image/*"
|
|
|
:action="uploadUrl"
|
|
|
- :headers="headers"
|
|
|
:on-preview="handlePictureCardPreview"
|
|
|
- :on-remove="handleRemove"
|
|
|
:on-success="handleSuccess"
|
|
|
- :file-list="fileList"
|
|
|
+ :on-remove="handleRemove"
|
|
|
+ v-model:file-list="fileList"
|
|
|
@before-upload="beforeUpload"
|
|
|
multiple
|
|
|
>
|
|
|
@@ -20,164 +20,93 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-upload>
|
|
|
- <el-dialog v-model="dialogVisible">
|
|
|
- <img width="100%" :src="dialogImageUrl" alt />
|
|
|
- </el-dialog>
|
|
|
- <el-image
|
|
|
- preview-teleported
|
|
|
- style="width: 0; height: 0; position: absolute"
|
|
|
- ref="preview"
|
|
|
- :src="previewUrl"
|
|
|
- :preview-src-list="previewList"
|
|
|
- >
|
|
|
- </el-image>
|
|
|
+ <ElImageViewer v-if="showPreview" :url-list="[previewUrl]" teleported @close="showPreview = false" />
|
|
|
</section>
|
|
|
</template>
|
|
|
-<script>
|
|
|
+<script setup>
|
|
|
import resolveUrl from 'resolve-url'
|
|
|
-export default {
|
|
|
- created() {
|
|
|
- this.uploadUrl = resolveUrl(this.$http.baseURL, 'upload/file')
|
|
|
- this.updateFileList(this.modelValue)
|
|
|
- },
|
|
|
- props: {
|
|
|
- modelValue: Array,
|
|
|
- usePrefix: {
|
|
|
- type: Boolean,
|
|
|
- default: true
|
|
|
- },
|
|
|
- url: {
|
|
|
- type: String
|
|
|
- },
|
|
|
- maxWidth: {
|
|
|
- type: Number,
|
|
|
- default: -1
|
|
|
- },
|
|
|
- maxHeight: {
|
|
|
- type: Number,
|
|
|
- default: -1
|
|
|
- },
|
|
|
- maxSize: {
|
|
|
- type: Number,
|
|
|
- default: 1024 * 1024
|
|
|
- }
|
|
|
+import { ref, watch } from 'vue'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import { Plus } from '@vicons/tabler'
|
|
|
+import { useImageSize } from '@/utils/imageSize'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: Array,
|
|
|
+ maxWidth: {
|
|
|
+ type: Number,
|
|
|
+ default: -1
|
|
|
},
|
|
|
- data() {
|
|
|
- return {
|
|
|
- dialogImageUrl: '',
|
|
|
- dialogVisible: false,
|
|
|
- fileList: [],
|
|
|
- uploadUrl: '',
|
|
|
- realFileList: [],
|
|
|
- previewUrl: '',
|
|
|
- previewList: []
|
|
|
- }
|
|
|
+ maxHeight: {
|
|
|
+ type: Number,
|
|
|
+ default: -1
|
|
|
},
|
|
|
- computed: {
|
|
|
- headers() {
|
|
|
- return {
|
|
|
- Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- handleRemove(file, fileList) {
|
|
|
- this.realFileList = fileList
|
|
|
- this.$emit(
|
|
|
- 'update:modelValue',
|
|
|
- fileList.map((i) => i.value)
|
|
|
- )
|
|
|
- },
|
|
|
- handlePictureCardPreview(file) {
|
|
|
- this.previewUrl = file.value
|
|
|
- this.previewList = this.fileList.map((i) => i.value)
|
|
|
- this.$refs.preview.showViewer = true
|
|
|
- },
|
|
|
- handleSuccess(res, file, fileList) {
|
|
|
- if (res instanceof Array) {
|
|
|
- file.value = res[0]
|
|
|
- } else {
|
|
|
- file.value = res
|
|
|
- }
|
|
|
- this.realFileList = fileList
|
|
|
- this.$emit(
|
|
|
- 'update:modelValue',
|
|
|
- fileList.map((i) => i.value)
|
|
|
- )
|
|
|
- },
|
|
|
- updateFileList(list) {
|
|
|
- if (!list) {
|
|
|
- list = []
|
|
|
- } else if (typeof list == 'string') {
|
|
|
- list = list.split(',')
|
|
|
- }
|
|
|
- for (let i = 0; i < list.length; i++) {
|
|
|
- if (!this.fileList[i]) {
|
|
|
- this.fileList[i] = {
|
|
|
- value: list[i],
|
|
|
- url: list[i]
|
|
|
- }
|
|
|
- } else if (this.fileList[i].value !== list[i]) {
|
|
|
- this.fileList[i] = {
|
|
|
- value: list[i],
|
|
|
- url: list[i]
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- this.fileList.splice(list.length)
|
|
|
- // this.fileList = list.map(i => {
|
|
|
- // return {
|
|
|
- // value: i,
|
|
|
- // url: i,
|
|
|
- // };
|
|
|
- // });
|
|
|
- },
|
|
|
- beforeUpload(file) {
|
|
|
- if (!/^image/.test(file.type)) {
|
|
|
- this.$message.error('只能上传图片格式!')
|
|
|
- return false
|
|
|
- }
|
|
|
- if (this.maxSize > 0 && file.size > this.maxSize) {
|
|
|
- this.$message.error('上传图片大小不能超过 ' + this.maxSize / 1024 + 'KB!')
|
|
|
- return false
|
|
|
- }
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- let image = document.createElement('img')
|
|
|
- image.onload = () => {
|
|
|
- resolve({
|
|
|
- width: image.width,
|
|
|
- height: image.height
|
|
|
- })
|
|
|
- }
|
|
|
- image.onerror = () => {
|
|
|
- this.$message.error('图片加载失败!')
|
|
|
- reject()
|
|
|
- }
|
|
|
- image.src = URL.createObjectURL(file)
|
|
|
- }).then((res) => {
|
|
|
- if (this.maxWidth > 0 && res.width > this.maxWidth) {
|
|
|
- this.$message.error('上传图片宽度不能超过 ' + this.maxWidth + 'px!')
|
|
|
- return Promise.reject()
|
|
|
- } else if (this.maxHeight > 0 && res.height > this.maxHeight) {
|
|
|
- this.$message.error('上传图片高度不能超过 ' + this.maxHeight + 'px!')
|
|
|
- return Promise.reject()
|
|
|
- } else {
|
|
|
- return Promise.resolve()
|
|
|
- }
|
|
|
- })
|
|
|
+ maxSize: {
|
|
|
+ type: Number,
|
|
|
+ default: 1024 * 1024
|
|
|
+ }
|
|
|
+})
|
|
|
+const emit = defineEmits(['update:modelValue'])
|
|
|
+const uploadUrl = resolveUrl(import.meta.env.VITE_API_BASE_URL, '/api/file/upload')
|
|
|
+const fileList = ref([])
|
|
|
+const loading = ref(false)
|
|
|
+const showPreview = ref(false)
|
|
|
+const previewUrl = ref(null)
|
|
|
+watch(
|
|
|
+ () => props.modelValue,
|
|
|
+ (val) => {
|
|
|
+ if (val.join() === fileList.value.map((i) => i.realUrl).join()) {
|
|
|
+ return
|
|
|
}
|
|
|
- },
|
|
|
- watch: {
|
|
|
- modelValue: {
|
|
|
- handler(val, oldVal) {
|
|
|
- if (JSON.stringify(val) == JSON.stringify(oldVal)) {
|
|
|
- return
|
|
|
- }
|
|
|
- this.updateFileList(val)
|
|
|
- },
|
|
|
- deep: true
|
|
|
+ updateFileList(val)
|
|
|
+ }
|
|
|
+)
|
|
|
+updateFileList(props.modelValue || [])
|
|
|
+function updateFileList(list) {
|
|
|
+ fileList.value = list.map((i) => {
|
|
|
+ return {
|
|
|
+ url: i,
|
|
|
+ realUrl: i
|
|
|
}
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+async function beforeUpload(file) {
|
|
|
+ if (!/^image/.test(file.type)) {
|
|
|
+ this.$message.error('只能上传图片格式!')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.maxSize > 0 && file.size > this.maxSize) {
|
|
|
+ this.$message.error('上传图片大小不能超过 ' + this.maxSize / 1024 + 'KB!')
|
|
|
+ return false
|
|
|
}
|
|
|
+ const { width, height } = await useImageSize(URL.createObjectURL(file))
|
|
|
+ if (props.maxWidth > 0 && width > props.maxWidth) {
|
|
|
+ this.$message.error('上传图片宽度不能超过 ' + props.maxWidth + 'px!')
|
|
|
+ return false
|
|
|
+ } else if (props.maxHeight > 0 && height > props.maxHeight) {
|
|
|
+ this.$message.error('上传图片高度不能超过 ' + props.maxHeight + 'px!')
|
|
|
+ return false
|
|
|
+ } else {
|
|
|
+ loading.value = true
|
|
|
+ return true
|
|
|
+ }
|
|
|
+}
|
|
|
+function handlePictureCardPreview(file) {
|
|
|
+ previewUrl.value = file.url || file.realUrl
|
|
|
+ showPreview.value = true
|
|
|
+}
|
|
|
+function handleSuccess(res, file, fileList) {
|
|
|
+ file.realUrl = res.url
|
|
|
+ emit(
|
|
|
+ 'update:modelValue',
|
|
|
+ fileList.map((i) => i.realUrl)
|
|
|
+ )
|
|
|
+}
|
|
|
+function handleRemove(file, fileList) {
|
|
|
+ emit(
|
|
|
+ 'update:modelValue',
|
|
|
+ fileList.map((i) => i.realUrl)
|
|
|
+ )
|
|
|
}
|
|
|
</script>
|
|
|
<style lang="less" scoped></style>
|