上传照片
parent
15981273b0
commit
444c7d3684
|
|
@ -0,0 +1,363 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useFormGroup } from '@idux/cdk'
|
||||||
|
import times, { FMT } from '@/common/utils/times.ts'
|
||||||
|
import {
|
||||||
|
TableColumn,
|
||||||
|
TableColumnSelectable
|
||||||
|
} from '@idux/components/table'
|
||||||
|
import { TablePagination } from '@idux/components/table/src/types'
|
||||||
|
import TspApi from '@/pages/tsp/tsp-api.ts'
|
||||||
|
import TspPhotoApi from '@/pages/tsp-photo/tsp-photo-api.ts'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
tspPhotoData: TspPhotoTypes.TspPhotoSearchParam
|
||||||
|
status: 'edit' | 'view'
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits([ 'update:tspPhotoData' ])
|
||||||
|
|
||||||
|
const weekday = [ '周一', '周二', '周三', '周四', '周五', '周六', '周日' ]
|
||||||
|
const days = ref<Array<Array<TspPhotoTypes.DayType | null>>>([])
|
||||||
|
const tspPhotoForm = useFormGroup<TspPhotoTypes.TspPhotoSearchParam>({
|
||||||
|
tspId: [ '' ],
|
||||||
|
pointName: [ '' ],
|
||||||
|
month: [ new Date() ],
|
||||||
|
day: [ new Date().getDate() ],
|
||||||
|
uploadDate: [ times.format(new Date(), FMT.date) ],
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedRowKeys = ref<string[]>([])
|
||||||
|
const tableSpin = ref(false)
|
||||||
|
const datasource = ref<TspTypes.TspData[]>([])
|
||||||
|
const selectableColumn = reactive<TableColumnSelectable<TspTypes.TspData>>({
|
||||||
|
type: 'selectable',
|
||||||
|
align: 'center',
|
||||||
|
multiple: false,
|
||||||
|
showIndex: false,
|
||||||
|
trigger: 'click',
|
||||||
|
onChange: (selectedKeys) => {
|
||||||
|
if (selectedKeys.length === 0) {
|
||||||
|
const value = tspPhotoForm.get('tspId')?.getValue()
|
||||||
|
if (value != null) {
|
||||||
|
selectedRowKeys.value = [ value ]
|
||||||
|
} else {
|
||||||
|
tspPhotoForm.get('tspId')?.setValue('')
|
||||||
|
tspPhotoForm.get('pointName')?.setValue('')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data = datasource.value?.find(item => item.id === (selectedKeys[0] as string))
|
||||||
|
tspPhotoForm.get('tspId')?.setValue(selectedKeys[0] as string)
|
||||||
|
tspPhotoForm.get('pointName')?.setValue(data?.pointName)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const columns: TableColumn<TspTypes.TspData>[] = [
|
||||||
|
selectableColumn,
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataKey: 'pointName',
|
||||||
|
customCell: 'pointName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属街道',
|
||||||
|
dataKey: 'streetName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属小区',
|
||||||
|
dataKey: 'microdistrict',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属物业',
|
||||||
|
dataKey: 'propertyManagement'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function searchHandler() {
|
||||||
|
tableSpin.value = true
|
||||||
|
return TspApi.paging({
|
||||||
|
current: pagination.pageIndex ?? 1,
|
||||||
|
size: pagination.pageSize ?? 10,
|
||||||
|
}).then(res => {
|
||||||
|
pagination.pageIndex = res.data.current
|
||||||
|
pagination.pageSize = res.data.size
|
||||||
|
pagination.total = res.data.total
|
||||||
|
datasource.value = res.data.records
|
||||||
|
return res.data.records
|
||||||
|
}).finally(() => {
|
||||||
|
tableSpin.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagination = reactive<TablePagination>({
|
||||||
|
pageIndex: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
size: 'sm',
|
||||||
|
showTotal: true,
|
||||||
|
onChange(pageIndex: number, pageSize: number) {
|
||||||
|
pagination.pageIndex = pageIndex
|
||||||
|
pagination.pageSize = pageSize
|
||||||
|
searchHandler()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
function disabledDate(date: Date) {
|
||||||
|
return times.parse(date).month > times.now().month
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
searchHandler()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function selectDayHandler(day: TspPhotoTypes.DayType) {
|
||||||
|
const date = `${day.year}-${day.month < 10 ? '0' + day.month : day.month}-${day.day < 10 ? '0' + day.day : day.day}`
|
||||||
|
const dateObj = times.parse(date, FMT.date)
|
||||||
|
if (dateObj.diffNow().toMillis() > 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tspPhotoForm.get('day')?.setValue(day.day)
|
||||||
|
tspPhotoForm.get('uploadDate')?.setValue(date)
|
||||||
|
emit('update:tspPhotoData', tspPhotoForm.getValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
const photoUploadStatus = ref<TspPhotoTypes.ObtainStatusResult>({})
|
||||||
|
|
||||||
|
function computedStatus(day: number) {
|
||||||
|
const count = photoUploadStatus.value[day]
|
||||||
|
return count != null && count > 0 ? 'uploaded'
|
||||||
|
: count != null && count === 0 ? 'unupload'
|
||||||
|
: 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
|
function obtainStatus() {
|
||||||
|
TspPhotoApi.obtainStatus(tspPhotoForm.getValue()).then(res => {
|
||||||
|
photoUploadStatus.value = res.data
|
||||||
|
computedCalendar()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function computedCalendar() {
|
||||||
|
const value: Date = tspPhotoForm.get('month')?.getValue() ?? new Date()
|
||||||
|
const beginOfMonth = times.beginOfMonth(times.parse(value))
|
||||||
|
const endOfMonth = times.endOfMonth(times.parse(value))
|
||||||
|
|
||||||
|
const firstDayIndex = beginOfMonth.weekday - 1
|
||||||
|
|
||||||
|
const yu_shu = (endOfMonth.day + firstDayIndex) % 7
|
||||||
|
|
||||||
|
const count = yu_shu > 0 ? (7 - yu_shu) + (endOfMonth.day + firstDayIndex) : (endOfMonth.day + firstDayIndex)
|
||||||
|
const days_: Array<Array<TspPhotoTypes.DayType | null>> = []
|
||||||
|
|
||||||
|
let temp: Array<TspPhotoTypes.DayType | null> = []
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
if (i < firstDayIndex) {
|
||||||
|
temp.push(null)
|
||||||
|
} else if (i >= firstDayIndex && i < firstDayIndex + endOfMonth.day) {
|
||||||
|
const day = i - firstDayIndex + 1
|
||||||
|
temp.push({
|
||||||
|
year: beginOfMonth.year,
|
||||||
|
month: beginOfMonth.month,
|
||||||
|
day: day,
|
||||||
|
status: computedStatus(day),
|
||||||
|
photoCount: photoUploadStatus.value[day] ?? 0
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
temp.push(null)
|
||||||
|
}
|
||||||
|
if (temp.length === 7) {
|
||||||
|
days_.push(temp)
|
||||||
|
temp = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
days.value = days_
|
||||||
|
}
|
||||||
|
|
||||||
|
tspPhotoForm.get('tspId')?.watchValue(() => {
|
||||||
|
obtainStatus()
|
||||||
|
emit('update:tspPhotoData', tspPhotoForm.getValue())
|
||||||
|
})
|
||||||
|
tspPhotoForm.get('month')?.watchValue((month) => {
|
||||||
|
if (month == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tspPhotoForm.get('day')?.setValue(1)
|
||||||
|
tspPhotoForm.get('uploadDate')?.setValue(times.format(times.parse(month), FMT.month) + '-01')
|
||||||
|
obtainStatus()
|
||||||
|
emit('update:tspPhotoData', tspPhotoForm.getValue())
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.status === 'edit') {
|
||||||
|
searchHandler()
|
||||||
|
.then((data) => {
|
||||||
|
if (data.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectedRowKeys.value = [ data[0].id ]
|
||||||
|
tspPhotoForm.get('tspId')?.setValue(data[0].id)
|
||||||
|
tspPhotoForm.get('pointName')?.setValue(data[0].pointName)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tspPhotoForm.get('tspId')?.setValue(props.tspPhotoData.tspId)
|
||||||
|
tspPhotoForm.get('pointName')?.setValue(props.tspPhotoData.pointName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
refresh() {
|
||||||
|
obtainStatus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="calendar-wrapper">
|
||||||
|
<div class="calendar-title">
|
||||||
|
<IxForm :control="tspPhotoForm" class="calendar-form" layout="inline">
|
||||||
|
<IxFormItem>
|
||||||
|
<IxInput v-if="status === 'view'" control="pointName" readonly/>
|
||||||
|
|
||||||
|
<IxPopover v-if="status === 'edit'" v-model:visible="visible" closable header="小区列表" placement="bottom" trigger="click">
|
||||||
|
<IxInput control="pointName" placeholder="请选择小区"/>
|
||||||
|
<template #content>
|
||||||
|
<IxTable v-model:selectedRowKeys="selectedRowKeys" :columns="columns" :dataSource="datasource" :pagination="pagination" :spin="tableSpin" get-key="id"/>
|
||||||
|
</template>
|
||||||
|
</IxPopover>
|
||||||
|
</IxFormItem>
|
||||||
|
<IxFormItem>
|
||||||
|
<IxDatePicker :disabled-date="disabledDate" control="month" type="month" @change="computedCalendar"/>
|
||||||
|
</IxFormItem>
|
||||||
|
</IxForm>
|
||||||
|
</div>
|
||||||
|
<table class="calendar">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="item in weekday" :key="'weekday-' + item" class="weekday">{{ item }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in days" :key="'day-' + index">
|
||||||
|
<td v-for="(it, i) in item" :key="'day-' + i" :class="{blank:it == null}" class="day">
|
||||||
|
<div v-if="it != null" :class="{'active-day': it.day === tspPhotoData.day && it.month === (tspPhotoData.month?.getMonth()??-1) + 1 && it.year === tspPhotoData.month?.getFullYear()}" class="day-content" @click="selectDayHandler(it)">
|
||||||
|
<div class="day-number">
|
||||||
|
<div>{{ it.day }}</div>
|
||||||
|
<div>{{ it.day === new Date().getDate() && it.month === new Date().getMonth() + 1 && it.year === new Date().getFullYear() ? '今' : '' }}</div>
|
||||||
|
</div>
|
||||||
|
<IxTagGroup v-if="it.status === 'uploaded'" :gap="0" class="day-status">
|
||||||
|
<IxTag status="success">已上传</IxTag>
|
||||||
|
<IxTag status="success">{{ it.photoCount }}张</IxTag>
|
||||||
|
</IxTagGroup>
|
||||||
|
<IxTag v-else-if="it.status === 'unupload'" class="day-status" status="error">未上传</IxTag>
|
||||||
|
<div v-else class="day-status"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.calendar-wrapper {
|
||||||
|
flex 1
|
||||||
|
padding 1rem
|
||||||
|
box-sizing border-box
|
||||||
|
border-right: 1px solid rgb(211, 215, 222);
|
||||||
|
|
||||||
|
.calendar-form {
|
||||||
|
width 100%
|
||||||
|
height 4rem
|
||||||
|
|
||||||
|
:deep(.ix-form-item):first-child {
|
||||||
|
width 30%
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ix-form-item):nth-child(2) {
|
||||||
|
width 10%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar {
|
||||||
|
width 100%
|
||||||
|
height calc(100% - 4rem);
|
||||||
|
margin-top 1rem
|
||||||
|
box-sizing border-box
|
||||||
|
table-layout fixed
|
||||||
|
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid rgb(211, 215, 222);
|
||||||
|
|
||||||
|
thead {
|
||||||
|
height 4rem
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
height calc(100% - 4rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.day {
|
||||||
|
border-top: 1px solid rgb(211, 215, 222);
|
||||||
|
|
||||||
|
&:not(.blank) {
|
||||||
|
border: 1px solid rgb(211, 215, 222);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.day-content {
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
|
height 100%
|
||||||
|
width 100%
|
||||||
|
display flex
|
||||||
|
flex-direction column
|
||||||
|
justify-content space-around
|
||||||
|
padding 1rem
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active-day {
|
||||||
|
background-color: rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.day-number {
|
||||||
|
font-size 3rem
|
||||||
|
font-weight bold
|
||||||
|
display: flex
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
& > div:last-child {
|
||||||
|
color #165DFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.day-status {
|
||||||
|
width 100%;
|
||||||
|
height 20px;
|
||||||
|
|
||||||
|
:deep(.ix-space-item) {
|
||||||
|
flex 1
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
width 100%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
<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--'+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
|
||||||
|
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>
|
||||||
|
|
@ -1,258 +1,20 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import times, { FMT } from '@/common/utils/times.ts'
|
import PhotoCalendar from '@/pages/tsp-photo/PhotoCalendar.vue'
|
||||||
import { ref } from 'vue'
|
import PhotoList from '@/pages/tsp-photo/PhotoList.vue'
|
||||||
import {
|
|
||||||
TableColumn,
|
|
||||||
TableColumnSelectable
|
|
||||||
} from '@idux/components/table'
|
|
||||||
import { TablePagination } from '@idux/components/table/src/types'
|
|
||||||
import TspApi from '@/pages/tsp/tsp-api.ts'
|
|
||||||
import { useFormGroup, } from '@idux/cdk'
|
|
||||||
import TspPhotoApi from '@/pages/tsp-photo/tsp-photo-api.ts'
|
|
||||||
|
|
||||||
const weekday = [ '周一', '周二', '周三', '周四', '周五', '周六', '周日' ]
|
const tspPhotoData = ref<TspPhotoTypes.TspPhotoSearchParam>({})
|
||||||
|
const photoCalendar = ref<InstanceType<typeof PhotoCalendar> | null>(null)
|
||||||
|
|
||||||
interface DayType {
|
function refresh() {
|
||||||
year: number
|
photoCalendar.value?.refresh()
|
||||||
month: number
|
|
||||||
day: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const visible = ref(false)
|
|
||||||
const selectedRowKeys = ref<string[]>([])
|
|
||||||
const tspPhotoForm = useFormGroup<TspPhotoTypes.TspPhotoSearchParam>({
|
|
||||||
tspId: [ undefined ],
|
|
||||||
pointName: [ undefined ],
|
|
||||||
month: [ new Date() ],
|
|
||||||
day: [ 0 ],
|
|
||||||
uploadDate: [ times.format(new Date(), FMT.date) ],
|
|
||||||
})
|
|
||||||
const days = ref<Array<Array<DayType | null>>>([])
|
|
||||||
|
|
||||||
function renderCalendar(value: Date = new Date()) {
|
|
||||||
const beginOfMonth = times.beginOfMonth(times.parse(value))
|
|
||||||
const endOfMonth = times.endOfMonth(times.parse(value))
|
|
||||||
|
|
||||||
const firstDayIndex = beginOfMonth.weekday - 1
|
|
||||||
|
|
||||||
const count = (7 - (endOfMonth.day + firstDayIndex) % 7) + (endOfMonth.day + firstDayIndex)
|
|
||||||
const days_: Array<Array<DayType | null>> = []
|
|
||||||
|
|
||||||
let temp: Array<DayType | null> = []
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
if (i < firstDayIndex) {
|
|
||||||
temp.push(null)
|
|
||||||
} else if (i >= firstDayIndex && i < firstDayIndex + endOfMonth.day) {
|
|
||||||
temp.push({
|
|
||||||
year: beginOfMonth.year,
|
|
||||||
month: beginOfMonth.month,
|
|
||||||
day: i - firstDayIndex + 1
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
temp.push(null)
|
|
||||||
}
|
|
||||||
if (temp.length === 7) {
|
|
||||||
days_.push(temp)
|
|
||||||
temp = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
days.value = days_
|
|
||||||
}
|
|
||||||
|
|
||||||
function disabledDate(date: Date) {
|
|
||||||
return times.parse(date).month > times.now().month
|
|
||||||
}
|
|
||||||
|
|
||||||
const datasource = ref<TspTypes.TspData[]>()
|
|
||||||
|
|
||||||
const selectableColumn = reactive<TableColumnSelectable<TspTypes.TspData>>({
|
|
||||||
type: 'selectable',
|
|
||||||
align: 'center',
|
|
||||||
multiple: false,
|
|
||||||
showIndex: false,
|
|
||||||
trigger: 'click',
|
|
||||||
onChange: (selectedKeys) => {
|
|
||||||
if (selectedKeys.length === 0) {
|
|
||||||
const value = tspPhotoForm.get('tspId')?.getValue()
|
|
||||||
if (value != null) {
|
|
||||||
selectedRowKeys.value = [ value ]
|
|
||||||
} else {
|
|
||||||
tspPhotoForm.get('tspId')?.setValue('')
|
|
||||||
tspPhotoForm.get('pointName')?.setValue('')
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const data = datasource.value?.find(item => item.id === (selectedKeys[0] as string))
|
|
||||||
tspPhotoForm.get('tspId')?.setValue(selectedKeys[0] as string)
|
|
||||||
tspPhotoForm.get('pointName')?.setValue(data?.pointName)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const tableSpin = ref(false)
|
|
||||||
|
|
||||||
const pagination = reactive<TablePagination>({
|
|
||||||
pageIndex: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
total: 0,
|
|
||||||
size: 'sm',
|
|
||||||
showTotal: true,
|
|
||||||
onChange(pageIndex: number, pageSize: number) {
|
|
||||||
pagination.pageIndex = pageIndex
|
|
||||||
pagination.pageSize = pageSize
|
|
||||||
searchHandler()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function searchHandler() {
|
|
||||||
tableSpin.value = true
|
|
||||||
TspApi.paging({
|
|
||||||
current: pagination.pageIndex ?? 1,
|
|
||||||
size: pagination.pageSize ?? 10,
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
pagination.pageIndex = res.data.current
|
|
||||||
pagination.pageSize = res.data.size
|
|
||||||
pagination.total = res.data.total
|
|
||||||
datasource.value = res.data.records
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
tableSpin.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const photoUploadStatus = ref<TspPhotoTypes.ObtainStatusResult>({})
|
|
||||||
|
|
||||||
const columns: TableColumn<TspTypes.TspData>[] = [
|
|
||||||
selectableColumn,
|
|
||||||
{
|
|
||||||
title: '名称',
|
|
||||||
dataKey: 'pointName',
|
|
||||||
customCell: 'pointName'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '所属街道',
|
|
||||||
dataKey: 'streetName',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '所属小区',
|
|
||||||
dataKey: 'microdistrict',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '所属物业',
|
|
||||||
dataKey: 'propertyManagement'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
watch(visible, (newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
searchHandler()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const computedTitle = () => {
|
|
||||||
const uploadDate = tspPhotoForm.get('uploadDate')?.getValue()
|
|
||||||
const pointName = tspPhotoForm.get('pointName')?.getValue()
|
|
||||||
return uploadDate == null || pointName == null ? '图片列表' : pointName + ' ' + times.format(times.parse(uploadDate, FMT.date), FMT.date_zh) + '上传的图片'
|
|
||||||
}
|
|
||||||
const photoListTitle = ref<string>('图片列表')
|
|
||||||
|
|
||||||
const photoList = ref<string[]>()
|
|
||||||
|
|
||||||
|
|
||||||
tspPhotoForm.get('tspId')?.watchValue(() => {
|
|
||||||
TspPhotoApi.obtainStatus(tspPhotoForm.getValue()).then(res => {
|
|
||||||
photoUploadStatus.value = res.data
|
|
||||||
})
|
|
||||||
})
|
|
||||||
tspPhotoForm.get('month')?.watchValue((month) => {
|
|
||||||
tspPhotoForm.get('day')?.setValue(0)
|
|
||||||
if (month == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tspPhotoForm.get('uploadDate')?.setValue(times.format(times.parse(month), FMT.date))
|
|
||||||
|
|
||||||
TspPhotoApi.obtainStatus(tspPhotoForm.getValue()).then(res => {
|
|
||||||
photoUploadStatus.value = res.data
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
function onClickDate(day: DayType) {
|
|
||||||
tspPhotoForm.get('day')?.setValue(day.day)
|
|
||||||
tspPhotoForm.get('uploadDate')?.setValue(`${day.year}-${day.month < 10 ? '0' + day.month : day.month}-${day.day < 10 ? '0' + day.day : day.day}`)
|
|
||||||
photoListTitle.value = computedTitle()
|
|
||||||
TspPhotoApi.listPhoto(tspPhotoForm.getValue())
|
|
||||||
.then(res => {
|
|
||||||
photoList.value = res.data?.photos ?? []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const files = ref([])
|
|
||||||
onMounted(() => {
|
|
||||||
renderCalendar()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="tsp-photo-wrapper">
|
<div class="tsp-photo-wrapper">
|
||||||
<div class="calendar-wrapper">
|
<PhotoCalendar ref="photoCalendar" v-model:tspPhotoData="tspPhotoData" status="edit"/>
|
||||||
<div class="calendar-title">
|
<PhotoList :pointName="tspPhotoData.pointName" :tspId="tspPhotoData.tspId"
|
||||||
<IxForm :control="tspPhotoForm" class="calendar-form" layout="inline">
|
:uploadDate="tspPhotoData.uploadDate" status="edit" @refresh="refresh"/>
|
||||||
<IxFormItem>
|
|
||||||
<IxPopover v-model:visible="visible" closable header="小区列表" placement="bottom" trigger="click">
|
|
||||||
<IxInput control="pointName" placeholder="请选择小区"/>
|
|
||||||
<template #content>
|
|
||||||
<IxTable v-model:selectedRowKeys="selectedRowKeys" :columns="columns" :dataSource="datasource" :pagination="pagination" :spin="tableSpin" get-key="id"/>
|
|
||||||
</template>
|
|
||||||
</IxPopover>
|
|
||||||
</IxFormItem>
|
|
||||||
<IxFormItem>
|
|
||||||
<IxDatePicker :disabled-date="disabledDate" control="month" type="month" @change="renderCalendar"/>
|
|
||||||
</IxFormItem>
|
|
||||||
</IxForm>
|
|
||||||
</div>
|
|
||||||
<table class="calendar">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th v-for="item in weekday" :key="'weekday-' + item" class="weekday">{{ item }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(item, index) in days" :key="'day-' + index">
|
|
||||||
<td v-for="(it, i) in item" :key="'day-' + i" :class="{blank:it == null}" class="day">
|
|
||||||
<div v-if="it != null" :class="{'active-day': it.day === tspPhotoForm.get('day')?.getValue()}" class="day-content" @click="onClickDate(it)">
|
|
||||||
<div class="day-number">{{ it.day }}</div>
|
|
||||||
<IxTagGroup v-if="photoUploadStatus[it.day+''] != null && photoUploadStatus[it.day+''] > 0" :gap="0" class="day-status">
|
|
||||||
<IxTag status="success">已上传</IxTag>
|
|
||||||
<IxTag status="success">{{ photoUploadStatus[it.day + ''] }}张</IxTag>
|
|
||||||
</IxTagGroup>
|
|
||||||
<IxTag v-else-if="photoUploadStatus[it.day+''] != null && photoUploadStatus[it.day+''] == 0" class="day-status" status="error">未上传</IxTag>
|
|
||||||
<div v-else class="day-status" status="error"></div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="photo-wrapper">
|
|
||||||
<div class="photo-title">
|
|
||||||
{{ photoListTitle }}
|
|
||||||
</div>
|
|
||||||
<div class="photo">
|
|
||||||
<IxImage v-for="(it,i) in photoList" :key="'photo--'+i" :src="it"/>
|
|
||||||
</div>
|
|
||||||
<div v-if="tspPhotoForm.get('day')?.getValue() !== 0" class="photo-bottom">
|
|
||||||
<IxUpload v-model:files="files" action="https://run.mocky.io/v3/7564bc4f-780e-43f7-bc58-467959ae3354" dragable>
|
|
||||||
<div class="drag-panel">
|
|
||||||
<IxIcon class="drag-panel-icon" name="upload"></IxIcon>
|
|
||||||
<p>拖拽上传</p>
|
|
||||||
</div>
|
|
||||||
<template #list>
|
|
||||||
<IxUploadFiles type="text"/>
|
|
||||||
</template>
|
|
||||||
</IxUpload>
|
|
||||||
<IxButton>提交</IxButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -261,131 +23,5 @@ onMounted(() => {
|
||||||
height: 100%
|
height: 100%
|
||||||
width: 100%
|
width: 100%
|
||||||
display flex
|
display flex
|
||||||
|
|
||||||
.calendar-wrapper {
|
|
||||||
flex 1
|
|
||||||
padding 1rem
|
|
||||||
box-sizing border-box
|
|
||||||
border-right: 1px solid rgb(211, 215, 222);
|
|
||||||
|
|
||||||
.calendar-form {
|
|
||||||
width 100%
|
|
||||||
height 4rem
|
|
||||||
|
|
||||||
:deep(.ix-form-item):first-child {
|
|
||||||
width 30%
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ix-form-item):nth-child(2) {
|
|
||||||
width 10%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar {
|
|
||||||
width 100%
|
|
||||||
height calc(100% - 4rem);
|
|
||||||
margin-top 1rem
|
|
||||||
box-sizing border-box
|
|
||||||
table-layout fixed
|
|
||||||
|
|
||||||
border-collapse: collapse;
|
|
||||||
border: 1px solid rgb(211, 215, 222);
|
|
||||||
|
|
||||||
thead {
|
|
||||||
height 4rem
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody {
|
|
||||||
height calc(100% - 4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.day {
|
|
||||||
border-top: 1px solid rgb(211, 215, 222);
|
|
||||||
|
|
||||||
&:not(.blank) {
|
|
||||||
border: 1px solid rgb(211, 215, 222);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.day-content {
|
|
||||||
cursor pointer
|
|
||||||
|
|
||||||
height 100%
|
|
||||||
width 100%
|
|
||||||
display flex
|
|
||||||
flex-direction column
|
|
||||||
justify-content space-around
|
|
||||||
padding 1rem
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active-day {
|
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.day-number {
|
|
||||||
font-size 3rem
|
|
||||||
font-weight bold
|
|
||||||
}
|
|
||||||
|
|
||||||
.day-status {
|
|
||||||
width 100%;
|
|
||||||
height 20px;
|
|
||||||
|
|
||||||
:deep(.ix-space-item) {
|
|
||||||
flex 1
|
|
||||||
|
|
||||||
& > span {
|
|
||||||
width 100%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo-wrapper {
|
|
||||||
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;
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo {
|
|
||||||
flex 1
|
|
||||||
width 100%;
|
|
||||||
padding 1rem
|
|
||||||
overflow-y 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import { get, } from '@/common/utils/http-util.ts'
|
import {
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
} from '@/common/utils/http-util.ts'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
save(data?: TspPhotoTypes.TspPhotoSaveParam) {
|
save(data?: TspPhotoTypes.TspPhotoSaveParam) {
|
||||||
return get<null>('/tsp_photo/save', data)
|
return post<null>('/tsp_photo/save', data)
|
||||||
},
|
},
|
||||||
listPhoto(data?: TspPhotoTypes.TspPhotoSearchParam) {
|
listPhoto(data?: TspPhotoTypes.TspPhotoSearchParam) {
|
||||||
return get<TspPhotoTypes.TspPhotoSearchResult>('/tsp_photo/list_photo', data)
|
return get<TspPhotoTypes.TspPhotoSearchResult>('/tsp_photo/list_photo', data)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
namespace TspPhotoTypes {
|
namespace TspPhotoTypes {
|
||||||
|
|
||||||
|
interface DayType {
|
||||||
|
year: number
|
||||||
|
month: number
|
||||||
|
day: number
|
||||||
|
status: 'uploaded' | 'unupload' | 'unknown'
|
||||||
|
photoCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface TspPhotoSearchParam {
|
interface TspPhotoSearchParam {
|
||||||
tspId?: string
|
tspId?: string
|
||||||
pointName?: string
|
pointName?: string
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import PhotoCalendar from '@/pages/tsp-photo/PhotoCalendar.vue'
|
||||||
|
import PhotoList from '@/pages/tsp-photo/PhotoList.vue'
|
||||||
|
import { nanoid } from 'nanoid'
|
||||||
|
|
||||||
|
const id = nanoid()
|
||||||
|
const show = ref(false)
|
||||||
|
const containerElement = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const tspPhotoData = ref<TspPhotoTypes.TspPhotoSearchParam>({})
|
||||||
|
const header = ref<string>('图片列表')
|
||||||
|
|
||||||
|
function closeHandler() {
|
||||||
|
containerElement.value!.style!.width = '0'
|
||||||
|
containerElement.value!.style!.height = '0'
|
||||||
|
tspPhotoData.value = {}
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open(tspId: string, pointName: string) {
|
||||||
|
tspPhotoData.value.tspId = tspId
|
||||||
|
tspPhotoData.value.pointName = pointName
|
||||||
|
show.value = true
|
||||||
|
containerElement.value!.style!.width = '100%'
|
||||||
|
containerElement.value!.style!.height = '100%'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :id="id" ref="containerElement" class="ix_modal-container">
|
||||||
|
<IxModal v-model:visible="show" :container="containerElement!"
|
||||||
|
:header="header" :mask="false"
|
||||||
|
:on-before-close="closeHandler"
|
||||||
|
type="default" width="100%">
|
||||||
|
<div class="photo-panel">
|
||||||
|
<PhotoCalendar ref="photoCalendar" v-model:tspPhotoData="tspPhotoData" status="view"/>
|
||||||
|
<PhotoList :pointName="tspPhotoData.pointName" :tspId="tspPhotoData.tspId"
|
||||||
|
:uploadDate="tspPhotoData.uploadDate" status="view"/>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<IxButton mode="primary" @click="closeHandler">关闭</IxButton>
|
||||||
|
</template>
|
||||||
|
</IxModal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.ix_modal-container {
|
||||||
|
position absolute
|
||||||
|
top 0
|
||||||
|
left 0
|
||||||
|
|
||||||
|
:deep(.ix-modal) {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
|
||||||
|
.ix-modal-body {
|
||||||
|
width 100%
|
||||||
|
overflow hidden
|
||||||
|
border-top: 1px dashed #E1E5EB;
|
||||||
|
border-bottom: 1px dashed #E1E5EB;
|
||||||
|
|
||||||
|
.photo-panel {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
display flex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ix-modal-footer {
|
||||||
|
justify-content center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -6,11 +6,11 @@ import { TablePagination } from '@idux/components/table/src/types'
|
||||||
import CreateTsp from '@/pages/tsp/create-tsp.vue'
|
import CreateTsp from '@/pages/tsp/create-tsp.vue'
|
||||||
import TspApi from '@/pages/tsp/tsp-api.ts'
|
import TspApi from '@/pages/tsp/tsp-api.ts'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import VideoPanel from '@/pages/tsp/VideoPanel.vue'
|
import PhotoPanel from '@/pages/tsp/PhotoPanel.vue'
|
||||||
import Toast from '@/components/toast'
|
|
||||||
|
|
||||||
const createTsp = ref<InstanceType<typeof CreateTsp> | null>(null)
|
const createTsp = ref<InstanceType<typeof CreateTsp> | null>(null)
|
||||||
const videoPanel = ref<InstanceType<typeof VideoPanel> | null>(null)
|
// const videoPanel = ref<InstanceType<typeof VideoPanel> | null>(null)
|
||||||
|
const photoPanel = ref<InstanceType<typeof PhotoPanel> | null>(null)
|
||||||
const dataSource: SelectData[] = [
|
const dataSource: SelectData[] = [
|
||||||
{key: '', label: '全部状态'},
|
{key: '', label: '全部状态'},
|
||||||
{key: 'ZhengChang', label: '正常运营'},
|
{key: 'ZhengChang', label: '正常运营'},
|
||||||
|
|
@ -92,12 +92,15 @@ function searchHandler() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVideo(record: TspTypes.TspData) {
|
/* function playVideo(record: TspTypes.TspData) {
|
||||||
if (record.videoUrl == null) {
|
if (record.videoUrl == null) {
|
||||||
Toast.error('该收纳点未配置视频监控')
|
Toast.error('该收纳点未配置视频监控')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
videoPanel.value?.open(record.videoUrl, record.pointName)
|
// videoPanel.value?.open(record.videoUrl, record.pointName)
|
||||||
|
} */
|
||||||
|
function playPhoto(record: TspTypes.TspData) {
|
||||||
|
photoPanel.value?.open(record.id, record.pointName)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -117,7 +120,7 @@ onMounted(() => {
|
||||||
<div>
|
<div>
|
||||||
<div>收纳点总数</div>
|
<div>收纳点总数</div>
|
||||||
<div>{{ statisticsResult.totalCount }}</div>
|
<div>{{ statisticsResult.totalCount }}</div>
|
||||||
<div><i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.totalCountGrowthRate }}%</div>
|
<div><!--<i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.totalCountGrowthRate }}%--></div>
|
||||||
</div>
|
</div>
|
||||||
<Iconfont name="map-pin" wrapper/>
|
<Iconfont name="map-pin" wrapper/>
|
||||||
</IxCard>
|
</IxCard>
|
||||||
|
|
@ -125,7 +128,7 @@ onMounted(() => {
|
||||||
<div>
|
<div>
|
||||||
<div>正常运营数量</div>
|
<div>正常运营数量</div>
|
||||||
<div>{{ statisticsResult.onlineCount }}</div>
|
<div>{{ statisticsResult.onlineCount }}</div>
|
||||||
<div><i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.onlineCountGrowthRate }}%</div>
|
<div><!--<i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.onlineCountGrowthRate }}%--></div>
|
||||||
</div>
|
</div>
|
||||||
<Iconfont name="check-circle-fill" wrapper/>
|
<Iconfont name="check-circle-fill" wrapper/>
|
||||||
</IxCard>
|
</IxCard>
|
||||||
|
|
@ -133,7 +136,7 @@ onMounted(() => {
|
||||||
<div>
|
<div>
|
||||||
<div>非正常运营数量</div>
|
<div>非正常运营数量</div>
|
||||||
<div>{{ statisticsResult.offlineCount }}</div>
|
<div>{{ statisticsResult.offlineCount }}</div>
|
||||||
<div><i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.offlineCountGrowthRate }}%</div>
|
<div><!--<i class="iconfont icon-arrow-up"></i>较上月增长 {{ statisticsResult.offlineCountGrowthRate }}%--></div>
|
||||||
</div>
|
</div>
|
||||||
<Iconfont name="exclamationcircle-f" wrapper/>
|
<Iconfont name="exclamationcircle-f" wrapper/>
|
||||||
</IxCard>
|
</IxCard>
|
||||||
|
|
@ -166,7 +169,8 @@ onMounted(() => {
|
||||||
<span>{{ record.pointName }}</span>
|
<span>{{ record.pointName }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #action="{record}">
|
<template #action="{record}">
|
||||||
<IxButton class="video-btn" icon="eye" mode="text" @click="playVideo(record)">查看监控</IxButton>
|
<!--<IxButton class="video-btn" icon="eye" mode="text" @click="playVideo(record)">查看监控</IxButton>-->
|
||||||
|
<IxButton class="video-btn" icon="eye" mode="text" @click="playPhoto(record)">查看照片</IxButton>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{record}">
|
<template #status="{record}">
|
||||||
<IxTag v-if="record.status === 'ZhengChang'" status="success">{{ record.statusTxt }}</IxTag>
|
<IxTag v-if="record.status === 'ZhengChang'" status="success">{{ record.statusTxt }}</IxTag>
|
||||||
|
|
@ -175,7 +179,8 @@ onMounted(() => {
|
||||||
</IxTable>
|
</IxTable>
|
||||||
</IxCard>
|
</IxCard>
|
||||||
<CreateTsp ref="createTsp"/>
|
<CreateTsp ref="createTsp"/>
|
||||||
<VideoPanel ref="videoPanel"/>
|
<!--<VideoPanel ref="videoPanel"/>-->
|
||||||
|
<PhotoPanel ref="photoPanel"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ defineExpose({
|
||||||
</template>
|
</template>
|
||||||
</IxModal>
|
</IxModal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue