| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- <template>
- <view class="image-grid-container">
- <view class="image-grid" :class="`count-${Math.min(images.length, 9)}`">
- <view
- v-for="(image, index) in showImages"
- :key="index"
- class="image-item"
- :style="getItemStyle(index)"
- >
- <image
- mode="heightFix"
- :src="image"
- class="image-content"
- lazy-load
- @click.stop="previewImage(index)"
- />
- </view>
- </view>
- </view>
- </template>
- <script setup>
- import { defineProps, computed } from "vue";
- const props = defineProps({
- images: {
- type: Array,
- required: true,
- default: () => [],
- },
- spacing: {
- type: Number,
- default: 8,
- },
- maxShow: {
- type: Number,
- default: 9, // 最多显示几张
- },
- isSeeLarge: {
- type: Boolean,
- default: false,
- },
- });
- const showImages = computed(() => {
- return props.images.slice(0, props.maxShow);
- });
- const previewImage = (index) => {
- if (props.isSeeLarge) {
- uni.previewImage({
- current: index,
- urls: props.images,
- indicator: "number",
- loop: true,
- });
- }
- };
- const getItemStyle = (index) => {
- const count = Math.min(props.images.length, 3);
- let style = {};
- if (count === 1) {
- style.width = "100%";
- style.paddingTop = "56.25%"; // 16:9比例
- } else {
- style.width = `calc(${100 / count}% - ${
- (props.spacing * (count - 1)) / count
- }px)`;
- style.paddingTop = style.width;
- }
- if (index % count !== count - 1) {
- style.marginRight = `${props.spacing}px`;
- }
- return style;
- };
- </script>
- <style lang="less" scoped>
- .image-grid-container {
- width: 100%;
- margin-bottom: 12px;
- .image-grid {
- display: flex;
- flex-wrap: wrap;
- width: 100%;
- .image-item {
- position: relative;
- overflow: hidden;
- border-radius: 16rpx;
- margin-bottom: v-bind('props.spacing + "px"');
- .image-content {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- object-fit: cover;
- transition: transform 0.2s ease;
- &:active {
- transform: scale(0.98);
- }
- }
- .image-more {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: rgba(0, 0, 0, 0.5);
- color: white;
- font-size: 24px;
- font-weight: bold;
- }
- }
- // 特殊处理只有一张图片的情况
- &.count-1 .image-item {
- border-radius: 12px;
- }
- }
- }
- ::v-deep .uni-preview-image {
- z-index: 999999 !important;
- }
- </style>
|