<template>
<view class="image-group">
<view class="image-group-list">
<view class="image-group-title">
{{ title }}
</view>
<uni-file-picker
ref="filepicker"
:model-value="images"
class="image-group-picker"
:source-type="sourceType"
:auto-upload="false"
:limit="limit"
@select="mentouSelect"
@delete="deleteImg"
>
<view class="add">
<view class="content-icon">
<uni-icons
type="plus"
size="40"
color="#C8E3E3"
/>
</view>
<view class="content-placeholder">
{{ defaultPlaceholder }}
</view>
</view>
</uni-file-picker>
</view>
</view>
</template>
```js
<script>
import global from '@/services/global'
import storage from '@/services/storage'
export default {
name: 'FormImageGroup',
props: {
value: {
type: Array,
default: () => ([])
},
title: {
type: String,
default: ''
},
limit: {
type: Number,
default: 1
}
},
emits: ['update:value'],
data: () => ({
images: [],
sourceType: ['album', 'camera']
}),
computed: {
defaultPlaceholder () {
return this.$t('global.image.placeholder')
}
},
watch: {
value (newVal, oldVal) {
if (newVal !== oldVal) {
this.initialImages(newVal)
}
}
},
mounted () {
this.initialImages(this.value)
},
methods: {
initialImages (images) {
if (!images) {
this.images = []
return
}
this.images = images.map((item) => {
return {
name: item.name,
extname: item.extname,
url: item.url,
id: item.id
}
})
},
async mentouSelect (e) {
this.propsValueExecuteOrRun = false
if (e.tempFilePaths && e.tempFiles) {
const files = e.tempFiles.map((file) => ({
name: 'attachments',
uri: file.path
}))
try {
const promises = []
for (let i = 0; i < files.length; i++) {
const promise = this.toUpload(files[i], this.images.length + i)
promises.push(promise)
}
await Promise.all(promises)
} catch (error) {
console.error('error', error)
uni.showToast({ icon: 'error' })
}
}
},
async toUpload (file, index) {
const formData = {}
this.$refs.filepicker.setProgress({ loaded: 25, total: 100 }, index, true)
return new Promise((resolve, reject) => {
uni.uploadFile({
url: `${global.apiHost}/v1.0/attachments`,
files: [file],
fileType: 'image',
formData: { ...formData },
header: {
'X-Csrf-Token': storage.getToken()
},
timeout: 60000,
success: uploadFileRes => {
const attachment = JSON.parse(uploadFileRes.data).data[0]
const newImages = this.images
const newImage = {
name: file.name,
extname: file.type,
url: file.uri,
id: attachment.id
}
newImages.push(newImage)
this.$emit('update:value', newImages)
this.$refs.filepicker.setProgress({ loaded: 90, total: 100 }, index, true)
return resolve(newImages)
},
fail (error) {
console.error(error)
return reject(error)
}
})
})
},
deleteImg (e) {
const newImages = this.images.filter((image) => {
return image.url !== e.tempFilePath
})
this.$emit('update:value', newImages)
}
}
}
</script>
```css
<style lang="scss" scoped>
.image-group-list .image-group-picker ::v-deep .uni-file-picker {
min-width: calc(100% - 24px);
}
.image-group{
margin:0 px2rpx(20px);
}
.image-group-list{
position: relative;
margin-top: px2rpx(16px);
}
.image-group-title{
width: px2rpx(148px);
margin-left: px2rpx(22px);
flex: 1;
box-sizing: border-box;
color: #172727;
font-size: 13px;
font-weight: 500;
line-height: px2rpx(23px);
display: inline-block;
vertical-align: middle;
text-align: center;
}
.image-group-picker{
position: relative;
}
.image-group-list .image-group-picker ::v-deep .uni-file-picker__container{
margin: 0;
justify-content: space-between;
margin-right: 13px;
padding: 0 10px;
flex-wrap: wrap;
}
.image-group-list .image-group-picker ::v-deep .uni-file-picker__container .file-picker__box{
width: 45% !important;
padding-top: 52%;
}
.image-group-list .image-group-picker ::v-deep .uni-file-picker__container .file-picker__box .is-add{
background-color: pink;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
width: px2rpx(158px);
height: px2rpx(158px);
background: #fff;
overflow: hidden;
border-radius: px2rpx(24px) !important;
border: px2rpx(1px) solid #c8e3e3 !important;
}
.image-group-list .image-group-picker ::v-deep .is-add .icon-add {
display: none;
margin-top: 0;
}
.image-group-list .image-group-picker ::v-deep .file-picker__box-content{
width: px2rpx(158px);
height: px2rpx(158px);
border-radius: px2rpx(24px) !important;
}
.image-group-list .image-group-picker ::v-deep .file-picker__box-content .icon-del-box{
display: block;
width: px2rpx(30px);
height: px2rpx(30px);
background: url("/static/images/icon/delete.png") no-repeat center;
background-size: cover;
transform: none;
z-index: 0;
}
.image-group-list .image-group-picker ::v-deep .file-picker__box-content .icon-del-box .icon-del{
display: none;
}
.add{
position: absolute;
display: inline-block;
.content-icon {
width: 100%;
height: px2rpx(40px);
display: flex;
align-items: center;
justify-content: center;
}
.content-placeholder {
color: #172727;
font-size: 12px;
font-weight: 400;
line-height: px2rpx(30px);
text-align: center;
opacity: 0.3;
}
}
.image-group-list .image-group-picker ::v-deep .uni-progress-bar .uni-progress-inner-bar{
background-color: #CDE162 !important;
}
</style>
这是整个页面的代码