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 IconButton from './iconButton'; 8import FastImage from './fastImage'; 9 10export interface 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 /> 38 ) : ( 39 <View style={[leftStyle.artworkWrapper, {width}]}> 40 {index !== undefined ? ( 41 <ThemeText 42 fontColor="secondary" 43 style={{fontStyle: 'italic'}}> 44 {index} 45 </ThemeText> 46 ) : icon !== undefined ? ( 47 <IconButton {...icon} /> 48 ) : ( 49 <FastImage 50 style={leftStyle.artwork} 51 uri={ 52 artwork?.startsWith('//') 53 ? `https:${artwork}` 54 : artwork 55 } 56 emptySrc={fallback} 57 /> 58 )} 59 </View> 60 ) 61 ) : ( 62 <></> 63 ); 64} 65 66const leftStyle = StyleSheet.create({ 67 artworkWrapper: { 68 justifyContent: 'center', 69 alignItems: 'center', 70 }, 71 artwork: { 72 width: rpx(76), 73 height: rpx(76), 74 borderRadius: rpx(16), 75 }, 76}); 77 78/** 歌单item */ 79interface IListItemProps { 80 /** 标题 */ 81 title: string | number; 82 /** 描述 */ 83 desc?: string | JSX.Element; 84 /** 标签 */ 85 tag?: string; 86 left?: ILeftProps; 87 /** 右侧按钮 */ 88 right?: () => JSX.Element; 89 itemPaddingHorizontal?: number; 90 itemHeight?: number; 91 onPress?: () => void; 92} 93 94export default function ListItem(props: IListItemProps) { 95 const { 96 title, 97 desc, 98 tag, 99 right, 100 itemHeight, 101 onPress, 102 left, 103 itemPaddingHorizontal = rpx(24), 104 } = props; 105 return ( 106 <List.Item 107 left={() => <Left {...(left ?? {})} />} 108 style={[ 109 style.wrapper, 110 { 111 paddingHorizontal: itemPaddingHorizontal, 112 height: itemHeight ?? rpx(120), 113 paddingVertical: 0, 114 }, 115 ]} 116 title={() => ( 117 <View 118 style={{ 119 alignItems: 'stretch', 120 justifyContent: 'center', 121 height: itemHeight ?? rpx(120), 122 marginRight: right ? rpx(18) : 0, 123 }}> 124 <View style={style.titleWrapper}> 125 <ThemeText numberOfLines={1} style={style.textWidth}> 126 {title} 127 </ThemeText> 128 {tag ? <Tag tagName={tag} /> : <></>} 129 </View> 130 {desc ? ( 131 <ThemeText 132 fontColor="secondary" 133 fontSize="description" 134 numberOfLines={1} 135 style={[style.textWidth, {marginTop: rpx(18)}]}> 136 {desc} 137 </ThemeText> 138 ) : ( 139 <></> 140 )} 141 </View> 142 )} 143 titleStyle={{ 144 paddingVertical: 0, 145 marginLeft: 0, 146 marginVertical: 0, 147 }} 148 right={right ? right : () => <></>} 149 onPress={onPress} 150 /> 151 ); 152} 153const style = StyleSheet.create({ 154 wrapper: { 155 justifyContent: 'center', 156 }, 157 titleWrapper: { 158 flexDirection: 'row', 159 alignItems: 'center', 160 justifyContent: 'space-between', 161 }, 162 textWidth: { 163 maxWidth: rpx(460), 164 }, 165 artworkWrapper: { 166 width: rpx(76), 167 justifyContent: 'center', 168 alignItems: 'center', 169 marginRight: rpx(12), 170 }, 171 artwork: { 172 width: rpx(76), 173 height: rpx(76), 174 borderRadius: rpx(16), 175 }, 176}); 177