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
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>
|