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