358 lines
8.4 KiB
Vue
358 lines
8.4 KiB
Vue
<template>
|
|
<div class="guoYuSheShiShuJuHistory-page">
|
|
<GuoYuSheShiShuJuHistorySearch
|
|
ref="searchRef"
|
|
class="search-container"
|
|
:guoyuStatus="guoyuStatus"
|
|
:direction="direction"
|
|
@reset="handleReset"
|
|
@search-finish="handleSearchFinish"
|
|
/>
|
|
|
|
<BasicTable
|
|
ref="tableRef"
|
|
:columns="columns"
|
|
:list-url="getFishDraftPage"
|
|
:search-params="{}"
|
|
:transform-data="customTransform"
|
|
>
|
|
<template #action="{ record }">
|
|
<div class="flex">
|
|
<a-button type="link" size="small" @click="handleView(record)"
|
|
>查看</a-button
|
|
>
|
|
</div>
|
|
</template>
|
|
</BasicTable>
|
|
<!-- 预览媒体组件 -->
|
|
<PreviewMedia
|
|
ref="previewMediaRef"
|
|
v-model:visible="mediaPreviewVisible"
|
|
:previewList="previewList"
|
|
:previewListIndex="previewListIndex"
|
|
:videoPreviewTitle="videoPreviewTitle"
|
|
/>
|
|
|
|
<EditModal
|
|
ref="editModalRef"
|
|
v-model:visible="editModalVisible"
|
|
:is-view="true"
|
|
:direction="direction"
|
|
:initial-values="currentRecord"
|
|
@cancel="editModalCancel"
|
|
@preview-click="handlePreviewClick"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, computed, onMounted, h, nextTick } from 'vue';
|
|
import BasicTable from '@/components/BasicTable/index.vue';
|
|
import PreviewMedia from '@/components/previewMedia/index.vue';
|
|
import GuoYuSheShiShuJuHistorySearch from './guoYuSheShiShuJuHistorySearch.vue';
|
|
import EditModal from '../guoYuSheShiShuJuTianBao/guoYuSheShiShuJuTianBaoForm.vue';
|
|
import { getFishDraftPage } from '@/api/guoYuSheShiShuJuTianBao';
|
|
import { Tag } from 'ant-design-vue';
|
|
import { getDictItemsByCode } from '@/api/dict';
|
|
|
|
const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;
|
|
|
|
interface FormData {
|
|
[key: string]: any;
|
|
}
|
|
|
|
interface ColumnConfig {
|
|
dataIndex: string;
|
|
key: string;
|
|
title: string;
|
|
width?: number;
|
|
fixed?: string;
|
|
customRender?: (text: any, record: any) => any;
|
|
}
|
|
|
|
const tableRef = ref<any>(null);
|
|
|
|
const direction = ref<any>([]);
|
|
const guoyuStatus = ref<any>([]);
|
|
|
|
const baseColumnsConfig: ColumnConfig[] = [
|
|
{
|
|
dataIndex: 'rvnm',
|
|
key: 'rvnm',
|
|
title: '流域',
|
|
width: 120,
|
|
fixed: 'left'
|
|
},
|
|
{
|
|
dataIndex: 'ennm',
|
|
key: 'ennm',
|
|
title: '电站名称',
|
|
width: 120,
|
|
fixed: 'left'
|
|
},
|
|
{
|
|
dataIndex: 'stnm',
|
|
key: 'stnm',
|
|
title: '过鱼设施名称',
|
|
width: 150,
|
|
fixed: 'left'
|
|
},
|
|
{ dataIndex: 'strdt', key: 'strdt', title: '过鱼时间', width: 150 },
|
|
{ dataIndex: 'ftpName', key: 'ftpName', title: '鱼种类', width: 120 },
|
|
{
|
|
dataIndex: 'isfs',
|
|
key: 'isfs',
|
|
title: '是否鱼苗',
|
|
width: 74,
|
|
customRender: ({ text }: any) => {
|
|
const isYes = text === 1 || text === '1';
|
|
return h(
|
|
Tag,
|
|
{
|
|
color: isYes ? 'success' : 'error',
|
|
style: { margin: 0 }
|
|
},
|
|
() => (isYes ? '是' : '否')
|
|
);
|
|
}
|
|
},
|
|
{
|
|
dataIndex: 'direction',
|
|
key: 'direction',
|
|
title: '游向',
|
|
width: 80,
|
|
customRender: ({ text }: any) =>
|
|
direction.value.find((item: any) => item.itemCode === text)?.dictName ||
|
|
'-'
|
|
},
|
|
{ dataIndex: 'fcnt', key: 'fcnt', title: '过鱼数量(尾)', width: 120 },
|
|
{ dataIndex: 'fsz', key: 'fsz', title: '体长(cm)', width: 110 },
|
|
{ dataIndex: 'fwet', key: 'fwet', title: '平均体重(g)', width: 110 },
|
|
{ dataIndex: 'wt', key: 'wt', title: '水温(℃)', width: 80 },
|
|
{ dataIndex: 'tm', key: 'tm', title: '填报时间', width: 150 },
|
|
{
|
|
dataIndex: 'status',
|
|
key: 'status',
|
|
title: '状态',
|
|
width: 74,
|
|
customRender: ({ text }: any) => {
|
|
let data = guoyuStatus.value.find((item: any) => item.itemCode === text);
|
|
return h(
|
|
Tag,
|
|
{
|
|
color: data?.custom1 || 'error'
|
|
},
|
|
() => data?.dictName || '-'
|
|
);
|
|
}
|
|
}
|
|
];
|
|
|
|
const editModalVisible = ref(false);
|
|
const currentRecord = ref<FormData | null>(null);
|
|
|
|
const mediaPreviewVisible = ref(false);
|
|
const videoPreviewTitle = ref('视频预览');
|
|
|
|
interface MediaItem {
|
|
id: string;
|
|
type: 'image' | 'video';
|
|
name: string;
|
|
url: string;
|
|
}
|
|
|
|
const previewList = ref<MediaItem[]>([]);
|
|
const previewListIndex = ref(0);
|
|
const columns = computed(() => {
|
|
return [
|
|
...baseColumnsConfig.map(col => {
|
|
if (col.dataIndex === 'level5') {
|
|
return {
|
|
...col,
|
|
customRender: ({ text }: any) => {
|
|
if (!text) return '-';
|
|
return `<span style="color:#52c41a; cursor:pointer">查看图片</span>`;
|
|
}
|
|
};
|
|
}
|
|
if (col.dataIndex === 'level6') {
|
|
return {
|
|
...col,
|
|
customRender: ({ text }: any) => {
|
|
if (!text) return '-';
|
|
return `<span style="color:#1890ff; cursor:pointer">播放视频</span>`;
|
|
}
|
|
};
|
|
}
|
|
return { ...col, visible: true };
|
|
}),
|
|
{
|
|
title: '操作',
|
|
key: 'action',
|
|
dataIndex: 'action',
|
|
fixed: 'right',
|
|
width: 100,
|
|
align: 'center',
|
|
slots: { customRender: 'action' }
|
|
}
|
|
];
|
|
});
|
|
|
|
const handleView = (record: any) => {
|
|
currentRecord.value = { ...record };
|
|
editModalVisible.value = true;
|
|
};
|
|
|
|
const editModalCancel = () => {
|
|
editModalVisible.value = false;
|
|
};
|
|
|
|
const handlePreviewClick = (record: any, type: string, index: number) => {
|
|
const mixedList: MediaItem[] = [];
|
|
if (type === 'image') {
|
|
videoPreviewTitle.value = '图片预览';
|
|
const nameList = JSON.parse(JSON.stringify(record)).picpthList;
|
|
nameList.forEach((item: any) => {
|
|
mixedList.push({
|
|
id: record.id,
|
|
type: 'image',
|
|
name: item.name,
|
|
url: item.url
|
|
});
|
|
});
|
|
} else if (type === 'video') {
|
|
videoPreviewTitle.value = '视频预览';
|
|
const nameList = JSON.parse(JSON.stringify(record)).vdpthList;
|
|
nameList.forEach((item: any) => {
|
|
mixedList.push({
|
|
id: record.id,
|
|
type: 'video',
|
|
name: item.name,
|
|
url: item.url
|
|
});
|
|
});
|
|
}
|
|
|
|
mediaPreviewVisible.value = true;
|
|
previewListIndex.value = index;
|
|
nextTick(() => {
|
|
previewList.value = mixedList;
|
|
});
|
|
};
|
|
|
|
const customTransform = (res: any) => {
|
|
const rawRecords = res?.data?.records || [];
|
|
const modifiedRecords = rawRecords.map((item: any) => {
|
|
return {
|
|
...item,
|
|
picpthList: item.picpth
|
|
? item.picpth.split(',').map((item: string) => baseUrl + '/?' + item) ||
|
|
[]
|
|
: []
|
|
};
|
|
});
|
|
return {
|
|
records: modifiedRecords,
|
|
total: res?.data?.total || 0
|
|
};
|
|
};
|
|
|
|
const handleReset = values => {
|
|
handleSearchFinish(values);
|
|
};
|
|
|
|
const handleSearchFinish = (values: any) => {
|
|
const filters = [
|
|
values.ftp && {
|
|
field: 'ftp',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.ftp
|
|
},
|
|
{
|
|
field: 'strdt',
|
|
operator: 'gte',
|
|
dataType: 'date',
|
|
value: values.strdt[0] + ' 00:00:00'
|
|
},
|
|
{
|
|
field: 'strdt',
|
|
operator: 'lte',
|
|
dataType: 'date',
|
|
value: values.strdt[1] + ' 23:59:59'
|
|
},
|
|
values.direction && {
|
|
field: 'direction',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.direction
|
|
},
|
|
{
|
|
field: 'status',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: 'APPROVED'
|
|
},
|
|
values.stcd && {
|
|
field: 'stcd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.stcd
|
|
},
|
|
values.rstcd && {
|
|
field: 'rstcd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.rstcd
|
|
},
|
|
values.rvcd !== 'all' && {
|
|
field: 'rvcd',
|
|
operator: 'eq',
|
|
dataType: 'string',
|
|
value: values.rvcd
|
|
}
|
|
].filter(Boolean);
|
|
|
|
const filter = {
|
|
logic: 'and',
|
|
filters: filters
|
|
};
|
|
tableRef.value?.getList(filter);
|
|
};
|
|
|
|
onMounted(() => {
|
|
getDictItemsByCode({ dictCode: 'direction' }).then(res => {
|
|
direction.value = res.data;
|
|
});
|
|
|
|
getDictItemsByCode({ dictCode: 'approvalStatus' }).then(res => {
|
|
guoyuStatus.value.length = 0;
|
|
res.data.forEach((item: any) => {
|
|
if (item.itemCode == 'APPROVED') {
|
|
guoyuStatus.value.push(item);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.guoYuSheShiShuJuHistory-page {
|
|
position: relative;
|
|
z-index: 900;
|
|
pointer-events: all;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #ffffff;
|
|
padding: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.search-container {
|
|
flex-shrink: 0;
|
|
}
|
|
</style>
|