<template>
	<view class="img-grid">
		<text v-if="label" class="img-grid__label">{{ label }}</text>
		<view class="img-grid__list">
			<view v-for="(url, index) in modelValue" :key="index" class="img-grid__item">
				<image class="img-grid__pic" :src="displayUrl(url)" mode="aspectFill" />
				<view class="img-grid__del" @click="removeAt(index)">×</view>
			</view>
			<view
				v-if="modelValue.length < max"
				class="img-grid__add"
				@click="chooseImages"
			>
				<u-icon name="camera-fill" color="#9a938c" size="36" />
				<text class="img-grid__tip">{{ uploading ? '上传中' : '添加图片' }}</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref } from 'vue'
import { joinApiUrl } from '@/config'
import { uploadFile } from '@/utils/upload'

const props = defineProps({
	modelValue: {
		type: Array,
		default: () => []
	},
	label: {
		type: String,
		default: ''
	},
	max: {
		type: Number,
		default: 9
	}
})

const emit = defineEmits(['update:modelValue'])

const uploading = ref(false)

function displayUrl(url) {
	if (!url) return ''
	if (/^https?:\/\//i.test(url)) return url
	return joinApiUrl(url)
}

function removeAt(index) {
	const next = [...props.modelValue]
	next.splice(index, 1)
	emit('update:modelValue', next)
}

function chooseImages() {
	if (uploading.value) return
	const left = props.max - props.modelValue.length
	if (left <= 0) return
	uni.chooseImage({
		count: left,
		sizeType: ['compressed'],
		success: async (res) => {
			const paths = res.tempFilePaths || []
			if (!paths.length) return
			uploading.value = true
			const uploaded = [...props.modelValue]
			try {
				for (const path of paths) {
					if (uploaded.length >= props.max) break
					const url = await uploadFile(path)
					uploaded.push(url)
				}
				emit('update:modelValue', uploaded)
			} catch (e) {
				uni.showToast({ title: (e && e.message) || '上传失败', icon: 'none' })
			} finally {
				uploading.value = false
			}
		}
	})
}
</script>

<style lang="scss" scoped>
.img-grid {
	padding: 16rpx 0;
}
.img-grid__label {
	display: block;
	margin-bottom: 12rpx;
	font-size: 28rpx;
	color: #333;
}
.img-grid__list {
	display: flex;
	flex-wrap: wrap;
	gap: 16rpx;
}
.img-grid__item,
.img-grid__add {
	position: relative;
	width: 160rpx;
	height: 160rpx;
	border-radius: 12rpx;
	overflow: hidden;
}
.img-grid__pic {
	width: 100%;
	height: 100%;
	background: #eee;
}
.img-grid__del {
	position: absolute;
	top: 0;
	right: 0;
	width: 40rpx;
	height: 40rpx;
	line-height: 36rpx;
	text-align: center;
	background: rgba(0, 0, 0, 0.5);
	color: #fff;
	font-size: 28rpx;
}
.img-grid__add {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8rpx;
	background: #f5f2ef;
	border: 1rpx dashed #ddd;
}
.img-grid__tip {
	font-size: 22rpx;
	color: #9a938c;
}
</style>
