货无忧
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.

300 lines
6.6 KiB

2 years ago
<template>
<view :class="rootClass" :hover-class="hoverClass" data-eventsync="true" hover-stay-time="70" @click="onClick">
<view class="hd-cell-left-icon" v-if="icon">
<hd-icon size="36rpx" color="#A1A1A1" :name="icon"></hd-icon>
</view>
<view :class="['hd-cell-title', required ? 'hd-cell-title--required' : '']" v-if="title">
<text class="hd-cell-title-txt">
{{ title }}
</text>
<view class="hd-cell-title-label" v-if="label">{{ label }}</view>
</view>
<view v-if="(value && value.length > 0) || $slots.value" :class="['hd-cell-value', !isLink ? 'hd-cell-value--noicon' : '']" :style="valueStyle">
<template v-if="$slots.value">
<!-- 自定义单元格内容 -->
<slot name="value"></slot>
</template>
<view v-else class="hd-cell-value-txt" :style="valueTextStyle">
{{ value }}
</view>
</view>
<view v-else :class="['hd-cell-placeholder', !isLink ? 'hd-cell-placeholder--noicon' : '']">
<view class="hd-cell-placeholder-txt" :style="placeholderStyle">{{ placeholder }}</view>
</view>
<view class="hd-cell-right-icon" v-if="isLink">
<hd-icon size="32rpx" color="#A1A1A1" name="ic_arrowright_line"></hd-icon>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { CommonUtil } from '../..'
type CellAlign = 'left' | 'right'
interface Props {
// 左侧图标名称,等同于 `Icon` 组件的 name 属性
icon?: string
// 左侧标题
title: string
// 右侧内容
value: string
// 标题下方的描述信息
label: string
// 右侧内容的对齐方式,可选值为 "left" | "right"
align?: CellAlign
// 是否展示右侧箭头并开启点击反馈
isLink?: boolean
// 是否开启点击反馈
clickable?: boolean
// 是否有下划线
hasLine?: boolean
// 是否超出省略
ellipsis?: boolean
// 占位文字
placeholder?: string
// 是否显示表单必填星号
required?: boolean
}
let props = withDefaults(defineProps<Props>(), {
// 左侧图标名称,等同于 `Icon` 组件的 name 属性
icon: '',
// 左侧标题
title: '',
// 右侧内容
value: '',
// 标题下方的描述信息
label: '',
// 右侧内容的对齐方式,可选值为 "left" | "right"
align: 'left',
// 是否为链接
isLink: false,
// 是否展示右侧箭头并开启点击反馈
clickable: false,
// 是否有下划线
hasLine: false,
// 是否超出省略
ellipsis: true,
// 占位文字
placeholder: '',
// 是否显示表单必填星号
required: false
})
/**
* 根节点类
*/
const rootClass = computed(() => {
const rootClass = ['hd-cell']
if (props.isLink || props.clickable) {
rootClass.push('hd-cell--clickable')
}
if (props.hasLine) {
rootClass.push('hd-cell--hasline')
}
return rootClass
})
/**
* 点击样式类
*/
const hoverClass = computed(() => {
let hoverClass = ''
if (props.isLink || props.clickable) {
hoverClass = 'hd-cell--active'
}
return hoverClass
})
/**
* 单元格右侧值样式
*/
const valueStyle = computed(() => {
const style = {
overflow: props.ellipsis ? 'hidden' : 'overlay',
'text-overflow': props.ellipsis ? 'ellipsis' : '',
'white-space': props.ellipsis ? 'nowrap' : ''
}
return CommonUtil.style(style)
})
/**
* 单元格右侧文字样式
*/
const valueTextStyle = computed(() => {
const style = {
overflow: props.ellipsis ? 'hidden' : 'overlay',
'text-overflow': props.ellipsis ? 'ellipsis' : '',
'white-space': props.ellipsis ? 'nowrap' : '',
'text-align': props.align
}
return CommonUtil.style(style)
})
/**
* 单元格右侧文字样式
*/
const placeholderStyle = computed(() => {
const style = {
'text-align': props.align
}
return CommonUtil.style(style)
})
const emit = defineEmits(['click'])
// 点击单元格事件
function onClick() {
emit('click')
}
// Cell 单元格
</script>
<style lang="scss" scoped>
@import '../../libs/css/index.scss';
.hd-cell {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 22rpx 24rpx;
background: rgba(255, 255, 255, 1);
display: flex;
flex-direction: row;
// 可以点击
&--clickable {
cursor: pointer;
}
// 被点击的样式
&--active {
background-color: #f2f3f5;
}
// 单元格分割线
&--hasline:not(:last-child)::after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 20rpx;
width: calc(100% - 40rpx);
border-bottom: 2rpx solid #eeeeee;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
// 标题
&-title {
min-width: 160rpx;
max-width: 160rpx;
margin-right: 16rpx;
font-size: 26rpx;
line-height: 44rpx;
&--required::before {
margin-right: 2px;
color: $color-error;
content: '*';
}
&-txt {
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #282c34;
}
&-label {
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: $color-text-fourth;
line-height: 32rpx;
margin-top: 8rpx;
}
}
// 内容
&-value {
min-width: 378rpx;
flex: 1 1 auto;
&-txt {
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #585a5e;
line-height: 44rpx;
}
//无右图标时value的长度
&--noicon {
width: 410rpx;
}
}
// 占位
&-placeholder {
min-width: 378rpx;
flex: 1 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
//无右图标时value的长度
&--noicon {
width: 410rpx;
}
&-txt {
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #cccccc;
line-height: 44rpx;
}
}
// 左侧图标
&-left-icon {
height: 44rpx;
width: 52rpx;
text-align: left;
display: flex;
flex-direction: column;
justify-content: center;
}
// 右侧图标
&-right-icon {
height: 44rpx;
width: 32rpx;
display: flex;
flex-direction: column;
justify-content: center;
image {
width: 32rpx;
height: 32rpx;
}
}
}
// #ifdef MP-WEIXIN
hd-cell:not(:last-child) {
.hd-cell--hasline::after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
bottom: 0;
left: 20rpx;
width: calc(100% - 40rpx);
border-bottom: 2rpx solid #eeeeee;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
// #endif
</style>