This commit is contained in:
2026-01-05 12:47:14 +08:00
commit 1fc846fae3
1614 changed files with 162035 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
import type { ExtractPropTypes } from 'vue'
import { CLICK_EVENT } from '../_constants'
import { commonProps } from '../_utils'
export const gridItemProps = {
...commonProps,
/**
* @description 文字
*/
text: String,
/**
* @description 点击后跳转的目标路由对象,同 vue-router 的 to 属性
*/
to: [String, Object],
/**
* @description 点击后跳转的链接地址
*/
url: String,
/**
* @description 是否在跳转时替换当前页面历史
*/
replace: Boolean,
background: String
}
export type GridItemProps = ExtractPropTypes<typeof gridItemProps>
export const gridItemEmits = {
[CLICK_EVENT]: (evt: MouseEvent) => evt instanceof Object,
}
export type GridItemEmits = typeof gridItemEmits

View File

@@ -0,0 +1,107 @@
<script setup lang="ts">
import type { CSSProperties } from 'vue'
import { computed, defineComponent } from 'vue'
import { CLICK_EVENT, PREFIX } from '../_constants'
import { useInject, useRouter } from '../_hooks'
import { getMainClass, getMainStyle, pxCheck } from '../_utils'
import type { GridProps } from '../grid'
import { GRID_KEY } from '../grid'
import { gridItemEmits, gridItemProps } from './griditem'
const props = defineProps(gridItemProps)
const emit = defineEmits(gridItemEmits)
const componentName = `${PREFIX}-grid-item`
const Parent = useInject<{ props: Required<GridProps> }>(GRID_KEY)
const index = Parent.index
const parent = Parent?.parent?.props
// root
const classes = computed(() => {
return getMainClass(props, componentName)
})
const styles = computed(() => {
if (!parent)
return
const style: CSSProperties = {
flexBasis: `${100 / +parent.columnNum}%`,
}
if (parent?.square) {
style.paddingTop = `${100 / +parent.columnNum}%`
}
else if (parent.gutter) {
style.paddingRight = pxCheck(parent.gutter)
if (index.value >= Number(parent.columnNum))
style.marginTop = pxCheck(parent.gutter)
}
return getMainStyle(props, style)
})
// content
const contentClass = computed(() => {
if (!parent)
return
const prefixCls = `${componentName}__content`
return {
[`${prefixCls}`]: true,
[`${prefixCls}--border`]: parent.border,
[`${prefixCls}--surround`]: parent.border && parent.gutter,
[`${prefixCls}--center`]: parent.center,
[`${prefixCls}--square`]: parent.square,
[`${prefixCls}--reverse`]: parent.reverse,
[`${prefixCls}--${parent.direction}`]: !!parent.direction,
[`${prefixCls}--clickable`]: parent.clickable,
}
})
// click
const router = useRouter()
function handleClick(event: unknown) {
emit(CLICK_EVENT, event as MouseEvent)
if (props.to && router) {
router[props.replace ? 'replace' : 'push'](props.to as string)
// #ifdef H5
}
else if (props.url) {
if (props.replace)
window.location.replace(props.url)
else
window.location.href = props.url
// #endif
}
}
</script>
<script lang="ts">
export default defineComponent({
name: 'NutGridItem',
options: {
virtualHost: true,
addGlobalClass: true,
styleIsolation: 'shared',
},
})
</script>
<template>
<view :class="classes" :style="styles" @click="handleClick">
<view :class="contentClass" :style="props.background ? {background:props.background} : {}">
<slot />
<view class="nut-grid-item__text">
<template v-if="text">
{{ text }}
</template>
<slot v-else name="text" />
</view>
</view>
</view>
</template>
<style lang="scss">
@import './index';
</style>

View File

@@ -0,0 +1,107 @@
.nut-theme-dark {
.nut-grid-item {
&__content {
color: $dark-color;
background: $dark-background;
border: 0 solid $dark-background2;
}
&__text {
color: $dark-color;
}
}
}
.nut-grid-item {
position: relative;
box-sizing: border-box;
$block: &;
&__text {
margin: $grid-item-text-margin 0 0 0;
font-size: $grid-item-text-font-size;
line-height: 1.5;
color: $grid-item-text-color;
word-break: break-all;
}
&__content {
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
padding: $grid-item-content-padding;
background: $grid-item-content-bg-color;
border: 0 solid $grid-border-color;
&--border {
border-right-width: 1px;
border-bottom-width: 1px;
}
&--surround {
border-top-width: 1px;
border-left-width: 1px;
}
&--center {
align-items: center;
justify-content: center;
}
&--square {
position: absolute;
top: 0;
right: 0;
left: 0;
}
&--reverse {
flex-direction: column-reverse;
#{$block}__text {
margin: 0 0 $grid-item-text-margin;
}
}
&--horizontal {
flex-direction: row;
#{$block}__text {
margin: 0 0 0 $grid-item-text-margin;
}
}
&--horizontal#{&}--reverse {
flex-direction: row-reverse;
#{$block}__text {
margin: 0 $grid-item-text-margin 0 0;
}
}
&--clickable {
cursor: pointer;
&::before {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
content: "";
background-color: $black;
border: inherit;
border-color: $black;
border-radius: inherit;
opacity: 0;
transform: translate(-50%, -50%);
}
&:active::before {
opacity: 0.1;
}
}
}
}

View File

@@ -0,0 +1 @@
export * from './griditem'