You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
5.3 KiB
237 lines
5.3 KiB
<template> |
|
<view :class="rootClass" :style="rootStyle" @click="onClick"> |
|
<view :class="contentClass" :style="contentStyle"> |
|
<block v-if="$slots.default"> |
|
<slot /> |
|
</block> |
|
<block v-else> |
|
<view class="hd-grid-item-icon"> |
|
<hd-icon v-if="icon" :name="icon" :color="iconColor" :class-prefix="iconPrefix" :size="iconSize" /> |
|
<slot v-else name="icon"></slot> |
|
</view> |
|
<view class="hd-grid-item-text"> |
|
<text v-if="text">{{ text }}</text> |
|
<slot v-else name="text"></slot> |
|
</view> |
|
</block> |
|
</view> |
|
</view> |
|
</template> |
|
<script lang="ts" setup> |
|
import { computed, inject, onBeforeMount, ref, Ref } from 'vue' |
|
import { CommonUtil } from '../..' |
|
|
|
/** |
|
* GridItem 宫格布局项 |
|
*/ |
|
type LinkType = 'navigateTo' | 'redirectTo' | 'switchTab' | 'reLaunch' |
|
interface Props { |
|
// 图标名称或图片链接,可选值见 Icon 组件 |
|
icon?: string |
|
// 图标颜色 |
|
iconColor?: string |
|
// 第三方图标前缀 |
|
iconPrefix?: string |
|
// 文字 |
|
text?: string |
|
// 点击后跳转的链接地址 |
|
url?: string |
|
// 链接跳转类型,可选值为 redirectTo switchTab reLaunch |
|
linkType?: LinkType |
|
} |
|
|
|
const props = withDefaults(defineProps<Props>(), { |
|
iconPrefix: 'fant-icon', |
|
linkType: 'navigateTo' |
|
}) |
|
|
|
const grid: any = inject('$grid') |
|
const children: Ref<string[]> | undefined = inject('children') |
|
const uid = ref<string>(CommonUtil.s4() + Math.random()) |
|
|
|
onBeforeMount(() => { |
|
children && children.value && children.value.push(uid.value) |
|
}) |
|
|
|
/** |
|
* 文字字体大小 |
|
*/ |
|
const iconSize = computed(() => { |
|
const { iconSize } = grid |
|
return iconSize || '56rpx' |
|
}) |
|
/** |
|
* 最外层样式 |
|
*/ |
|
const rootStyle = computed(() => { |
|
const { columnNum, square, gutter } = grid |
|
const width = 100 / columnNum + '%' |
|
let index: number = -1 |
|
if (children && children.value && children.value.length) { |
|
index = children.value.indexOf(uid.value) |
|
} |
|
|
|
return CommonUtil.style({ |
|
width: width, |
|
'padding-top': square ? width : null, |
|
'padding-right': CommonUtil.addUnit(gutter), |
|
'margin-top': index >= columnNum && !square ? CommonUtil.addUnit(gutter) : null |
|
}) |
|
}) |
|
// 最外层类 |
|
const rootClass = computed(() => { |
|
const { square } = grid |
|
let rootClass = 'hd-grid-item' |
|
if (square) { |
|
rootClass = `${rootClass} hd-grid-item--square` |
|
} |
|
return rootClass |
|
}) |
|
/** |
|
* 内容样式 |
|
*/ |
|
const contentStyle = computed(() => { |
|
const { square, gutter } = grid |
|
return square |
|
? CommonUtil.style({ |
|
right: CommonUtil.addUnit(CommonUtil.getPx(gutter), 'px'), |
|
bottom: CommonUtil.addUnit(CommonUtil.getPx(gutter), 'px'), |
|
height: 'auto' |
|
}) |
|
: '' |
|
}) |
|
/** |
|
* 内容类 |
|
*/ |
|
const contentClass = computed(() => { |
|
const { direction, center, square, reverse, gutter, clickable, border } = grid |
|
const surround = border && gutter |
|
let contentClass = 'hd-grid-item-content' |
|
if (surround) { |
|
contentClass = `${contentClass} hd-grid-item-content--surround` |
|
} |
|
if (center) { |
|
contentClass = `${contentClass} hd-grid-item-content--center` |
|
} |
|
if (square) { |
|
contentClass = `${contentClass} hd-grid-item-content--square` |
|
} |
|
if (reverse) { |
|
contentClass = `${contentClass} hd-grid-item-content--reverse` |
|
} |
|
if (clickable) { |
|
contentClass = `${contentClass} hd-grid-item-content--clickable` |
|
} |
|
if (border) { |
|
contentClass = `${contentClass} hd-hairline--surround` |
|
} |
|
contentClass = `${contentClass} hd-grid-item-content--${direction}` |
|
return contentClass |
|
}) |
|
|
|
const emit = defineEmits(['click']) |
|
|
|
function onClick() { |
|
/** |
|
* 点击格子时触发 |
|
*/ |
|
emit('click') |
|
if (props.url) { |
|
if (props.linkType === 'navigateTo' && getCurrentPages().length > 9) { |
|
uni.redirectTo({ url: props.url }) |
|
} else { |
|
uni[props.linkType]({ url: props.url }) |
|
} |
|
} |
|
} |
|
</script> |
|
<style lang="scss" scoped> |
|
@import '../../libs/css/index.scss'; |
|
.hd-grid-item { |
|
position: relative; |
|
float: left; |
|
box-sizing: border-box; |
|
|
|
&--square { |
|
height: 0; |
|
} |
|
|
|
&-content { |
|
display: flex; |
|
flex-direction: column; |
|
box-sizing: border-box; |
|
height: 100%; |
|
padding: $grid-item-content-padding; |
|
background-color: $grid-item-content-background-color; |
|
|
|
&::after { |
|
z-index: 1; |
|
border-width: 0 $border-width-base $border-width-base 0; |
|
} |
|
|
|
&--surround { |
|
&::after { |
|
border-width: $border-width-base; |
|
} |
|
} |
|
|
|
&--center { |
|
align-items: center; |
|
justify-content: center; |
|
} |
|
|
|
&--square { |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
left: 0; |
|
} |
|
|
|
&--horizontal { |
|
flex-direction: row; |
|
|
|
.hd-grid-item-text { |
|
margin: 0 0 0 $padding-xs !important; |
|
} |
|
} |
|
|
|
&--reverse { |
|
flex-direction: column-reverse; |
|
|
|
.hd-grid-item-text { |
|
margin: 0 0 $padding-xs; |
|
} |
|
} |
|
|
|
&--horizontal, |
|
&--reverse { |
|
flex-direction: row-reverse; |
|
|
|
.hd-grid-item-text { |
|
margin: 0 $padding-xs 0 0; |
|
} |
|
} |
|
|
|
&--clickable:active { |
|
background-color: $grid-item-content-active-color; |
|
} |
|
} |
|
|
|
&-icon { |
|
display: flex; |
|
align-items: center; |
|
font-size: $grid-item-icon-size; |
|
height: $grid-item-icon-size; |
|
} |
|
|
|
&-text { |
|
word-wrap: break-word; |
|
color: $grid-item-text-color; |
|
font-size: $grid-item-text-font-size; |
|
} |
|
|
|
&-icon + &-text { |
|
margin-top: 8px; |
|
} |
|
} |
|
</style>
|
|
|