| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- <template>
- <Touchable
- touchable
- overflow="hidden"
- :width="isListStyle ? undefined : itemSize.width"
- :height="isListStyle ? undefined : itemSize.height"
- :innerStyle="{
- ...(isListStyle ? themeStyles.itemListStyle.value : themeStyles.item.value),
- ...(isListStyle ? selectStyleType(item.state, 'notstart', {
- notstart: {},
- uploading: themeStyles.itemListStyleUploading.value,
- success: themeStyles.itemListStyleSuccess.value,
- fail: themeStyles.itemListStyleFail.value,
- }) : {}),
- ...props.style as ViewStyle,
- }"
- :direction="isListStyle ? 'row' : 'column'"
- center
- @click="emit('click')"
- >
- <template v-if="!isListStyle">
- <IconButton
- v-if="showDelete"
- icon="delete-filling"
- color="danger"
- :buttonStyle="themeStyles.itemDeleteButton.value"
- @click.stop="emit('delete')" />
-
- <FlexView v-if="item.state === 'uploading'" :innerStyle="{
- ...itemMaskStyle,
- backgroundColor: themeContext.resolveThemeColor('UploaderListItemUploadingBackgroundColor', 'mask.primary'),
- }">
- <ActivityIndicator :color="itemMaskTextColor" :size="loadingSize" />
- <Text :color="itemMaskTextColor" :style="itemMaskTextStyle" textAlign="center" :text="item.message" />
- </FlexView>
- <FlexView v-if="item.state === 'fail'" :innerStyle="{
- ...itemMaskStyle,
- backgroundColor: themeContext.resolveThemeColor('UploaderListItemUploadingBackgroundColor', 'mask.danger'),
- }">
- <Icon icon="error" :color="itemMaskTextColor" :size="iconSize" />
- <Text :color="itemMaskTextColor" :style="itemMaskTextStyle" textAlign="center" :text="item.message" />
- </FlexView>
- </template>
- <Image
- v-if="isImage"
- :src="item.previewPath || item.filePath"
- :defaultImage="defaultSource ?? fileIcon"
- :width="isListStyle ? itemListStyleImageSize : itemSize.width"
- :height="isListStyle ? itemListStyleImageSize : itemSize.height"
- :innerStyle="{
- ...(isListStyle ? themeStyles.itemListStyleImage.value : themeStyles.itemImage.value),
- ...imageStyle,
- }"
- mode="aspectFill"
- />
- <Icon v-else :icon="fileIcon" :color="itemMaskTextColor" :size="itemListStyleImageSize" />
- <FlexRow v-if="isListStyle" :flex="1" align="center">
- <Width :size="20" />
- <FlexCol :flex="1">
- <Text :fontSize="26" :text="StringUtils.path.getFileName(item.filePath)" />
- <Text :fontSize="22" :text="item.message" />
- <Height :size="10" />
- <Progress :progressColor="selectStyleType(item.state, 'notstart', {
- notstart: 'primary',
- uploading: 'primary',
- success: 'success',
- fail: 'danger',
- })" :value="item.progress || 0" />
- </FlexCol>
- <Icon v-if="item.state === 'success'" icon="select-bold" color="success" />
- <Icon v-else-if="item.state === 'fail'" icon="close-bold" color="danger" />
- <ActivityIndicator v-else-if="item.state === 'uploading'" :size="45" />
- <Width :size="20" />
- <IconButton v-if="showDelete" icon="trash" @click.stop="emit('delete')" />
- </FlexRow>
- </Touchable>
- </template>
- <script setup lang="ts">
- import { computed, watch } from 'vue';
- import { useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
- import { DynamicColor, DynamicSize, DynamicSize2, selectStyleType } from '../theme/ThemeTools';
- import { StringUtils } from '@imengyu/imengyu-utils';
- import ActivityIndicator from '../basic/ActivityIndicator.vue';
- import Icon from '../basic/Icon.vue';
- import IconButton from '../basic/IconButton.vue';
- import Image from '../basic/Image.vue';
- import Text from '../basic/Text.vue';
- import FlexCol from '../layout/FlexCol.vue';
- import FlexView from '../layout/FlexView.vue';
- import FlexRow from '../layout/FlexRow.vue';
- import Progress from '../display/Progress.vue';
- import IconApk from '../images/files/apk.png';
- import IconAudio from '../images/files/audio.png';
- import IconDefault from '../images/files/default.png';
- import IconExcel from '../images/files/excel.png';
- import IconPowerpoint from '../images/files/powerpoint.png';
- import IconUnknown from '../images/files/unknown.png';
- import IconVideo from '../images/files/video.png';
- import IconWord from '../images/files/word.png';
- import IconZip from '../images/files/zip.png';
- import IconPdf from '../images/files/pdf.png';
- import Width from '../layout/space/Width.vue';
- import Height from '../layout/space/Height.vue';
- import Touchable from '../feedback/Touchable.vue';
- import type { UploaderItem } from './Uploader';
- export interface UploaderListItemProps {
- item: UploaderItem;
- style?: ViewStyle;
- imageStyle?: ViewStyle;
- itemMaskTextStyle?: TextStyle;
- itemMaskStyle?: ViewStyle;
- itemSize: { width: number, height: number };
- showDelete: boolean;
- defaultSource: string | undefined;
- isListStyle: boolean;
- }
- const props = defineProps<UploaderListItemProps>();
- const emit = defineEmits(['click', 'delete'])
- const themeContext = useTheme();
- const itemListStyleImageSize = computed(() => themeContext.resolveThemeSize('UploaderListItemListImageSize', 64));
- const themeStyles = themeContext.useThemeStyles({
- item: {
- position: 'relative',
- borderRadius: DynamicSize('UploaderListItemBorderRadius', 20),
- backgroundColor: DynamicColor('UploaderListItemBackgroundColor', 'grey'),
- marginHorizontal: DynamicSize('UploaderListItemGridMargin', 4),
- marginBottom: DynamicSize('UploaderListItemGridMargin', 4),
- },
- itemListStyle: {
- position: 'relative',
- borderStyle: 'solid',
- borderWidth: DynamicSize('UploaderListItemListBorderWidth', 2),
- borderRadius: DynamicSize('UploaderListItemBorderRadius', 15),
- backgroundColor: DynamicColor('UploaderListItemBackgroundColor', 'white'),
- padding: DynamicSize2('UploaderListItemListPaddingVertical', 'UploaderListItemListPaddingHorizontal', 20, 20),
- marginBottom: DynamicSize('UploaderListItemListMargin', 10),
- },
- itemListStyleUploading: {
- borderColor: DynamicColor('UploaderListItemListUploadingBorderColor', 'primary'),
- backgroundColor: DynamicColor('UploaderListItemListUploadingBackgroundColor', 'background.primary'),
- },
- itemListStyleSuccess: {
- borderColor: DynamicColor('UploaderListItemListSuccessBorderColor', 'success'),
- backgroundColor: DynamicColor('UploaderListItemListSuccessBackgroundColor', 'background.success'),
- },
- itemListStyleFail: {
- borderColor: DynamicColor('UploaderListItemListFailBorderColor', 'danger'),
- backgroundColor: DynamicColor('UploaderListItemListFailBackgroundColor', 'background.danger'),
- },
- itemListStyleImage: {
- borderRadius: DynamicSize('UploaderListItemListBorderRadius', 20),
- },
- itemImage: {
- position: 'absolute',
- top: 0,
- left: 0,
- borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 15),
- zIndex: 5,
- },
- itemList: {
- },
- itemMask: {
- backgroundColor: 'rgba(0,0,0,0.3)',
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 20),
- zIndex: 10,
- },
- itemMaskText: {
- marginTop: 5,
- color: '#fff',
- },
- itemDeleteButton: {
- position: 'absolute',
- right: 0,
- top: 0,
- zIndex: 30,
- borderRadius: DynamicSize('UploaderListItemGridBorderRadius', 20),
- backgroundColor: '#fff',
- },
- });
- const itemMaskTextStyle = computed(() => ({ ...themeStyles.itemMaskText.value, ...props.itemMaskTextStyle }));
- const itemMaskStyle = computed(() => ({ ...themeStyles.itemMask.value, ...props.itemMaskStyle }));
- const itemMaskTextColor = computed(() => props.itemMaskTextStyle?.color || themeStyles.itemMaskText.value.color as string);
- const iconSize = computed(() => themeContext.resolveThemeSize('UploaderListItemIconSize', 65));
- const loadingSize = computed(() => themeContext.resolveThemeSize('UploaderListItemLoadingSize', 35));
- const imageExts = [ 'jpg', 'jpeg', 'png', 'webp', 'gif' ]
- const isImage = computed(() => {
- return props.item.isImage
- || (props.item.previewPath && imageExts.includes(StringUtils.path.getFileExt(props.item.previewPath)))
- || (props.item.filePath && imageExts.includes(StringUtils.path.getFileExt(props.item.filePath || ''))
- )
- });
- const fileIcon = computed(() => {
- const ext = StringUtils.path.getFileExt(props.item.filePath || '');
- switch (ext) {
- case 'apk1':
- case 'apk': return IconApk;
- case 'audio':
- case 'mp3':
- case 'wav':
- case 'wma':
- case 'ogg':
- case 'flac':
- return IconAudio;
- case 'default':
- return IconDefault;
- case 'excel':
- case 'xls':
- case 'xlsx':
- return IconExcel;
- case 'powerpoint':
- case 'ppt':
- case 'pptx':
- return IconPowerpoint;
- case 'unknown':
- case 'video':
- case 'mp4':
- case 'mov':
- case 'wmv':
- case 'avi':
- case 'flv':
- return IconVideo;
- case 'word':
- case 'docx':
- case 'doc':
- case 'txt':
- case 'rtf':
- return IconWord;
- case 'zip':
- case '7z':
- case 'rar':
- return IconZip;
- case 'pdf':
- return IconPdf;
- }
- return IconUnknown;
- });
- </script>
|