125 lines
3.8 KiB
Plaintext
125 lines
3.8 KiB
Plaintext
<template>
|
||
<!--
|
||
列表项:内部统一由组件库 xCell 渲染
|
||
对外保持本项目既有的 <hr-lrow icon theme title sub value …/> 用法,
|
||
这样 30+ 处列表无需逐个改造,且全站列表外观/交互由 xCell 统一保证。
|
||
-->
|
||
<x-cell :card="false" :margin="emptyMargin" :padding="cellPadding" :min-height="minHeight"
|
||
:show-bottom-border="!isLast" :bottom-border-insert="true" bottom-border-color="#F3F4F6" :title="title"
|
||
title-color="#1F2937" title-size="28rpx" :icon="resolvedIcon" :link="false" @click="onClick">
|
||
<!-- 左侧图标:彩色圆角块 + RemixIcon -->
|
||
<template v-slot:avatar>
|
||
<view class="hr-lrow-ic" :style="{ backgroundColor: tc.bg }">
|
||
<x-icon :name="resolvedIcon" :color="tc.color" font-size="32rpx"></x-icon>
|
||
</view>
|
||
</template>
|
||
|
||
<!--
|
||
标题走默认插槽自己渲染。
|
||
原因:库内 .title 写死 lines:2(且是 scoped 样式),全站列表希望标题只有一行、
|
||
超出省略号;用插槽把标题换成自己的元素,样式完全可控,不依赖 !important 覆盖。
|
||
-->
|
||
<template v-slot:default>
|
||
<text class="hr-lrow-t">{{ title }}</text>
|
||
</template>
|
||
|
||
<!-- 副标题 -->
|
||
<template v-slot:desc>
|
||
<text v-if="sub != ''" class="hr-lmain-s">{{ sub }}</text>
|
||
</template>
|
||
|
||
<!-- 右侧:自定义插槽 + 数值文本 -->
|
||
<template v-slot:right>
|
||
<slot name="right"></slot>
|
||
<text v-if="value != ''" class="hr-lval" :style="valueStyle">{{ value }}</text>
|
||
</template>
|
||
</x-cell>
|
||
</template>
|
||
|
||
<script lang="uts" setup>
|
||
import { computed } from 'vue'
|
||
import { toRemixIcon, themeColor, HrThemeColor } from '@/utils/icon.uts'
|
||
|
||
/**
|
||
* 列表行
|
||
* theme:default / pri / red / amb / grn —— 控制左侧图标底色
|
||
* valueTheme:t3(默认) / pri / red / amb / grn / t1
|
||
* icon 支持字符图标(设计稿沿用)或 RemixIcon 名,内部自动识别
|
||
*/
|
||
const props = defineProps({
|
||
icon : { type: String, default: '' },
|
||
theme : { type: String, default: 'default' },
|
||
title : { type: String, default: '' },
|
||
sub : { type: String, default: '' },
|
||
value : { type: String, default: '' },
|
||
valueTheme : { type: String, default: 't3' },
|
||
/** 右侧文字字号(rpx) */
|
||
valueSize : { type: String, default: '26rpx' },
|
||
/** 值是否加粗 */
|
||
valueBold : { type: Boolean, default: false },
|
||
/** 是否是最后一行(去除分隔线) */
|
||
isLast : { type: Boolean, default: false },
|
||
/** 是否是第一行 */
|
||
isFirst : { type: Boolean, default: false }
|
||
})
|
||
|
||
const emits = defineEmits<{
|
||
(e : 'click') : void
|
||
}>()
|
||
|
||
const resolvedIcon = computed(() : string => {
|
||
return toRemixIcon(props.icon)
|
||
})
|
||
|
||
const tc = computed(() : HrThemeColor => {
|
||
return themeColor(props.theme)
|
||
})
|
||
|
||
const emptyMargin = computed(() : string[] => {
|
||
return ['0', '0']
|
||
})
|
||
|
||
const cellPadding = computed(() : string[] => {
|
||
return props.isFirst ? ['20rpx', '0'] : ['24rpx', '0']
|
||
})
|
||
|
||
const minHeight = computed(() : string => {
|
||
return '112rpx'
|
||
})
|
||
|
||
const valueStyle = computed(() : string => {
|
||
let color = '#9CA3AF'
|
||
if (props.valueTheme == 'pri') { color = '#2563EB' }
|
||
if (props.valueTheme == 'red') { color = '#DC2626' }
|
||
if (props.valueTheme == 'amb') { color = '#D97706' }
|
||
if (props.valueTheme == 'grn') { color = '#059669' }
|
||
if (props.valueTheme == 't1') { color = '#1F2937' }
|
||
const weight = props.valueBold ? 'bold' : 'normal'
|
||
return `color:${color};font-size:${props.valueSize};font-weight:${weight};`
|
||
})
|
||
|
||
function onClick() : void {
|
||
emits('click')
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.hr-lrow-ic {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border-radius: 18rpx;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 列表行标题:单行显示,超出省略号 */
|
||
.hr-lrow-t {
|
||
font-size: 28rpx;
|
||
color: #1F2937;
|
||
lines: 1;
|
||
text-overflow: ellipsis;
|
||
}
|
||
</style>
|