This commit is contained in:
2026-09-24 16:25:22 +08:00
commit 7428184f01
1198 changed files with 314515 additions and 0 deletions
@@ -0,0 +1,242 @@
<script lang="ts" setup>
import { ref, computed } from "vue"
import { getUid } from "../../core/util/xCoreUtil.uts"
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
import { checkIsCssUnit, getUnit } from "../../core/util/xCoreUtil.uts"
import { xConfig } from "../../config/xConfig.uts"
/**
* @name 图集 xImageGroup
* @description 主要是为了一些需要快速图片排版集的展示,比如评论图集,详情列表图集等,快速开发时使用。方便快捷。
* @page /pages/index/image-group
* @category 展示组件
* @constant 平台兼容
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
*/
defineOptions({name:"xImageGroup"})
const emits = defineEmits<{
/**
* 图片项目被点击
* @param item - 项目
*/
click: [item: UTSJSONObject]
}>()
type xImageGroupPropsType = {
/**
* 图片列表
* 只要包含有url字段即可。
* label需要在图片显示的文本字段,如果没有不要出现此字段
* 如果提供了temp缩略图,会优先展示temp字段,预览时采用url原图
* {url:string,label?:string,temp?:string}
*/
list: UTSJSONObject[],
/**
* 显示的模式见:https://doc.dcloud.net.cn/uni-app-x/component/image.html
*/
model: string,
/**
* 图片高,不要使用auto%
*/
height: string,
/**
* 图片宽,不要使用auto,可以%值
*/
width: string,
/**
* 间隙
*/
gutter: string,
/**
* inset表示文本在图片上
* ouuter表示文本在正文展示
* 不要动态修改
*/
labelModel: 'inset' | 'outter',
/**
* 如果有文字显示文字的大小
*/
labelFontSize: string,
/**
* 如果有文字,显示文字的颜色
*/
labelFontColor: string,
/**
* 如果有文字,显示文字的颜色,暗黑时为空时取白
*/
darkLabelFontColor: string,
/**
* 是否预览图片
*/
preview: boolean,
/**
* 圆角
*/
round: string
}
const props = withDefaults(defineProps<xImageGroupPropsType>(), {
list: ():UTSJSONObject[] => [] as UTSJSONObject[],
model: "scaleToFill",
height: "100",
width: "33.33%",
gutter: "2",
labelModel: "inset",
labelFontSize: "14",
labelFontColor: "white",
darkLabelFontColor: "",
preview: true,
round: "0"
})
// 计算属性
const _list = computed((): UTSJSONObject[] => {
return props.list
})
const _labelFontColor = computed((): string => {
if (xConfig.dark == 'dark') {
if (props.darkLabelFontColor != '') return getDefaultColor(props.darkLabelFontColor)
return "#ffffff"
}
return getDefaultColor(props.labelFontColor)
})
const _gutter = computed((): string => {
return checkIsCssUnit(props.gutter, xConfig.unit)
})
const _labelFontSize = computed((): string => {
let fontSize = checkIsCssUnit(props.labelFontSize, xConfig.unit);
if (xConfig.fontScale == 1) return fontSize;
let sizeNumber = parseInt(fontSize)
if (isNaN(sizeNumber)) {
sizeNumber = 14
}
return (sizeNumber * xConfig.fontScale).toString() + getUnit(fontSize)
})
const _width = computed((): string => {
return checkIsCssUnit(props.width, xConfig.unit)
})
const _height = computed((): string => {
return checkIsCssUnit(props.height, xConfig.unit)
})
const _round = computed((): string => {
return checkIsCssUnit(props.round, xConfig.unit)
})
// 方法
function showUrlList(item: UTSJSONObject): string {
let url = item.getString('url');
url = url == null ? '' : url
let temp = item.getString('temp');
if (temp != null) return temp;
return url;
}
function showLabel(item: UTSJSONObject): string {
let label = item.getString('label');
label = label == null ? '' : label
return label;
}
function onClick(item: UTSJSONObject, index: number): void {
let url = item.getString('url');
url = url == null ? '' : url
let listurl = _list.value.map((el: UTSJSONObject): string => {
let temurl = el.getString('url');
temurl = temurl == null ? '' : temurl
return temurl;
})
if (props.preview) {
uni.previewImage({
current: url,
urls: listurl as string[]
})
}
emits('click', item)
}
</script>
<template>
<view class="xImageGroup">
<view @click="onClick(item,index)" v-for="(item,index) in _list" :key="index" class="xImageGroupWrap"
:style="{padding:_gutter,width:_width,height:_height,borderRadius:_round}">
<view class="xImageGroupWrapBox">
<x-image :round="_round" :ratio="1" width="100%" height="100%" style="height: 100%;width:100%" :model="props.model" :preview="false" :src="showUrlList(item)"></x-image>
</view>
<!-- margin:labelModel=='inset'?_gutter:'0px' -->
<view v-if="showLabel(item)!=''" class="xImageGroupLabelBox" :style="{
position:props.labelModel=='inset'?'absolute':'static',
}">
<view class="xImageGroupLabelBoxPadding" :style="{
margin:props.labelModel=='inset'?_gutter:'0px',
padding: props.labelModel=='inset'?'20rpx':'20rpx 0px',
borderRadius:_round,
'background-image': props.labelModel=='inset'?'linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,0.9))':''
}">
<text :style="{fontSize:_labelFontSize,color:_labelFontColor}"
class="xImageGroupLabelLabel">{{showLabel(item)}}</text>
</view>
</view>
</view>
</view>
</template>
<style scoped>
.xImageGroupLabelBox {
z-index: 2;
left: 0px;
bottom: 0px;
pointer-events: none;
width: 100%;
/* #ifdef MP || WEB */
box-sizing: border-box;
/* #endif */
}
.xImageGroupLabelBoxPadding {
/* background-image: linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,0.9)); */
}
.xImageGroupLabelLabel {
/* color:white; */
lines: 1;
/* #ifdef WEB */
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
/* #endif */
}
.xImageGroupWrap {
display: flex;
flex-direction: column;
align-items: stretch;
position: relative;
/* #ifdef MP || WEB */
box-sizing: border-box;
/* #endif */
}
.xImageGroupWrapBox {
flex: 1;
pointer-events: none;
}
.xImageGroup {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
}
</style>