| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- <template>
- <Touchable
- direction="row"
- :touchable="touchable || Boolean($attrs['onClick'])"
- :pressedColor="pressedColor"
- :innerStyle="{
- ...viewStyle,
- ...style,
- }"
- :flex="1"
- :align="center ? 'center' : 'flex-start'"
- justify="space-between"
- @click="handleClick"
- >
- <slot>
- <FlexRow key="left" :flexShrink="1" center>
- <slot name="left">
- <FlexRow
- key="leftIcon"
- :width="(iconPlaceholder || icon) ? iconWidth : 0"
- center
- >
- <slot name="leftIcon">
- <Icon
- v-if="icon"
- key="leftIcon"
- :icon="icon"
- :size="iconSize"
- v-bind="iconProps"
- :innerStyle="{
- ...titleStyle,
- ...iconStyle,
- }"
- />
- </slot>
- </FlexRow>
- <FlexCol :innerStyle="leftViewStyle">
- <slot name="title">
- <Text v-if="title" :innerStyle="{ ...titleStyle, ...textStyle} ">{{ title }}</Text>
- </slot>
- <slot name="label">
- <Text v-if="label" :innerStyle="{ ...labelStyle, ...textStyle} ">{{ label }}</Text>
- </slot>
- </FlexCol>
- </slot>
- </FlexRow>
- <FlexRow key="right" :flexShrink="0" center>
- <slot name="right">
- <slot name="rightPrepend" />
- <slot name="value">
- <Text
- key="value"
- :selectable="valueSelectable"
- :innerStyle="{ ...valueStyle, ...textStyle }"
- >
- {{value ? ('' + value) : ''}}
- </Text>
- </slot>
- <Icon
- v-if="showArrow"
- key="rightArrow"
- icon="arrow-right"
- :size="textStyle.fontSize"
- :color="titleStyle.color"
- />
- <slot name="rightIcon">
- <Icon
- v-if="rightIcon"
- key="rightIcon"
- v-bind="rightIconProps"
- :size="iconSize"
- :icon="rightIcon"
- :innerStyle="{ ...titleStyle, ...rightIconStyle }"
- />
- </slot>
- </slot>
- </FlexRow>
- </slot>
- </Touchable>
- </template>
- <script setup lang="ts">
- import { computed, provide } from 'vue';
- import { propGetThemeVar, useTheme, type ThemePaddingMargin } from '../theme/ThemeDefine';
- import { CellContextKey, type CellContext } from './CellContext';
- import { configPadding } from '../theme/ThemeTools';
- import type { IconProps } from './Icon.vue';
- import FlexRow from '../layout/FlexRow.vue';
- import FlexCol from '../layout/FlexCol.vue';
- import Text from './Text.vue';
- import Icon from './Icon.vue';
- import Touchable from '../feedback/Touchable.vue';
- export interface CellProp {
- /**
- * 左侧标题
- */
- title?: string,
- /**
- * 右侧内容
- */
- value?: string|number,
- /**
- * 设置右侧内容是否可以选择
- * @default false
- */
- valueSelectable?: boolean,
- /**
- * 标题下方的描述信息
- */
- label?: string,
- /**
- * 左侧图标名称或图片链接(http/https),等同于 Icon 组件的 icon
- */
- icon?: string,
- /**
- * 当使用图标时,左图标的附加属性
- */
- iconProps?: IconProps;
- /**
- * 当左侧图标未设置时,是否在左侧追加一个占位区域,以和其他单元格对齐
- * @default false
- */
- iconPlaceholder?: boolean,
- /**
- * 左侧图标区域的宽度
- * @default 50
- */
- iconWidth?: number|string|'auto',
- /**
- * 左侧图标的大小
- * @default 40
- */
- iconSize?: number|string,
- /**
- * 右侧图标的大小
- * @default 40
- */
- rightIconSize?: number|string,
- /**
- * 右侧图标名称或图片链接(http/https),等同于 Icon 组件的 icon
- */
- rightIcon?: string,
- /**
- * 当使用图标时,右图标的附加属性
- */
- rightIconProps?: IconProps;
- /**
- * 是否可以点击
- * @default false
- */
- touchable?: boolean,
- /**
- * 是否展示右侧箭头
- * @default false
- */
- showArrow?: boolean,
- /**
- * 是否使内容垂直居中
- * @default false
- */
- center?: boolean,
- /**
- * 大小
- * @default medium
- */
- size?:'small'|'medium'|'large',
- /**
- * 背景颜色
- * @default Color.white
- */
- backgroundColor?: string;
- /**
- * 是否显示顶部边框
- * @default false
- */
- topBorder?: boolean;
- /**
- * 是否显示底部边框
- * @default true
- */
- bottomBorder?: boolean;
- /**
- * 按下的背景颜色
- * @default PressedColor(Color.white)
- */
- pressedColor?: string,
- /**
- * 圆角
- */
- radius?: string|number,
- /**
- * 自定义样式
- */
- innerStyle?: object,
- /**
- * 自定义左侧图标样式
- */
- iconStyle?: object,
- /**
- * 自定义右侧图标样式
- */
- rightIconStyle?: object,
- /**
- * 强制控制按钮的边距。如果是数字,则设置所有方向边距;两位数组 [vetical,horizontal];四位数组 [top,right,down,left]
- */
- padding?: number|number[]|ThemePaddingMargin,
- }
- const emit = defineEmits([ 'click' ]);
- const theme = useTheme();
- const props = withDefaults(defineProps<CellProp>(), {
- backgroundColor: () => propGetThemeVar('CellBackground', 'white'),
- size: () => propGetThemeVar('CellSize', 'medium'),
- padding: () => propGetThemeVar<any>('CellPadding', undefined),
- pressedColor: () => propGetThemeVar('CellPressedColor', 'pressed.white'),
- bottomBorder: () => propGetThemeVar('CellBottomBorder', true),
- topBorder: () => propGetThemeVar('CellTopBorder', false),
- center: () => propGetThemeVar('CellCenter', true),
- radius: () => propGetThemeVar('CellRadius', 0),
- iconWidth: () => propGetThemeVar('CellIconWidth', 50),
- iconSize: () => propGetThemeVar('CellIconSize', 40),
- rightIconSize: () => propGetThemeVar('CellIconSize', 40),
- valueSelectable: false,
- })
- provide<CellContext>(CellContextKey, {
- setOnClickListener: (listener) => {
- customClickListener = listener;
- },
- })
- const themeVars = computed(() => theme.resolveThemeSizes({
- CellBorderWidth: 1,
- CellFontSizeLarge: 36,
- CellFontSizeMedium: 32,
- CellFontSizeSmall: 28,
- CellIconSize: 30,
- CellIconWidth: 40,
- CellHeightLarge: 100,
- CellHeightMedium: 75,
- CellHeightSmall: 50,
- CellPaddingLarge: 15,
- CellPaddingMedium: 10,
- CellPaddingSmall: 7,
- }));
- const themeColorVars = computed(() => theme.resolveThemeColors({
- CellBorderColor: 'border.cell',
- }));
- const leftViewStyle = computed(() => ({
- marginLeft: theme.resolveThemeSize('CellLeftPaddingHorizontal', 15),
- marginRight: theme.resolveThemeSize('CellLeftPaddingHorizontal', 15),
- }));
- const titleStyle = computed(() => ({
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- color: theme.resolveThemeColor('CellTitleColor', 'text.content'),
- }));
- const labelStyle = computed(() => ({
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- color: theme.resolveThemeColor('CellLabelColor', 'text.second'),
- }));
- const valueStyle = computed(() => ({
- color: theme.resolveThemeColor('CellLabelColor', 'text.second'),
- marginLeft: theme.resolveThemeSize('CellValuePaddingHorizontal', 20),
- marginRight: theme.resolveThemeSize('CellValuePaddingHorizontal', 20),
- }));
- const viewStyle = computed(() => ({
- position: 'relative',
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- overflow: 'hidden',
- paddingLeft: theme.resolveThemeSize('CellPaddingHorizontal', 25),
- paddingRight: theme.resolveThemeSize('CellPaddingHorizontal', 25),
- }));
- const style = computed(() => {
- const styleObj : Record<string, any> = {
- backgroundColor: theme.resolveThemeColor(props.backgroundColor),
- borderRadius: theme.resolveThemeSize(props.radius),
- ...props.innerStyle,
- };
- switch (props.size) {
- case 'large':
- styleObj.minHeight = themeVars.value.CellHeightLarge as number;
- styleObj.paddingTop = themeVars.value.CellPaddingLarge as number;
- styleObj.paddingBottom = themeVars.value.CellPaddingLarge as number;
- break;
- default:
- case 'medium':
- styleObj.minHeight = themeVars.value.CellHeightMedium as number;
- styleObj.paddingTop = themeVars.value.CellPaddingMedium as number;
- styleObj.paddingBottom = themeVars.value.CellPaddingMedium as number;
- break;
- case 'small':
- styleObj.minHeight = themeVars.value.CellHeightSmall as number;
- styleObj.paddingTop = themeVars.value.CellPaddingSmall as number;
- styleObj.paddingBottom = themeVars.value.CellPaddingSmall as number;
- }
- //内边距样式的强制设置
- configPadding(styleObj, theme.theme, props.padding);
- //边框设置
- if (props.topBorder)
- styleObj.borderTop = `${themeVars.value.CellBorderWidth} solid ${themeColorVars.value.CellBorderColor}`;
- if (props.bottomBorder)
- styleObj.borderBottom = `${themeVars.value.CellBorderWidth} solid ${themeColorVars.value.CellBorderColor}`;
- return styleObj
- });
- //文字样式
- const textStyle = computed(() => {
- switch (props.size) {
- case 'large':
- return { fontSize: themeVars.value.CellFontSizeLarge };
- default:
- return { fontSize: themeVars.value.CellFontSizeMedium };
- case 'small':
- return { fontSize: themeVars.value.CellFontSizeSmall };
- }
- });
- let customClickListener: (() => void)|undefined;
- function handleClick() {
- customClickListener?.();
- emit('click');
- }
- </script>
|