1import React from 'react'; 2import {StyleSheet, View} from 'react-native'; 3import rpx from '@/utils/rpx'; 4import {List} from 'react-native-paper'; 5import Tag from './tag'; 6import ThemeText from './themeText'; 7import Image from './image'; 8import IconButton from './iconButton'; 9 10interface ILeftProps { 11 /** 序号 */ 12 index?: number | string; 13 /** 封面图 */ 14 artwork?: string; 15 /** 封面图的兜底 */ 16 fallback?: any; 17 /** icon */ 18 icon?: Parameters<typeof IconButton>[0]; 19 /** 宽度 */ 20 width?: number; 21 /** 组件 */ 22 component?: () => JSX.Element; 23} 24 25function Left(props?: ILeftProps) { 26 const { 27 index, 28 artwork, 29 fallback, 30 icon, 31 width = rpx(100), 32 component: Component, 33 } = props ?? {}; 34 35 return props && Object.keys(props).length ? ( 36 Component ? ( 37 <Component></Component> 38 ) : ( 39 <View style={[leftStyle.artworkWrapper, {width}]}> 40 {index !== undefined ? ( 41 <ThemeText fontColor="secondary" style={{fontStyle: 'italic'}}> 42 {index} 43 </ThemeText> 44 ) : icon !== undefined ? ( 45 <IconButton {...icon}></IconButton> 46 ) : ( 47 <Image 48 style={leftStyle.artwork} 49 uri={artwork} 50 fallback={fallback}></Image> 51 )} 52 </View> 53 ) 54 ) : ( 55 <></> 56 ); 57} 58 59const leftStyle = StyleSheet.create({ 60 artworkWrapper: { 61 justifyContent: 'center', 62 alignItems: 'center', 63 }, 64 artwork: { 65 width: rpx(76), 66 height: rpx(76), 67 borderRadius: rpx(16), 68 }, 69}); 70 71/** 歌单item */ 72interface IListItemProps { 73 /** 标题 */ 74 title: string; 75 /** 描述 */ 76 desc?: string | JSX.Element; 77 /** 标签 */ 78 tag?: string; 79 left?: ILeftProps; 80 /** 右侧按钮 */ 81 right?: () => JSX.Element; 82 itemPaddingHorizontal?: number; 83 itemHeight?: number; 84 onPress?: () => void; 85} 86 87export default function ListItem(props: IListItemProps) { 88 const { 89 title, 90 desc, 91 tag, 92 right, 93 itemHeight, 94 onPress, 95 left, 96 itemPaddingHorizontal = rpx(24), 97 } = props; 98 return ( 99 <List.Item 100 left={() => <Left {...(left ?? {})}></Left>} 101 style={[ 102 style.wrapper, 103 { 104 paddingHorizontal: itemPaddingHorizontal, 105 height: itemHeight ?? rpx(120), 106 paddingVertical: 0, 107 }, 108 ]} 109 title={() => ( 110 <View 111 style={{ 112 alignItems: 'stretch', 113 justifyContent: 'center', 114 height: itemHeight ?? rpx(120), 115 marginRight: right ? rpx(18) : 0, 116 }}> 117 <View style={style.titleWrapper}> 118 <ThemeText numberOfLines={1} style={style.textWidth}> 119 {title} 120 </ThemeText> 121 {tag ? <Tag tagName={tag}></Tag> : <></>} 122 </View> 123 {desc ? ( 124 <ThemeText 125 fontColor="secondary" 126 fontSize="description" 127 numberOfLines={1} 128 style={[style.textWidth, {marginTop: rpx(18)}]}> 129 {desc} 130 </ThemeText> 131 ) : ( 132 <></> 133 )} 134 </View> 135 )} 136 titleStyle={{ 137 paddingVertical: 0, 138 marginLeft: 0, 139 marginVertical: 0, 140 }} 141 right={right ? right : () => <></>} 142 onPress={onPress}></List.Item> 143 ); 144} 145const style = StyleSheet.create({ 146 wrapper: { 147 justifyContent: 'center', 148 }, 149 titleWrapper: { 150 flexDirection: 'row', 151 alignItems: 'center', 152 justifyContent: 'space-between', 153 }, 154 textWidth: { 155 maxWidth: rpx(460), 156 }, 157 artworkWrapper: { 158 width: rpx(76), 159 justifyContent: 'center', 160 alignItems: 'center', 161 marginRight: rpx(12), 162 }, 163 artwork: { 164 width: rpx(76), 165 height: rpx(76), 166 borderRadius: rpx(16), 167 }, 168}); 169