zsy-recycling-supervision-a.../src/pages/tsp-photo/PhotoList.vue

254 lines
6.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script lang="ts" setup>
import { uploadBaseUrl } from '@/common'
import { UploadFile } from '@idux/components'
import AppApi from '@/common/app/app-api.ts'
import Toast from '@/components/toast'
import TspPhotoApi from '@/pages/tsp-photo/tsp-photo-api.ts'
import { ref } from 'vue'
import times, { FMT } from '@/common/utils/times.ts'
const props = defineProps<{
tspId?: string
pointName?: string
uploadDate?: string
status: 'edit' | 'view'
}>()
const emit = defineEmits([ 'refresh' ])
const photoListTitle = computed(() => {
return props.uploadDate == null || props.pointName == null ? '图片列表'
: props.pointName + times.format(times.parse(props.uploadDate, FMT.date), FMT.date_zh) + '上传的图片'
})
const files = ref<UploadFile[]>([])
const fileUrls = ref<{ [key: string]: string }>({})
async function requestData(file: UploadFile) {
if (file.raw == null) return Promise.reject()
let res = await AppApi.obtainPresignedUrl(file.name)
const url = '/' + res.data.bucketName + '/' + res.data.objectName
file.thumbUrl = AppApi.fileUrl(url)
const key = file.key as string
fileUrls.value[key] = url
delete res.data.bucketName
delete res.data.objectName
return Promise.resolve(res.data)
}
function fileStatusChange(file: UploadFile) {
if (file.status === 'success') {
Toast.success('上传成功')
} else if (file.status === 'error') {
Toast.error('上传失败')
}
}
function delPhoto(index: number) {
const key = files.value[index].key as string
delete fileUrls.value[key]
files.value.splice(index, 1)
}
watch(
() => props.uploadDate,
(val) => {
if (val == null) {
files.value = []
return
}
TspPhotoApi.listPhoto({
tspId: props.tspId,
uploadDate: props.uploadDate,
}).then(res => {
let data = res.data?.photos ?? []
let temp: UploadFile[] = []
for (let datum of data) {
temp.push({
key: datum,
name: datum,
status: 'success',
thumbUrl: AppApi.fileUrl(datum),
})
}
files.value = temp
})
})
function submitPhoto() {
TspPhotoApi.save({
tspId: props.tspId,
uploadDate: props.uploadDate,
photos: files.value.map(it => fileUrls.value[it.key as string]).filter(it => it != null),
}).then(() => {
Toast.success('提交成功')
emit('refresh')
})
}
</script>
<template>
<div class="photo-list-container">
<div class="photo-title">
{{ photoListTitle }}
</div>
<div v-if="status === 'view'" class="photo-list">
<IxImage v-for="(it,i) in files" :key="'photo--'+i" :src="it.status==='success' ? it.thumbUrl ?? '' : ''">
<template #previewIcon>
<div class="photo-preview">
<IxIcon name="plus-circle"/>
</div>
</template>
</IxImage>
</div>
<!--<div v-else-if="status === 'edit' && uploadDate != null">
<div style="height: 100px;width: 100px;background-color: #00B42A" v-for="(it,i) in files" :key="'photo&#45;&#45;'+i"></div>
</div>-->
<IxUpload
v-else-if="status === 'edit' && uploadDate != null"
v-model:files="files"
:action="uploadBaseUrl"
:progress="{strokeColor: {
'0%': '#108EE9',
'100%': '#87D068',
},
strokeWidth: 3,
}"
:request-data="requestData"
dragable
accept="image/*"
multiple
@file-status-change="fileStatusChange">
<div class="drag-panel">
<IxIcon class="drag-panel-icon" name="upload"/>
<p>点击或拖拽上传</p>
</div>
<template #list>
<div v-if="files.length > 0" class="photo-list">
<IxImage v-for="(it,i) in files" :key="'photo--'+i" :src="it.status==='success' ? it.thumbUrl ?? '' : ''">
<template #previewIcon>
<div class="photo-preview">
<IxIcon name="plus-circle"/>
<IxIcon name="delete" @click.stop="delPhoto(i)"/>
</div>
</template>
</IxImage>
</div>
<IxEmpty v-else/>
</template>
</IxUpload>
<IxEmpty v-else description="请选择小区和日期"/>
<div v-if="status === 'edit' && uploadDate != null" class="photo-bottom">
<IxPopconfirm placement="top" title="是否提交?" @ok="submitPhoto">
<IxButton :disabled="files.length === 0" mode="primary"></IxButton>
<template #content>
<div>小区{{ pointName }}</div>
<div>日期{{ uploadDate }}</div>
<div>图片数量{{ files.length }}</div>
</template>
</IxPopconfirm>
</div>
</div>
</template>
<style lang="stylus" scoped>
.photo-list-container {
width 30%
height 100%
display flex
flex-direction column
.photo-title {
font-size 2rem
font-weight bold
padding 1rem
box-sizing border-box
border-bottom 1px solid rgb(211, 215, 222);
text-wrap: auto;
word-break: break-word;
overflow-wrap: normal;
line-height: 1.6;
}
:deep(.ix-upload) {
flex 1
display: flex
flex-direction: column;
height: 0;
.ix-upload-selector {
height 6rem
width 100%;
margin-bottom 1rem
.drag-panel {
height 100%
width 100%;
display: flex;
align-items: center;
justify-content: center;
gap 1rem
&-icon {
font-size: 24px;
}
p {
font-size: 14px;
margin: 8px 0 0 0;
}
&:hover {
color: #1C6EFF;
}
}
}
}
.photo-list {
flex 1
width 100%;
padding 1rem
overflow auto
display grid
grid-template-columns repeat(2, 1fr)
grid-auto-rows: 8rem
gap 1rem
align-items stretch
& > div {
height: 8rem;
box-sizing: border-box;
}
.photo-preview {
display: flex
color: white;
font-size: 2rem;
gap: 1rem;
}
}
.photo-bottom {
display flex
justify-content space-evenly
align-items center
height 10rem
gap 5%
padding 1rem
& > button {
width 10rem
}
}
}
</style>