数据填报bug修改,添加预览视频图片公共组件,删除无用预览改为公共组件
This commit is contained in:
parent
0d5c79bd2e
commit
f289059628
@ -15,6 +15,6 @@ VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
||||
|
||||
|
||||
# 开发环境导入预览地址
|
||||
VITE_APP_BASE_API_URL = 'http://172.16.21.14:8096'
|
||||
VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093'
|
||||
## 开发环境预览 图片视频地址
|
||||
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'
|
||||
|
||||
@ -32,5 +32,5 @@ module.exports = {
|
||||
// Vue文件脚本和样式标签缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
|
||||
endOfLine: 'lf'
|
||||
endOfLine: 'lf',
|
||||
};
|
||||
|
||||
BIN
frontend/dist.rar
Normal file
BIN
frontend/dist.rar
Normal file
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 分页查询过鱼数据
|
||||
export function getFishDraftPage(data:any) {
|
||||
export function getFishDraftPage(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/page',
|
||||
method: 'post',
|
||||
@ -9,7 +9,7 @@ export function getFishDraftPage(data:any) {
|
||||
});
|
||||
}
|
||||
//新增过鱼数据
|
||||
export function addFishDraft(queryParams:any) {
|
||||
export function addFishDraft(queryParams: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/saveDraft',
|
||||
method: 'post',
|
||||
@ -17,7 +17,7 @@ export function addFishDraft(queryParams:any) {
|
||||
});
|
||||
}
|
||||
//修改过鱼数据
|
||||
export function editFishDraft(queryParams:any) {
|
||||
export function editFishDraft(queryParams: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/updateDraft',
|
||||
method: 'post',
|
||||
@ -25,7 +25,7 @@ export function editFishDraft(queryParams:any) {
|
||||
});
|
||||
}
|
||||
//删除 过鱼数据
|
||||
export function delFishDraft(data:any) {
|
||||
export function delFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchRemoveDraft',
|
||||
method: 'post',
|
||||
@ -33,7 +33,7 @@ export function delFishDraft(data:any) {
|
||||
});
|
||||
}
|
||||
//提交过鱼数据
|
||||
export function submitFishDraft(data:any) {
|
||||
export function submitFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/submitDrafts',
|
||||
method: 'post',
|
||||
@ -44,11 +44,11 @@ export function submitFishDraft(data:any) {
|
||||
export function batchApproveAll() {
|
||||
return request({
|
||||
url: '/data/fishDraft/submitDraftsAll',
|
||||
method: 'post',
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
//审批过鱼数据
|
||||
export function successFishDraft(data:any) {
|
||||
export function successFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchApprove',
|
||||
method: 'post',
|
||||
@ -56,7 +56,7 @@ export function successFishDraft(data:any) {
|
||||
});
|
||||
}
|
||||
//驳回过鱼数据
|
||||
export function rejectFishDraft(data:any) {
|
||||
export function rejectFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/reject',
|
||||
method: 'post',
|
||||
@ -64,7 +64,7 @@ export function rejectFishDraft(data:any) {
|
||||
});
|
||||
}
|
||||
// 导入zip
|
||||
export function importFishZip(data:FormData) {
|
||||
export function importFishZip(data: FormData) {
|
||||
return request({
|
||||
url: '/data/fishDraft/importZip',
|
||||
method: 'post',
|
||||
@ -73,7 +73,7 @@ export function importFishZip(data:FormData) {
|
||||
});
|
||||
}
|
||||
// 取消导入任务
|
||||
export function cancelImportTask(data:any) {
|
||||
export function cancelImportTask(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/cancelImport',
|
||||
method: 'post',
|
||||
@ -95,7 +95,7 @@ export function getLastImportResult() {
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
export function deleteFile(params:any) {
|
||||
export function deleteFile(params: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/deleteFile',
|
||||
method: 'get',
|
||||
@ -103,10 +103,18 @@ export function deleteFile(params:any) {
|
||||
});
|
||||
}
|
||||
// 批量保存草稿
|
||||
export function batchSaveDraft(data:any) {
|
||||
export function batchSaveDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchSaveDraft',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 批量删除 审批已驳回的
|
||||
export function batchRemoveDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/approvalMain/batchDelete',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
@ -34,8 +34,6 @@ interface Props {
|
||||
rowKey?: string;
|
||||
// 外部传入的搜索/过滤参数,变化时会自动触发刷新
|
||||
searchParams?: Record<string, any>;
|
||||
// 是否只加载一次,默认 false
|
||||
isOneLoad?: boolean;
|
||||
// 默认每页显示数量
|
||||
defaultPageSize?: number;
|
||||
getCheckboxProps?: (record: any) => any;
|
||||
@ -46,7 +44,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
enableRowSelection: false,
|
||||
rowKey: "id",
|
||||
data: () => ([]),
|
||||
isOneLoad: true,
|
||||
searchParams: () => ({}),
|
||||
defaultPageSize: 20,
|
||||
getCheckboxProps: undefined,
|
||||
@ -143,7 +140,6 @@ const getList = async (filter?: Record<string, any>) => {
|
||||
totalCount = res?.data?.total || res?.total || 0;
|
||||
}
|
||||
|
||||
|
||||
tableData.value = records;
|
||||
total.value = totalCount;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -10,10 +10,10 @@
|
||||
class="map-modal"
|
||||
>
|
||||
<a-tabs :active-key="currentActiveKey" @change="onTabChange">
|
||||
<a-tab-pane v-for="tab in tabsConfig" :key="tab.key" :tab="tab.title">
|
||||
<a-tab-pane v-for="tab in tabsConfig" :key="tab.key" :tab="tab.name">
|
||||
<div class="content">
|
||||
<!-- 基本信息组件 -->
|
||||
<BasicInfo v-if="currentActiveKey === 'basicInfo'" :url="tab.url" />
|
||||
<BasicInfo v-if="currentActiveKey === 'basicInfo'" :url="tab.url" />
|
||||
<!-- 地图组件 -->
|
||||
<!-- <MapView v-else-if="currentActiveKey === 'mapView'" :data="modalData" /> -->
|
||||
<!-- 周边配套组件 -->
|
||||
@ -23,6 +23,14 @@
|
||||
/> -->
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<template #rightExtra>
|
||||
<a-tooltip :title="!isEngConfig ? '' : '该电站无专题配置'">
|
||||
<a-button type="primary" :disabled="isEngConfig">
|
||||
<i class="icon iconfont icon-topic mr-[5px]"></i>
|
||||
电站专题
|
||||
</a-button
|
||||
></a-tooltip>
|
||||
</template>
|
||||
</a-tabs>
|
||||
</a-modal>
|
||||
</template>
|
||||
@ -31,6 +39,13 @@
|
||||
import { ref, watch } from "vue";
|
||||
// 导入预定义的 Tab 内容组件
|
||||
import BasicInfo from "./components/BasicInfo.vue";
|
||||
import { useModelStore } from "@/store/modules/model";
|
||||
import { handleTabs } from "./setting.config";
|
||||
|
||||
const modelStore = useModelStore();
|
||||
const tabsConfig = ref([]);
|
||||
// 判断是否显示电站专题配置
|
||||
const isEngConfig = ref(true);
|
||||
// import MapView from './components/MapView.vue';
|
||||
// import SurroundingInfo from './components/SurroundingInfo.vue';
|
||||
|
||||
@ -46,7 +61,6 @@ const props = defineProps<{
|
||||
visible: boolean;
|
||||
title?: string;
|
||||
activeKey?: string; // 外部控制的当前激活 tab
|
||||
tabsConfig?: TabItem[]; // Tab 配置列表,用于生成 Tab 头
|
||||
data?: any; // 可选:传递给内部组件的数据
|
||||
}>();
|
||||
|
||||
@ -71,7 +85,13 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => modelStore.params,
|
||||
(newVal) => {
|
||||
tabsConfig.value = handleTabs(newVal);
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
// 监听内部 tab 切换
|
||||
const onTabChange = (key: string) => {
|
||||
currentActiveKey.value = key;
|
||||
|
||||
@ -12,95 +12,98 @@
|
||||
// import { Utility } from '@zebras/qgc-share/utils/Utility'
|
||||
|
||||
// // 水电站 √
|
||||
// const ENGTabs: Array<any> = [
|
||||
// {
|
||||
// name: '基础信息',
|
||||
// key: 'basicInfo',
|
||||
// type: 'basic',
|
||||
// url: '/bbi/siteBipc/getSiteBasicInfo'
|
||||
// },
|
||||
// {
|
||||
// name: '阶段属性',
|
||||
// key: 'basicFilter',
|
||||
// type: 'basicFilter',
|
||||
// url: '/eng/engBasisInfo/getEngBaseInfo'
|
||||
// },
|
||||
// {
|
||||
// name: '实时视频',
|
||||
// key: 'videoInfo',
|
||||
// type: 'video',
|
||||
// url: '/video/dataStcdFrame/getVideoMonitorList'
|
||||
// },
|
||||
// {
|
||||
// name: '全景影像',
|
||||
// key: 'panoramaInfo',
|
||||
// type: 'panorama'
|
||||
// },
|
||||
// {
|
||||
// name: '监测数据',
|
||||
// key: 'monitorInfo',
|
||||
// type: 'tabsWithTwo',
|
||||
// code: 'dzxq.tabs.jcsj'
|
||||
// },
|
||||
// {
|
||||
// name: '预警提示',
|
||||
// key: 'tableTabs',
|
||||
// type: 'tableTabs',
|
||||
// code: 'dzxq-yjts',
|
||||
// tabs: [
|
||||
// {
|
||||
// name: '设计参数变更提示',
|
||||
// key: 'DesignParameterChangePrompt',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/GetKendoList'
|
||||
// },
|
||||
// {
|
||||
// name: '施工期环保措施落实预警',
|
||||
// key: 'ImplementEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/sgqhbss/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '环保设施建设预警',
|
||||
// key: 'ConstructionEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/hbssjs/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '环保设施运行预警',
|
||||
// key: 'RunEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/hbssyx/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '鱼类放流预警',
|
||||
// key: 'ReleaseEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/ylfl/GetKendoListCust'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// Session.getAppCode() === 'hbb' ? {
|
||||
// name: '查看报告',
|
||||
// key: 'attachment',
|
||||
// type: 'attachment'
|
||||
// } : null,
|
||||
// {
|
||||
// name: '批复文件',
|
||||
// key: 'approval',
|
||||
// type: 'approval'
|
||||
// },
|
||||
// // {
|
||||
// // name: "特征曲线",
|
||||
// // key: "characteristicCurve",
|
||||
// // type: "characteristicCurve"
|
||||
// // }
|
||||
// ].filter(Boolean)
|
||||
const ENGTabs: Array<any> = [
|
||||
{
|
||||
name: '基础信息',
|
||||
key: 'basicInfo',
|
||||
type: 'basic',
|
||||
url: '/bbi/siteBipc/getSiteBasicInfo'
|
||||
},
|
||||
{
|
||||
name: '阶段属性',
|
||||
key: 'basicFilter',
|
||||
type: 'basicFilter',
|
||||
url: '/eng/engBasisInfo/getEngBaseInfo'
|
||||
},
|
||||
{
|
||||
name: '实时视频',
|
||||
key: 'videoInfo',
|
||||
type: 'video',
|
||||
url: '/video/dataStcdFrame/getVideoMonitorList'
|
||||
},
|
||||
{
|
||||
name: '全景影像',
|
||||
key: 'panoramaInfo',
|
||||
type: 'panorama'
|
||||
},
|
||||
{
|
||||
name: '监测数据',
|
||||
key: 'monitorInfo',
|
||||
type: 'tabsWithTwo',
|
||||
code: 'dzxq.tabs.jcsj'
|
||||
},
|
||||
{
|
||||
name: '预警提示',
|
||||
key: 'tableTabs',
|
||||
type: 'tableTabs',
|
||||
code: 'dzxq-yjts',
|
||||
tabs: [
|
||||
{
|
||||
name: '设计参数变更提示',
|
||||
key: 'DesignParameterChangePrompt',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl: '/dec-lygk-base-server/base/engWarning/GetKendoList'
|
||||
},
|
||||
{
|
||||
name: '施工期环保措施落实预警',
|
||||
key: 'ImplementEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/sgqhbss/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '环保设施建设预警',
|
||||
key: 'ConstructionEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/hbssjs/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '环保设施运行预警',
|
||||
key: 'RunEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/hbssyx/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '鱼类放流预警',
|
||||
key: 'ReleaseEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl: '/dec-lygk-base-server/base/engWarning/ylfl/GetKendoListCust'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '查看报告',
|
||||
key: 'attachment',
|
||||
type: 'attachment'
|
||||
},
|
||||
{
|
||||
name: '批复文件',
|
||||
key: 'approval',
|
||||
type: 'approval'
|
||||
}
|
||||
// {
|
||||
// name: "特征曲线",
|
||||
// key: "characteristicCurve",
|
||||
// type: "characteristicCurve"
|
||||
// }
|
||||
].filter(Boolean);
|
||||
// // 水电站生态流量 √
|
||||
// const ENGEQTabs: Array<any> = [
|
||||
// {
|
||||
@ -1076,15 +1079,15 @@
|
||||
// // }
|
||||
// // ]
|
||||
|
||||
// //其他配置
|
||||
// const CommonTabs: any = [
|
||||
// {
|
||||
// name: '基础信息',
|
||||
// key: 'basicInfo',
|
||||
// type: 'basic',
|
||||
// url: '/bbi/siteBipc/getSiteBasicInfo'
|
||||
// }
|
||||
// ]
|
||||
// 其他配置
|
||||
const CommonTabs: any = [
|
||||
{
|
||||
name: '基础信息',
|
||||
key: 'basicInfo',
|
||||
type: 'basic',
|
||||
url: '/bbi/siteBipc/getSiteBasicInfo'
|
||||
}
|
||||
];
|
||||
|
||||
// // 气象站
|
||||
// const WeatherTabs: any = [
|
||||
@ -1139,157 +1142,158 @@
|
||||
// ]
|
||||
|
||||
// //mway : 1-是人工 , 2-是自动 dtinType: 0-自建 1-国家 2-人工
|
||||
// const handleTabs = (modaldata: any) => {
|
||||
// console.log('modaldata', modaldata)
|
||||
// if (!modaldata?.sttp) return
|
||||
// let sttp = modaldata?.sttp ? modaldata?.sttp.toUpperCase() : ''
|
||||
// switch (sttp) {
|
||||
// case 'ENG':
|
||||
// if (modaldata?.eqtp == 'QEC') {
|
||||
// const { page } = Utility.parseQueryString()
|
||||
// if (page == 'shengTaiLiuLiangManZuQingKuangJiangJu') {
|
||||
// return ENGEQTabsJuangJu
|
||||
// } else {
|
||||
// return ENGEQTabs
|
||||
// }
|
||||
// } else {
|
||||
// return Session.getAppCode() === 'hbb' ? ENGTabs.filter((e) => e.name !== '阶段属性') : ENGTabs
|
||||
// }
|
||||
// case 'ENG_ALARM':
|
||||
// return DZGJ
|
||||
// case 'EQ':
|
||||
// return EQTabs
|
||||
// case 'DW':
|
||||
// case 'DW_1':
|
||||
// case 'DW_2':
|
||||
// case 'DW_3':
|
||||
// case 'DW_4':
|
||||
// case 'DW_5':
|
||||
// return DWTabs
|
||||
// case 'FP': //todo,后续再删除多余代码
|
||||
// case 'FP_1': //todo,后续再删除多余代码
|
||||
// // case "FP_2": //todo,后续再删除多余代码
|
||||
// case 'FP_3': //todo,后续再删除多余代码
|
||||
// case 'FP_4': //todo,后续再删除多余代码
|
||||
// // case "FP_5": //todo,后续再删除多余代码
|
||||
// if (Session.getAppCode() === 'hbb') {
|
||||
// // mway为2的时侯显示在线监测数据
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return [
|
||||
// ...FPTabs1 //建设情况
|
||||
// ]
|
||||
// } else {
|
||||
// if (modaldata.mway != 2) {
|
||||
// return FPTabs.filter((item) => item.name !== '在线监测数据')
|
||||
// } else {
|
||||
// return [
|
||||
// ...FPTabs //有监测数据
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return [
|
||||
// ...FPTabs1
|
||||
// // {
|
||||
// // name: "系统运行记录",
|
||||
// // key: "FishSystemRunState", //Normal1
|
||||
// // type: "FishSystemRunState", //Normal
|
||||
// // tabs: []
|
||||
// // }
|
||||
// ]
|
||||
// } else {
|
||||
// return [
|
||||
// ...FPTabs
|
||||
// // {
|
||||
// // name: "系统运行记录",
|
||||
// // key: "FishSystemRunState", //Normal1
|
||||
// // type: "FishSystemRunState", //Normal
|
||||
// // tabs: []
|
||||
// // }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// case 'FP_2': //todo,后续再删除多余代码
|
||||
// case 'FP_5': //todo,后续再删除多余代码
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return FPTabs1
|
||||
// } else {
|
||||
// return FPTabs
|
||||
// }
|
||||
// case 'ZQ':
|
||||
// return ZQTabs
|
||||
// case 'FB':
|
||||
// if (modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return FBTabs1
|
||||
// } else {
|
||||
// return FBTabs
|
||||
// }
|
||||
// case 'FH':
|
||||
// return FHTabs
|
||||
// case 'VD_FB':
|
||||
// case 'VD_FP':
|
||||
// case 'VD_SG':
|
||||
// case 'VD_VP':
|
||||
// case 'VD_EQ':
|
||||
// case 'VD_DW':
|
||||
// case 'VD_FH':
|
||||
// case 'VD_OTWE':
|
||||
// case 'VD_OTTE':
|
||||
// case 'VD_FBP':
|
||||
// case 'VD_FC':
|
||||
// case 'VD_WQ':
|
||||
// case 'VD_TE':
|
||||
// case 'VD_WE':
|
||||
// case 'VD_EQS':
|
||||
// case 'VD_WT':
|
||||
// case 'VD_FBFM':
|
||||
// case 'VD_FBI':
|
||||
// case 'VD_PR':
|
||||
// case 'VD_FPB':
|
||||
// case 'VD_GZFC':
|
||||
// case 'VD_FPC':
|
||||
// case 'VD_VA':
|
||||
// case 'VD':
|
||||
// return videoTabs
|
||||
// case 'VD_SN':
|
||||
// case 'VD_WVD':
|
||||
// return noLiveVideoTabs
|
||||
// case 'VP':
|
||||
// return VPTabs
|
||||
// case 'VA':
|
||||
// return VATabs
|
||||
// case 'WQFB':
|
||||
// return WQFBTabs
|
||||
// case 'WQ':
|
||||
// const _tabs = [...WQTabs]
|
||||
// if (modaldata?.dtinType == 2 || modaldata?.dtinType == 1) _tabs.splice(2, 1)//国家站 人工站把视频tab去除
|
||||
// return _tabs
|
||||
// case 'WQDTA':
|
||||
// return WQDTATabs
|
||||
// case 'LL':
|
||||
// return FLOWTabs
|
||||
// case 'WT':
|
||||
// case 'WTRV':
|
||||
// if (modaldata.enfc == '1') {
|
||||
// return WTTabs1
|
||||
// } else {
|
||||
// return WTTabs
|
||||
// }
|
||||
// case 'WE':
|
||||
// return WETabs
|
||||
// case 'MM':
|
||||
// return WeatherTabs
|
||||
// case 'WARN':
|
||||
// return WaterQualityMonitoring
|
||||
// case 'AI':
|
||||
// return AIPrediction
|
||||
// case 'AI_Basic':
|
||||
// return AIbasic
|
||||
// default:
|
||||
// return CommonTabs
|
||||
// }
|
||||
// }
|
||||
const handleTabs = (modaldata: any) => {
|
||||
console.log('modaldata', modaldata);
|
||||
if (!modaldata?.sttp) return;
|
||||
let sttp = modaldata?.sttp ? modaldata?.sttp.toUpperCase() : '';
|
||||
switch (sttp) {
|
||||
case 'ENG':
|
||||
return ENGTabs;
|
||||
// if (modaldata?.eqtp == 'QEC') {
|
||||
// const { page } = Utility.parseQueryString()
|
||||
// if (page == 'shengTaiLiuLiangManZuQingKuangJiangJu') {
|
||||
// return ENGEQTabsJuangJu
|
||||
// } else {
|
||||
// return ENGEQTabs
|
||||
// }
|
||||
// } else {
|
||||
// return Session.getAppCode() === 'hbb' ? ENGTabs.filter((e) => e.name !== '阶段属性') : ENGTabs
|
||||
// }
|
||||
// case 'ENG_ALARM':
|
||||
// return DZGJ
|
||||
// case 'EQ':
|
||||
// return EQTabs
|
||||
// case 'DW':
|
||||
// case 'DW_1':
|
||||
// case 'DW_2':
|
||||
// case 'DW_3':
|
||||
// case 'DW_4':
|
||||
// case 'DW_5':
|
||||
// return DWTabs
|
||||
// case 'FP': //todo,后续再删除多余代码
|
||||
// case 'FP_1': //todo,后续再删除多余代码
|
||||
// // case "FP_2": //todo,后续再删除多余代码
|
||||
// case 'FP_3': //todo,后续再删除多余代码
|
||||
// case 'FP_4': //todo,后续再删除多余代码
|
||||
// // case "FP_5": //todo,后续再删除多余代码
|
||||
// if (Session.getAppCode() === 'hbb') {
|
||||
// // mway为2的时侯显示在线监测数据
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return [
|
||||
// ...FPTabs1 //建设情况
|
||||
// ]
|
||||
// } else {
|
||||
// if (modaldata.mway != 2) {
|
||||
// return FPTabs.filter((item) => item.name !== '在线监测数据')
|
||||
// } else {
|
||||
// return [
|
||||
// ...FPTabs //有监测数据
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return [
|
||||
// ...FPTabs1
|
||||
// // {
|
||||
// // name: "系统运行记录",
|
||||
// // key: "FishSystemRunState", //Normal1
|
||||
// // type: "FishSystemRunState", //Normal
|
||||
// // tabs: []
|
||||
// // }
|
||||
// ]
|
||||
// } else {
|
||||
// return [
|
||||
// ...FPTabs
|
||||
// // {
|
||||
// // name: "系统运行记录",
|
||||
// // key: "FishSystemRunState", //Normal1
|
||||
// // type: "FishSystemRunState", //Normal
|
||||
// // tabs: []
|
||||
// // }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// case 'FP_2': //todo,后续再删除多余代码
|
||||
// case 'FP_5': //todo,后续再删除多余代码
|
||||
// if (modaldata.bldsttCcode == '1' || modaldata.bldsttCcode == '0' || modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return FPTabs1
|
||||
// } else {
|
||||
// return FPTabs
|
||||
// }
|
||||
// case 'ZQ':
|
||||
// return ZQTabs
|
||||
// case 'FB':
|
||||
// if (modaldata.bldstt == '1' || modaldata.bldstt == '0') {
|
||||
// return FBTabs1
|
||||
// } else {
|
||||
// return FBTabs
|
||||
// }
|
||||
// case 'FH':
|
||||
// return FHTabs
|
||||
// case 'VD_FB':
|
||||
// case 'VD_FP':
|
||||
// case 'VD_SG':
|
||||
// case 'VD_VP':
|
||||
// case 'VD_EQ':
|
||||
// case 'VD_DW':
|
||||
// case 'VD_FH':
|
||||
// case 'VD_OTWE':
|
||||
// case 'VD_OTTE':
|
||||
// case 'VD_FBP':
|
||||
// case 'VD_FC':
|
||||
// case 'VD_WQ':
|
||||
// case 'VD_TE':
|
||||
// case 'VD_WE':
|
||||
// case 'VD_EQS':
|
||||
// case 'VD_WT':
|
||||
// case 'VD_FBFM':
|
||||
// case 'VD_FBI':
|
||||
// case 'VD_PR':
|
||||
// case 'VD_FPB':
|
||||
// case 'VD_GZFC':
|
||||
// case 'VD_FPC':
|
||||
// case 'VD_VA':
|
||||
// case 'VD':
|
||||
// return videoTabs
|
||||
// case 'VD_SN':
|
||||
// case 'VD_WVD':
|
||||
// return noLiveVideoTabs
|
||||
// case 'VP':
|
||||
// return VPTabs
|
||||
// case 'VA':
|
||||
// return VATabs
|
||||
// case 'WQFB':
|
||||
// return WQFBTabs
|
||||
// case 'WQ':
|
||||
// const _tabs = [...WQTabs]
|
||||
// if (modaldata?.dtinType == 2 || modaldata?.dtinType == 1) _tabs.splice(2, 1)//国家站 人工站把视频tab去除
|
||||
// return _tabs
|
||||
// case 'WQDTA':
|
||||
// return WQDTATabs
|
||||
// case 'LL':
|
||||
// return FLOWTabs
|
||||
// case 'WT':
|
||||
// case 'WTRV':
|
||||
// if (modaldata.enfc == '1') {
|
||||
// return WTTabs1
|
||||
// } else {
|
||||
// return WTTabs
|
||||
// }
|
||||
// case 'WE':
|
||||
// return WETabs
|
||||
// case 'MM':
|
||||
// return WeatherTabs
|
||||
// case 'WARN':
|
||||
// return WaterQualityMonitoring
|
||||
// case 'AI':
|
||||
// return AIPrediction
|
||||
// case 'AI_Basic':
|
||||
// return AIbasic
|
||||
default:
|
||||
return CommonTabs;
|
||||
}
|
||||
};
|
||||
|
||||
// const modalTabSetting = {
|
||||
// footer: false,
|
||||
@ -1309,4 +1313,21 @@
|
||||
// className: 'map-tabs'
|
||||
// }
|
||||
|
||||
// export { ENGTabs, DWTabs, WQTabs, FLOWTabs, EQTabs, FBTabs, WETabs, FPTabs, VPTabs, FHTabs, WTTabs, VATabs, WTTabs1, handleTabs, modalTabSetting, modalTabSettingLy }
|
||||
export {
|
||||
ENGTabs,
|
||||
// DWTabs,
|
||||
// WQTabs,
|
||||
// FLOWTabs,
|
||||
// EQTabs,
|
||||
// FBTabs,
|
||||
// WETabs,
|
||||
// FPTabs,
|
||||
// VPTabs,
|
||||
// FHTabs,
|
||||
// WTTabs,
|
||||
// VATabs,
|
||||
// WTTabs1,
|
||||
handleTabs
|
||||
// modalTabSetting,
|
||||
// modalTabSettingLy
|
||||
};
|
||||
|
||||
315
frontend/src/components/previewMedia/index.vue
Normal file
315
frontend/src/components/previewMedia/index.vue
Normal file
@ -0,0 +1,315 @@
|
||||
<template>
|
||||
<!-- 媒体预览 Modal -->
|
||||
<a-modal
|
||||
:open="visible"
|
||||
:title="videoPreviewTitle"
|
||||
:footer="null"
|
||||
width="900px"
|
||||
@cancel="closeMediaPreview"
|
||||
:zIndex="2000"
|
||||
>
|
||||
<div class="flex h-[60vh] gap-4">
|
||||
<!-- 左侧:混合列表 (图片+视频) -->
|
||||
<div class="w-1/4 overflow-y-auto border-r pr-2 media-list-container">
|
||||
<div
|
||||
v-for="(item, index) in previewList"
|
||||
:key="index"
|
||||
class="mb-2 cursor-pointer list-item"
|
||||
:class="{ select: index == currentMediaIndex }"
|
||||
@click="currentMediaIndex = index"
|
||||
>
|
||||
<span class="file-name">{{ item.name }}</span>
|
||||
<!-- 删除按钮 -->
|
||||
<div
|
||||
class="list-item-delete"
|
||||
v-if="isDel"
|
||||
@click.stop="handleDeleteMedia(item, index)"
|
||||
>
|
||||
<CloseCircleOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:动态预览区域 -->
|
||||
<div
|
||||
class="w-3/4 flex flex-col items-center justify-center bg-gray-100 relative p-4"
|
||||
>
|
||||
<a-spin v-if="imageLoading" tip="图片加载中..." size="large" />
|
||||
<!-- 图片预览 -->
|
||||
<div
|
||||
v-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
currentMediaItem.type === 'image'
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-show="!imageLoading && !imageLoadError"
|
||||
:src="currentMediaItem.url"
|
||||
alt="preview"
|
||||
class="max-w-full max-h-[50vh] object-contain"
|
||||
@load="onImageLoad"
|
||||
@error="onImageError"
|
||||
/>
|
||||
|
||||
<!-- 3. 加载失败提示 -->
|
||||
<div
|
||||
v-if="!imageLoading && imageLoadError"
|
||||
class="text-gray-400 flex flex-col items-center"
|
||||
>
|
||||
<ExclamationCircleOutlined style="font-size: 24px; margin-bottom: 8px" />
|
||||
<span>图片加载失败</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
currentMediaItem.type === 'image'
|
||||
"
|
||||
class="text-gray-400"
|
||||
>
|
||||
暂无图片预览
|
||||
</div>
|
||||
|
||||
<!-- 视频预览 -->
|
||||
<video
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
currentMediaItem.type === 'video'
|
||||
"
|
||||
:src="currentMediaItem.url"
|
||||
controls
|
||||
autoplay
|
||||
class="max-w-full max-h-[50vh]"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<div
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
currentMediaItem.type === 'video'
|
||||
"
|
||||
class="text-gray-400"
|
||||
>
|
||||
暂无视频预览
|
||||
</div>
|
||||
|
||||
<!-- 底部切换控制 -->
|
||||
<div class="absolute bottom-4 flex gap-4 z-10">
|
||||
<a-button
|
||||
shape="circle"
|
||||
:icon="h(LeftOutlined)"
|
||||
@click="prevMedia"
|
||||
:disabled="currentMediaIndex === 0"
|
||||
/>
|
||||
<span class="self-center text-gray-600 bg-white px-2 rounded shadow-sm">
|
||||
{{ currentMediaIndex + 1 }} / {{ previewList.length }}
|
||||
</span>
|
||||
<a-button
|
||||
shape="circle"
|
||||
:icon="h(RightOutlined)"
|
||||
@click="nextMedia"
|
||||
:disabled="currentMediaIndex === previewList.length - 1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, computed, watch, h } from "vue";
|
||||
import { message, Modal } from "ant-design-vue"; // 假设使用 ant-design-vue
|
||||
import {
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
CloseCircleOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
} from "@ant-design/icons-vue";
|
||||
import { deleteFile } from "@/api/guoYuSheShiShuJuTianBao";
|
||||
// 图片加载状态
|
||||
const imageLoading = ref(false);
|
||||
const imageLoadError = ref(false);
|
||||
|
||||
interface MediaItem {
|
||||
id: string;
|
||||
type: "image" | "video";
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
videoPreviewTitle: string;
|
||||
previewList: MediaItem[];
|
||||
previewListIndex: number;
|
||||
taskId?: string;
|
||||
isDel?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["update:visible", "deleteMedia"]);
|
||||
const currentMediaIndex = ref(props.previewListIndex);
|
||||
|
||||
// 计算当前选中的项
|
||||
const currentMediaItem = computed(() => props.previewList[currentMediaIndex.value]);
|
||||
|
||||
const closeMediaPreview = () => {
|
||||
emit("update:visible", false);
|
||||
nextTick(() => {
|
||||
currentMediaIndex.value = 0;
|
||||
});
|
||||
};
|
||||
|
||||
// 【新增】统一切换逻辑
|
||||
const prevMedia = () => {
|
||||
if (currentMediaIndex.value > 0) {
|
||||
currentMediaIndex.value--;
|
||||
}
|
||||
};
|
||||
// 【新增】统一下一逻辑
|
||||
const nextMedia = () => {
|
||||
if (currentMediaIndex.value < props.previewList.length - 1) {
|
||||
currentMediaIndex.value++;
|
||||
}
|
||||
};
|
||||
|
||||
// 【新增】统一删除逻辑
|
||||
const handleDeleteMedia = (item: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "确定要从预览列表中移除该项吗?",
|
||||
zIndex: 2002,
|
||||
onOk: async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const params = {
|
||||
id: item.id,
|
||||
taskId: props.taskId,
|
||||
type:
|
||||
props.videoPreviewTitle == "图片预览"
|
||||
? 1
|
||||
: props.videoPreviewTitle == "视频预览"
|
||||
? 2
|
||||
: 0,
|
||||
filename: item.name,
|
||||
};
|
||||
try {
|
||||
let res: any = await deleteFile(params);
|
||||
if (res && res?.code == 0) {
|
||||
message.success("删除成功");
|
||||
|
||||
emit("deleteMedia", item, props.videoPreviewTitle, index);
|
||||
if (props.previewList.length === 0) {
|
||||
closeMediaPreview();
|
||||
} else {
|
||||
// 调整索引
|
||||
if (index <= currentMediaIndex.value) {
|
||||
currentMediaIndex.value = Math.max(0, currentMediaIndex.value - 1);
|
||||
}
|
||||
}
|
||||
resolve(true);
|
||||
} else {
|
||||
message.error("删除失败");
|
||||
reject();
|
||||
}
|
||||
} catch (e) {
|
||||
message.error("删除失败");
|
||||
reject();
|
||||
}
|
||||
}).catch(() => console.log("Oops errors!"));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 【新增】图片加载完成回调
|
||||
const onImageLoad = () => {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = false;
|
||||
};
|
||||
|
||||
// 【新增】图片加载失败回调
|
||||
const onImageError = () => {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = true;
|
||||
};
|
||||
watch(
|
||||
() => props.previewListIndex,
|
||||
(newIndex) => {
|
||||
currentMediaIndex.value = newIndex;
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVisible) => {
|
||||
if (newVisible) {
|
||||
if (props.videoPreviewTitle == "图片预览") {
|
||||
imageLoading.value = true;
|
||||
imageLoadError.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
watch(currentMediaIndex, (newIndex) => {
|
||||
const item = props.previewList[newIndex];
|
||||
if (item && item.type === "image") {
|
||||
imageLoading.value = true;
|
||||
imageLoadError.value = false;
|
||||
} else {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.media-list-container {
|
||||
background-color: rgb(234, 241, 251);
|
||||
padding: 10px;
|
||||
|
||||
.list-item {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.file-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&.select {
|
||||
color: #ffffff;
|
||||
background-color: rgb(37, 93, 138);
|
||||
}
|
||||
|
||||
.list-item-delete {
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
margin-left: 8px;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .list-item-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -2,8 +2,12 @@
|
||||
import { computed } from "vue";
|
||||
import { useTagsViewStore } from "@/store/modules/tagsView";
|
||||
import { useRoute } from "vue-router";
|
||||
import MapModal from "@/components/MapModal/index.vue";
|
||||
import { useModelStore } from "@/store/modules/model";
|
||||
// import GisView from "@/components/gis/GisView.vue";
|
||||
|
||||
const modelStore = useModelStore();
|
||||
|
||||
const tagsViewStore = useTagsViewStore();
|
||||
|
||||
const router = useRoute();
|
||||
@ -22,6 +26,13 @@ const routeKey = computed(() => router.path + Math.random());
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
|
||||
<MapModal
|
||||
v-model:visible="modelStore.modalVisible"
|
||||
v-model:active-key="modelStore.currentTabKey"
|
||||
:title="modelStore.title"
|
||||
:tabs-config="modelStore.tabList"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
@ -3,12 +3,23 @@ import { ref } from 'vue';
|
||||
|
||||
export const useModelStore = defineStore('model', () => {
|
||||
// state
|
||||
const info = ref<{
|
||||
type: string;
|
||||
const modalVisible = ref(false);
|
||||
const currentTabKey = ref("basicInfo");
|
||||
const tabList = ref([]);
|
||||
const title = ref('');
|
||||
const isBasicEdit = ref(false);
|
||||
|
||||
const params = ref<{
|
||||
sttp: string;
|
||||
}>({
|
||||
type: 'zh'
|
||||
sttp: 'eng'
|
||||
});
|
||||
return {
|
||||
info,
|
||||
params,
|
||||
modalVisible,
|
||||
currentTabKey,
|
||||
tabList,
|
||||
title,
|
||||
isBasicEdit,
|
||||
};
|
||||
});
|
||||
|
||||
@ -4,10 +4,9 @@ import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||
import jidiInfoMod from "@/modules/jidiInfoMod/index.vue";
|
||||
import shuidianhuangjingjieruMod from "@/modules/shuidianhuangjingjieruMod/index.vue";
|
||||
import MapModal from "@/components/MapModal/index.vue";
|
||||
import { useModelStore } from "@/store/modules/model";
|
||||
|
||||
const modelInfo = useModelStore();
|
||||
const modelStore = useModelStore();
|
||||
// import { getQgcStaticData } from "@/api/ecoFlow";
|
||||
onMounted(() => {
|
||||
// const params = {
|
||||
@ -26,29 +25,23 @@ onMounted(() => {
|
||||
// });
|
||||
});
|
||||
|
||||
const modalVisible = ref(false);
|
||||
const currentTabKey = ref("basicInfo");
|
||||
const projectData = ref({ id: 1, name: "测试项目" });
|
||||
|
||||
const tabList = [
|
||||
{ key: "basicInfo", title: "基础信息", url: "" },
|
||||
{ key: "mapView", title: "地图视图", url: "" },
|
||||
{ key: "surrounding", title: "周边配套", url: "" },
|
||||
];
|
||||
|
||||
const showMapModal = () => {
|
||||
modalVisible.value = true;
|
||||
currentTabKey.value = "basicInfo";
|
||||
modelInfo.info.type = "eng";
|
||||
modelStore.modalVisible = true;
|
||||
modelStore.params.sttp = "ENG";
|
||||
modelStore.title = "三峡 详情信息";
|
||||
modelStore.currentTabKey = "basicInfo";
|
||||
modelStore.isBasicEdit = true;
|
||||
};
|
||||
const showMapModal1 = () => {
|
||||
modalVisible.value = true;
|
||||
currentTabKey.value = "basicInfo";
|
||||
modelInfo.info.type = "zh";
|
||||
};
|
||||
|
||||
const onTabChange = (key: string) => {
|
||||
console.log("Tab 切换为:", key);
|
||||
modelStore.modalVisible = true;
|
||||
modelStore.params.sttp = "ENG";
|
||||
modelStore.title = "三峡222 详情信息";
|
||||
modelStore.currentTabKey = "basicInfo";
|
||||
modelStore.isBasicEdit = false;
|
||||
// modelStore.modalVisible = true;
|
||||
// modelStore.params.sttp = "zh";
|
||||
// modelStore.title = '三峡222 详情信息';
|
||||
// modelStore.currentTabKey = "mapView";
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -60,16 +53,8 @@ const onTabChange = (key: string) => {
|
||||
<div class="rightContent">
|
||||
<RightDrawer>
|
||||
<!-- <a-button @click="showMapModal">打开电站地图弹窗</a-button>
|
||||
<a-button @click="showMapModal1">打开地图弹窗1</a-button>
|
||||
<a-button @click="showMapModal1">打开地图弹窗1</a-button> -->
|
||||
|
||||
<MapModal
|
||||
v-model:visible="modalVisible"
|
||||
v-model:active-key="currentTabKey"
|
||||
title="三峡 详情信息"
|
||||
:tabs-config="tabList"
|
||||
:data="projectData"
|
||||
@change="onTabChange"
|
||||
/> -->
|
||||
<jidiInfoMod />
|
||||
<shuidianhuangjingjieruMod />
|
||||
</RightDrawer>
|
||||
|
||||
@ -1,90 +1,67 @@
|
||||
<template>
|
||||
<div class="guoYuSheShiShuJuHistory-page">
|
||||
<GuoYuSheShiShuJuHistorySearch ref="searchRef" class="search-container" :guoyuStatus="guoyuStatus"
|
||||
:direction="direction" @reset="handleReset" @search-finish="handleSearchFinish" />
|
||||
<GuoYuSheShiShuJuHistorySearch
|
||||
ref="searchRef"
|
||||
class="search-container"
|
||||
:guoyuStatus="guoyuStatus"
|
||||
:direction="direction"
|
||||
@reset="handleReset"
|
||||
@search-finish="handleSearchFinish"
|
||||
/>
|
||||
|
||||
<div class="table-container" ref="tableContainerRef">
|
||||
<BasicTable ref="tableRef" :columns="columns" :scroll-y="tableScrollY" :list-url="getFishDraftPage"
|
||||
:search-params="{}" :transform-data="customTransform">
|
||||
<BasicTable
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:scroll-y="tableScrollY"
|
||||
:list-url="getFishDraftPage"
|
||||
:search-params="{}"
|
||||
:transform-data="customTransform"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action' || column.dataIndex === 'action'">
|
||||
<div class="flex">
|
||||
<a-button type="link" size="small" @click="handleView(record)">查看</a-button>
|
||||
<a-button type="link" size="small" @click="handleView(record)"
|
||||
>查看</a-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
<!-- 预览媒体组件 -->
|
||||
<PreviewMedia
|
||||
ref="previewMediaRef"
|
||||
v-model:visible="mediaPreviewVisible"
|
||||
:previewList="previewList"
|
||||
:previewListIndex="previewListIndex"
|
||||
:videoPreviewTitle="videoPreviewTitle"
|
||||
/>
|
||||
|
||||
<a-modal v-model:open="mediaPreviewVisible" :title="videoPreviewTitle" :footer="null" width="900px"
|
||||
@cancel="closeMediaPreview" :zIndex="2000">
|
||||
<div class="flex h-[60vh] gap-4">
|
||||
<div class="w-1/4 overflow-y-auto border-r pr-2 media-list-container">
|
||||
<div v-for="(item, index) in previewList" :key="index" class="mb-2 cursor-pointer list-item"
|
||||
:class="{ select: index === currentMediaIndex }" @click="currentMediaIndex = index">
|
||||
<span class="file-name">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-3/4 flex flex-col items-center justify-center bg-gray-100 relative p-4">
|
||||
<a-image v-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
(currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
|
||||
" :src="currentMediaItem.url" class="max-w-full max-h-full object-contain" />
|
||||
<div v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
(currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
|
||||
" class="text-gray-400">
|
||||
暂无图片预览
|
||||
</div>
|
||||
|
||||
<video v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
(currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
|
||||
" :src="currentMediaItem.url" controls autoplay class="max-w-full max-h-[50vh]">
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<div v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
(currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
|
||||
" class="text-gray-400">
|
||||
暂无视频预览
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-4 flex gap-4 z-10">
|
||||
<a-button shape="circle" :icon="h(LeftOutlined)" @click="prevMedia" :disabled="currentMediaIndex === 0" />
|
||||
<span class="self-center text-gray-600 bg-white px-2 rounded shadow-sm">
|
||||
{{ currentMediaIndex + 1 }} / {{ previewList.length }}
|
||||
</span>
|
||||
<a-button shape="circle" :icon="h(RightOutlined)" @click="nextMedia"
|
||||
:disabled="currentMediaIndex === previewList.length - 1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<EditModal ref="editModalRef" v-model:visible="editModalVisible" :is-view="true" :direction="direction"
|
||||
:initial-values="currentRecord" @cancel="editModalCancel" @preview-click="handlePreviewClick" />
|
||||
<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 { message } from "ant-design-vue";
|
||||
import { LeftOutlined, RightOutlined } from "@ant-design/icons-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_PREVIEW_URL;
|
||||
const baseUrlPreview = import.meta.env.VITE_APP_BASE_URL;
|
||||
|
||||
interface FormData {
|
||||
[key: string]: any;
|
||||
@ -100,8 +77,6 @@ interface ColumnConfig {
|
||||
}
|
||||
|
||||
const tableRef = ref<any>(null);
|
||||
const searchRef = ref<any>(null);
|
||||
const editModalRef = ref<any>(null);
|
||||
|
||||
const direction = ref<any>([]);
|
||||
const guoyuStatus = ref<any>([]);
|
||||
@ -174,17 +149,13 @@ const videoPreviewTitle = ref("视频预览");
|
||||
|
||||
interface MediaItem {
|
||||
id: string;
|
||||
type: "image" | "video" | "formVideo" | "formImage";
|
||||
type: "image" | "video";
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const previewList = ref<MediaItem[]>([]);
|
||||
const currentMediaIndex = ref(0);
|
||||
const tablePreviewRecord = ref<any>({});
|
||||
|
||||
const currentMediaItem = computed(() => previewList.value[currentMediaIndex.value]);
|
||||
|
||||
const previewListIndex = ref(0);
|
||||
const columns = computed(() => {
|
||||
return [
|
||||
...baseColumnsConfig.map((col) => {
|
||||
@ -231,59 +202,23 @@ const editModalCancel = () => {
|
||||
const handlePreviewClick = (record: any, type: string, index: number) => {
|
||||
const mixedList: MediaItem[] = [];
|
||||
if (type === "image") {
|
||||
tablePreviewRecord.value = record;
|
||||
videoPreviewTitle.value = "图片预览";
|
||||
const nameList = record.picpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "image",
|
||||
name: item.name,
|
||||
url:
|
||||
baseUrlPreview +
|
||||
"/data/fishDraft/previewFile?filename=" +
|
||||
item.name +
|
||||
"&taskId=" +
|
||||
"" +
|
||||
"&type=1",
|
||||
});
|
||||
});
|
||||
} else if (type === "video") {
|
||||
tablePreviewRecord.value = record;
|
||||
videoPreviewTitle.value = "视频预览";
|
||||
const nameList = record.vdpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "video",
|
||||
name: item.name,
|
||||
url:
|
||||
baseUrlPreview +
|
||||
"/data/fishDraft/previewFile?filename=" +
|
||||
item.name +
|
||||
"&taskId=" +
|
||||
"" +
|
||||
"&type=2",
|
||||
});
|
||||
});
|
||||
} else if (type === "formImage") {
|
||||
videoPreviewTitle.value = "图片预览";
|
||||
const nameList = JSON.parse(JSON.stringify(record)).picpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "formImage",
|
||||
type: "image",
|
||||
name: item.name,
|
||||
url: item.url,
|
||||
});
|
||||
});
|
||||
} else if (type === "formVideo") {
|
||||
} else if (type === "video") {
|
||||
videoPreviewTitle.value = "视频预览";
|
||||
const nameList = JSON.parse(JSON.stringify(record)).vdpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "formVideo",
|
||||
type: "video",
|
||||
name: item.name,
|
||||
url: item.url,
|
||||
});
|
||||
@ -291,32 +226,12 @@ const handlePreviewClick = (record: any, type: string, index: number) => {
|
||||
}
|
||||
|
||||
mediaPreviewVisible.value = true;
|
||||
currentMediaIndex.value = index;
|
||||
previewListIndex.value = index;
|
||||
nextTick(() => {
|
||||
previewList.value = mixedList;
|
||||
});
|
||||
};
|
||||
|
||||
const prevMedia = () => {
|
||||
if (currentMediaIndex.value > 0) {
|
||||
currentMediaIndex.value--;
|
||||
}
|
||||
};
|
||||
|
||||
const nextMedia = () => {
|
||||
if (currentMediaIndex.value < previewList.value.length - 1) {
|
||||
currentMediaIndex.value++;
|
||||
}
|
||||
};
|
||||
|
||||
const closeMediaPreview = () => {
|
||||
mediaPreviewVisible.value = false;
|
||||
nextTick(() => {
|
||||
previewList.value = [];
|
||||
currentMediaIndex.value = 0;
|
||||
});
|
||||
};
|
||||
|
||||
const customTransform = (res: any) => {
|
||||
const rawRecords = res?.data?.records || [];
|
||||
const modifiedRecords = rawRecords.map((item: any) => {
|
||||
@ -349,13 +264,13 @@ const handleSearchFinish = (values: any) => {
|
||||
field: "strdt",
|
||||
operator: "gte",
|
||||
dataType: "date",
|
||||
value: values.strdt[0] + ' 00:00:00',
|
||||
value: values.strdt[0] + " 00:00:00",
|
||||
},
|
||||
{
|
||||
field: "strdt",
|
||||
operator: "lte",
|
||||
dataType: "date",
|
||||
value: values.strdt[1] + ' 23:59:59',
|
||||
value: values.strdt[1] + " 23:59:59",
|
||||
},
|
||||
values.direction && {
|
||||
field: "direction",
|
||||
@ -367,7 +282,7 @@ const handleSearchFinish = (values: any) => {
|
||||
field: "status",
|
||||
operator: "eq",
|
||||
dataType: "string",
|
||||
value: 'APPROVED',
|
||||
value: "APPROVED",
|
||||
},
|
||||
values.stcd && {
|
||||
field: "stcd",
|
||||
@ -456,39 +371,4 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.media-list-container {
|
||||
background-color: rgb(234, 241, 251);
|
||||
padding: 10px;
|
||||
|
||||
.list-item {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.file-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&.select {
|
||||
color: #ffffff;
|
||||
background-color: rgb(37, 93, 138);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="流域" name="hbrvcd">
|
||||
<a-form-item label="流域" name="hbrvcd">
|
||||
<a-select
|
||||
v-model:value="formData.hbrvcd"
|
||||
:loading="hbrvcdLoading"
|
||||
@ -413,7 +413,7 @@ const emit = defineEmits<{
|
||||
(e: "update:visible", value: boolean): void;
|
||||
(e: "cancel"): void;
|
||||
(e: "ok", values: any): void;
|
||||
(e: "preview-click", record: any, type: string, index: number): void;
|
||||
(e: "preview-click", record: any, type: string, index: number, action: string): void;
|
||||
}>();
|
||||
|
||||
// 表单引用
|
||||
@ -654,13 +654,12 @@ const initForm = () => {
|
||||
|
||||
// 视频预览
|
||||
const handleVideoPreview = () => {
|
||||
emit("preview-click", { vdpthList: videoFileList.value }, "formVideo", 0);
|
||||
emit("preview-click", { vdpthList: videoFileList.value }, "video", 0, "preview");
|
||||
};
|
||||
|
||||
// 预览图片
|
||||
const handleImagePreview = async (file: any) => {
|
||||
emit("preview-click", { picpthList: imageFileList.value }, "formImage", 0);
|
||||
return Promise.reject();
|
||||
emit("preview-click", { picpthList: imageFileList.value }, "image", 0, "preview");
|
||||
};
|
||||
// 确认操作
|
||||
const handleOk = async () => {
|
||||
@ -809,7 +808,7 @@ watch(
|
||||
if (newVisible) {
|
||||
// 弹窗打开时,初始化数据
|
||||
// getBaseDropdownSelect();// 基地
|
||||
getHbrvcdDropdownSelect();// 流域
|
||||
getHbrvcdDropdownSelect(); // 流域
|
||||
getEngInfoDropdownSelect(formData.hbrvcd);
|
||||
getFpssDropdownSelect(formData.rstcd, formData.hbrvcd);
|
||||
initForm();
|
||||
@ -819,7 +818,7 @@ watch(
|
||||
);
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
localLoading
|
||||
localLoading,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<!--
|
||||
<!--
|
||||
<template v-if="column.key === 'index' || column.dataIndex === 'index'">
|
||||
{{ index + 1 }}
|
||||
</template> -->
|
||||
@ -144,14 +144,14 @@
|
||||
</template>
|
||||
|
||||
<!-- 过鱼时间 -->
|
||||
<template v-else-if="column.dataIndex === 'strdt'">
|
||||
<template v-else-if="column.dataIndex === 'strdtStr'">
|
||||
<a-date-picker
|
||||
v-model:value="editingData.strdt"
|
||||
v-model:value="editingData.strdtStr"
|
||||
show-time
|
||||
style="width: 100%"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
@change="(val) => delWarning(val, 'strdt')"
|
||||
@change="(val) => delWarning(val, 'strdtStr')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -251,7 +251,7 @@
|
||||
<div
|
||||
class="text"
|
||||
:class="{ text_warning: record.picpthsWarnings.includes(item.name) }"
|
||||
@click="emit('preview-click', record, 'image', index)"
|
||||
@click="emit('preview-click', record, 'image', index, 'delete')"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
@ -263,7 +263,7 @@
|
||||
<div
|
||||
class="text"
|
||||
:class="{ text_warning: record.vdpthsWarnings.includes(item.name) }"
|
||||
@click="emit('preview-click', record, 'video', index)"
|
||||
@click="emit('preview-click', record, 'video', index, 'delete')"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
@ -307,7 +307,15 @@ const rowStates = reactive<Record<number, any>>({});
|
||||
const editingData = ref<any>(null);
|
||||
|
||||
const modalColumns = ref([
|
||||
{ dataIndex: "rowIndex", key: "rowIndex", title: "序号", width: 60, dataIndexKey: "rowIndex",align: "center",fixed: "left" },
|
||||
{
|
||||
dataIndex: "rowIndex",
|
||||
key: "rowIndex",
|
||||
title: "序号",
|
||||
width: 60,
|
||||
dataIndexKey: "rowIndex",
|
||||
align: "center",
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
dataIndex: "hbrvnm",
|
||||
key: "hbrvnm",
|
||||
@ -330,9 +338,9 @@ const modalColumns = ref([
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
dataIndex: "strdt",
|
||||
key: "strdt",
|
||||
dataIndexKey: "strdt",
|
||||
dataIndex: "strdtStr",
|
||||
key: "strdtStr",
|
||||
dataIndexKey: "strdtStr",
|
||||
title: "过鱼时间",
|
||||
width: 190,
|
||||
},
|
||||
@ -577,6 +585,10 @@ const startEdit = (index: number) => {
|
||||
editingData.value.stcd = null;
|
||||
delWarning(null, "stcd");
|
||||
}
|
||||
if (editingData.value.warnings.includes("strdt")) {
|
||||
editingData.value.strdt = null;
|
||||
delWarning(null, "strdt");
|
||||
}
|
||||
|
||||
// 3. 预加载下拉选项 (基于 editingData 的值)
|
||||
if (editingData.value.hbrvcd == "" || editingData.value.hbrvcd == undefined) {
|
||||
@ -652,6 +664,7 @@ const saveEdit = async (index: number) => {
|
||||
// 2. 创建新数组,替换对应索引的数据
|
||||
const newData = [...props.fileTableData];
|
||||
newData[index] = { ...editingData.value };
|
||||
newData[index].strdt = newData[index].strdtStr;
|
||||
emit("update:fileLoading", true);
|
||||
try {
|
||||
const res: any = await revalidateAndUpdateRow({
|
||||
|
||||
@ -185,142 +185,28 @@
|
||||
@ok="handleEditSubmit"
|
||||
@preview-click="handlePreviewClick"
|
||||
/>
|
||||
|
||||
<!-- 媒体预览 Modal -->
|
||||
<a-modal
|
||||
v-model:open="mediaPreviewVisible"
|
||||
:title="videoPreviewTitle"
|
||||
:footer="null"
|
||||
width="900px"
|
||||
@cancel="closeMediaPreview"
|
||||
:zIndex="2000"
|
||||
>
|
||||
<div class="flex h-[60vh] gap-4">
|
||||
<!-- 左侧:混合列表 (图片+视频) -->
|
||||
<div class="w-1/4 overflow-y-auto border-r pr-2 media-list-container">
|
||||
<div
|
||||
v-for="(item, index) in previewList"
|
||||
:key="index"
|
||||
class="mb-2 cursor-pointer list-item"
|
||||
:class="{ select: index === currentMediaIndex }"
|
||||
@click="currentMediaIndex = index"
|
||||
>
|
||||
<span class="file-name">{{ item.name }}</span>
|
||||
<!-- 删除按钮 -->
|
||||
<div
|
||||
class="list-item-delete"
|
||||
v-if="item.type != 'formVideo' && item.type != 'formImage'"
|
||||
@click.stop="handleDeleteMedia(item, index)"
|
||||
>
|
||||
<CloseCircleOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:动态预览区域 -->
|
||||
<div
|
||||
class="w-3/4 flex flex-col items-center justify-center bg-gray-100 relative p-4"
|
||||
>
|
||||
<a-spin v-if="imageLoading" tip="图片加载中..." size="large" />
|
||||
<!-- 图片预览 -->
|
||||
<div
|
||||
v-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
(currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-show="!imageLoading && !imageLoadError"
|
||||
:src="currentMediaItem.url"
|
||||
alt="preview"
|
||||
class="max-w-full max-h-[50vh] object-contain"
|
||||
@load="onImageLoad"
|
||||
@error="onImageError"
|
||||
/>
|
||||
|
||||
<!-- 3. 加载失败提示 -->
|
||||
<div
|
||||
v-if="!imageLoading && imageLoadError"
|
||||
class="text-gray-400 flex flex-col items-center"
|
||||
>
|
||||
<ExclamationCircleOutlined style="font-size: 24px; margin-bottom: 8px" />
|
||||
<span>图片加载失败</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
(currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
|
||||
"
|
||||
class="text-gray-400"
|
||||
>
|
||||
暂无图片预览
|
||||
</div>
|
||||
|
||||
<!-- 视频预览 -->
|
||||
<video
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url != '' &&
|
||||
(currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
|
||||
"
|
||||
:src="currentMediaItem.url"
|
||||
controls
|
||||
autoplay
|
||||
class="max-w-full max-h-[50vh]"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<div
|
||||
v-else-if="
|
||||
currentMediaItem &&
|
||||
currentMediaItem.url == '' &&
|
||||
(currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
|
||||
"
|
||||
class="text-gray-400"
|
||||
>
|
||||
暂无视频预览
|
||||
</div>
|
||||
|
||||
<!-- 底部切换控制 -->
|
||||
<div class="absolute bottom-4 flex gap-4 z-10">
|
||||
<a-button
|
||||
shape="circle"
|
||||
:icon="h(LeftOutlined)"
|
||||
@click="prevMedia"
|
||||
:disabled="currentMediaIndex === 0"
|
||||
/>
|
||||
<span class="self-center text-gray-600 bg-white px-2 rounded shadow-sm">
|
||||
{{ currentMediaIndex + 1 }} / {{ previewList.length }}
|
||||
</span>
|
||||
<a-button
|
||||
shape="circle"
|
||||
:icon="h(RightOutlined)"
|
||||
@click="nextMedia"
|
||||
:disabled="currentMediaIndex === previewList.length - 1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
<!-- 预览媒体组件 -->
|
||||
<PreviewMedia
|
||||
ref="previewMediaRef"
|
||||
v-model:visible="mediaPreviewVisible"
|
||||
:previewList="previewList"
|
||||
:previewListIndex="previewListIndex"
|
||||
:videoPreviewTitle="videoPreviewTitle"
|
||||
:taskId="taskId"
|
||||
:isDel="isPreviewMediaDelete"
|
||||
@deleteMedia="handleDeleteMedia"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, h, nextTick, watch } from "vue";
|
||||
import { message, Modal } from "ant-design-vue"; // 假设使用 ant-design-vue
|
||||
import {
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
CloseCircleOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
} from "@ant-design/icons-vue"; // 引入图标组件
|
||||
import BasicTable from "@/components/BasicTable/index.vue";
|
||||
import GuoYuSheShiShuJuTianBaoSearch from "./guoYuSheShiShuJuTianBaoSearch.vue";
|
||||
import GuoYuSheShiShuJuTianBaoTable from "./guoYuSheShiShuJuTianBaoTable.vue";
|
||||
import EditModal from "./guoYuSheShiShuJuTianBaoForm.vue";
|
||||
import PreviewMedia from "@/components/previewMedia/index.vue";
|
||||
import { checkPerm } from "@/directive/permission";
|
||||
import {
|
||||
getFishDraftPage,
|
||||
@ -335,11 +221,11 @@ import {
|
||||
checkImportStatus,
|
||||
batchSaveDraft,
|
||||
getLastImportResult,
|
||||
deleteFile,
|
||||
batchApproveAll,
|
||||
} from "@/api/guoYuSheShiShuJuTianBao";
|
||||
import { Tag } from "ant-design-vue"; // 确保导入 Tag
|
||||
import { getDictItemsByCode } from "@/api/dict";
|
||||
import { fr } from "element-plus/es/locale/index.mjs";
|
||||
|
||||
const baseUrl = import.meta.env.VITE_APP_PREVIEW_URL;
|
||||
const baseUrlApi = import.meta.env.VITE_APP_BASE_API_URL;
|
||||
@ -358,9 +244,6 @@ interface ColumnConfig {
|
||||
}
|
||||
const fileInputRef = ref<any>(null);
|
||||
const tableRef = ref<any>(null);
|
||||
// 图片加载状态
|
||||
const imageLoading = ref(false);
|
||||
const imageLoadError = ref(false);
|
||||
// 字典项
|
||||
const direction = ref<any>([]);
|
||||
const guoyuStatus = ref<any>([]);
|
||||
@ -435,20 +318,18 @@ const isView = ref(false);
|
||||
const currentRecord = ref<FormData | null>(null);
|
||||
|
||||
const mediaPreviewVisible = ref(false);
|
||||
const isPreviewMediaDelete = ref(false);
|
||||
const videoPreviewTitle = ref("视频预览");
|
||||
interface MediaItem {
|
||||
id: string;
|
||||
type: "image" | "video" | "formVideo" | "formImage";
|
||||
type: "image" | "video";
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
const previewList = ref<MediaItem[]>([]);
|
||||
const currentMediaIndex = ref(0);
|
||||
const previewListIndex = ref(0);
|
||||
const tablePreviewRecord = ref<any>({});
|
||||
|
||||
// 计算当前选中的项
|
||||
const currentMediaItem = computed(() => previewList.value[currentMediaIndex.value]);
|
||||
|
||||
// 表格数据
|
||||
const fileTableData = ref<any[]>([]);
|
||||
const batchData = ref<any[]>([]);
|
||||
@ -810,6 +691,9 @@ const importBtn = async () => {
|
||||
if (visible.value) importBtn();
|
||||
}, 5000);
|
||||
}
|
||||
} else if (currentTask.status == "FAILED") {
|
||||
message.error(currentTask.statusText);
|
||||
fileLoading.value = false;
|
||||
} else if (currentTask.status == "VALIDATED") {
|
||||
nextTick(async () => {
|
||||
modalTableRef.value.editingRowIndex = null;
|
||||
@ -839,13 +723,6 @@ const fileChange = (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
await importFishZip(formData);
|
||||
try {
|
||||
setTimeout(() => {
|
||||
if (visible.value) importBtn();
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
message.error("导入失败");
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取文件列表
|
||||
@ -994,167 +871,95 @@ const handleSearchFinish = (values: any) => {
|
||||
tableRef.value?.getList(filter);
|
||||
};
|
||||
// 处理预览点击 (由子组件触发)
|
||||
const handlePreviewClick = (record: any, type: string, index: number) => {
|
||||
const handlePreviewClick = (record: any, type: string, index: number, action: string) => {
|
||||
const mixedList: MediaItem[] = [];
|
||||
if (type === "image") {
|
||||
imageLoading.value = true;
|
||||
imageLoadError.value = false;
|
||||
if (action === "delete") {
|
||||
isPreviewMediaDelete.value = true;
|
||||
tablePreviewRecord.value = record;
|
||||
} else if (action === "preview") {
|
||||
isPreviewMediaDelete.value = false;
|
||||
}
|
||||
if (type === "image") {
|
||||
videoPreviewTitle.value = "图片预览";
|
||||
const nameList = record.picpthList;
|
||||
|
||||
nameList.forEach((item: any) => {
|
||||
let url = "";
|
||||
if (action === "preview") {
|
||||
url = item.url;
|
||||
} else if (action === "delete") {
|
||||
url =
|
||||
baseUrlApi +
|
||||
"/data/fishDraft/previewFile?filename=" +
|
||||
item.name +
|
||||
"&taskId=" +
|
||||
taskId.value +
|
||||
"&type=1";
|
||||
}
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "image",
|
||||
name: item.name,
|
||||
url:
|
||||
url: url,
|
||||
});
|
||||
});
|
||||
} else if (type === "video") {
|
||||
videoPreviewTitle.value = "视频预览";
|
||||
const nameList = record.vdpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
let url = "";
|
||||
if (action === "preview") {
|
||||
url = item.url;
|
||||
} else if (action === "delete") {
|
||||
url =
|
||||
baseUrlApi +
|
||||
"/data/fishDraft/previewFile?filename=" +
|
||||
item.name +
|
||||
"&taskId=" +
|
||||
taskId.value +
|
||||
"&type=1",
|
||||
});
|
||||
});
|
||||
} else if (type === "video") {
|
||||
tablePreviewRecord.value = record;
|
||||
videoPreviewTitle.value = "视频预览";
|
||||
const nameList = record.vdpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
"&type=2";
|
||||
}
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "video",
|
||||
name: item.name, // 视频通常没有单独的名称字段,可根据需要调整
|
||||
url:
|
||||
baseUrlApi +
|
||||
"/data/fishDraft/previewFile?filename=" +
|
||||
item.name +
|
||||
"&taskId=" +
|
||||
taskId.value +
|
||||
"&type=2",
|
||||
});
|
||||
});
|
||||
} else if (type === "formImage") {
|
||||
imageLoading.value = true;
|
||||
imageLoadError.value = false;
|
||||
videoPreviewTitle.value = "图片预览";
|
||||
const nameList = JSON.parse(JSON.stringify(record)).picpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "formImage",
|
||||
name: item.name, // 视频通常没有单独的名称字段,可根据需要调整
|
||||
url: item.url,
|
||||
});
|
||||
});
|
||||
} else if (type === "formVideo") {
|
||||
videoPreviewTitle.value = "视频预览";
|
||||
const nameList = JSON.parse(JSON.stringify(record)).vdpthList;
|
||||
nameList.forEach((item: any) => {
|
||||
mixedList.push({
|
||||
id: record.id,
|
||||
type: "formVideo",
|
||||
name: item.name, // 视频通常没有单独的名称字段,可根据需要调整
|
||||
url: item.url,
|
||||
url: url,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
mediaPreviewVisible.value = true;
|
||||
currentMediaIndex.value = index;
|
||||
previewListIndex.value = index;
|
||||
nextTick(() => {
|
||||
console.log(mixedList);
|
||||
previewList.value = mixedList;
|
||||
});
|
||||
};
|
||||
|
||||
// 【新增】统一切换逻辑
|
||||
const prevMedia = () => {
|
||||
if (currentMediaIndex.value > 0) {
|
||||
currentMediaIndex.value--;
|
||||
const handleDeleteMedia = (item: any, type: string, index: number) => {
|
||||
previewList.value.splice(index, 1);
|
||||
if (type == "图片预览") {
|
||||
if (previewList.value.length == 0) {
|
||||
tablePreviewRecord.value.picpthList = [];
|
||||
tablePreviewRecord.value.picpthsWarnings = [];
|
||||
} else {
|
||||
tablePreviewRecord.value.picpthList.splice(index, 1);
|
||||
tablePreviewRecord.value.picpthsWarnings = tablePreviewRecord.value.picpthsWarnings.filter(
|
||||
(warningName: any) => warningName !== item.name
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (previewList.value.length == 0) {
|
||||
tablePreviewRecord.value.vdpthList = [];
|
||||
tablePreviewRecord.value.vdpthsWarnings = [];
|
||||
} else {
|
||||
tablePreviewRecord.value.vdpthList.splice(index, 1);
|
||||
tablePreviewRecord.value.vdpthsWarnings = tablePreviewRecord.value.vdpthsWarnings.filter(
|
||||
(warningName: any) => warningName !== item.name
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 【新增】统一下一逻辑
|
||||
const nextMedia = () => {
|
||||
if (currentMediaIndex.value < previewList.value.length - 1) {
|
||||
currentMediaIndex.value++;
|
||||
}
|
||||
};
|
||||
|
||||
// 【新增】统一删除逻辑
|
||||
const handleDeleteMedia = (item: any, index: number) => {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "确定要从预览列表中移除该项吗?",
|
||||
zIndex: 2002,
|
||||
onOk: async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const params = {
|
||||
id: item.id,
|
||||
taskId: taskId.value,
|
||||
type:
|
||||
videoPreviewTitle.value == "图片预览"
|
||||
? 1
|
||||
: videoPreviewTitle.value == "视频预览"
|
||||
? 2
|
||||
: 0,
|
||||
filename: item.name,
|
||||
};
|
||||
try {
|
||||
let res: any = await deleteFile(params);
|
||||
if (res && res?.code == 0) {
|
||||
message.success("删除成功");
|
||||
previewList.value.splice(index, 1);
|
||||
if (videoPreviewTitle.value == "图片预览") {
|
||||
if (previewList.value.length == 0) {
|
||||
tablePreviewRecord.value.picpthList = [];
|
||||
tablePreviewRecord.value.picpthsWarnings = [];
|
||||
} else {
|
||||
tablePreviewRecord.value.picpthList.splice(index, 1);
|
||||
tablePreviewRecord.value.picpthsWarnings = tablePreviewRecord.value.picpthsWarnings.filter(
|
||||
(warningName: any) => warningName !== item.name
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (previewList.value.length == 0) {
|
||||
tablePreviewRecord.value.vdpthList = [];
|
||||
tablePreviewRecord.value.vdpthsWarnings = [];
|
||||
} else {
|
||||
tablePreviewRecord.value.vdpthList.splice(index, 1);
|
||||
tablePreviewRecord.value.vdpthsWarnings = tablePreviewRecord.value.vdpthsWarnings.filter(
|
||||
(warningName: any) => warningName !== item.name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (previewList.value.length === 0) {
|
||||
mediaPreviewVisible.value = false;
|
||||
} else {
|
||||
// 调整索引
|
||||
if (index <= currentMediaIndex.value) {
|
||||
currentMediaIndex.value = Math.max(0, currentMediaIndex.value - 1);
|
||||
}
|
||||
}
|
||||
resolve(true);
|
||||
} else {
|
||||
message.error("删除失败");
|
||||
reject();
|
||||
}
|
||||
} catch (e) {
|
||||
message.error("删除失败");
|
||||
reject();
|
||||
}
|
||||
}).catch(() => console.log("Oops errors!"));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const closeMediaPreview = () => {
|
||||
mediaPreviewVisible.value = false;
|
||||
nextTick(() => {
|
||||
previewList.value = [];
|
||||
currentMediaIndex.value = 0;
|
||||
});
|
||||
};
|
||||
const tableContainerRef = ref<HTMLElement | null>(null);
|
||||
const tableScrollY = ref<number | undefined>(undefined);
|
||||
// 计算表格主体高度(减去表头、分页器、内边距等)
|
||||
@ -1174,28 +979,6 @@ const observer = new ResizeObserver(() => {
|
||||
calcTableScrollY();
|
||||
});
|
||||
|
||||
// 【新增】图片加载完成回调
|
||||
const onImageLoad = () => {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = false;
|
||||
};
|
||||
|
||||
// 【新增】图片加载失败回调
|
||||
const onImageError = () => {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = true;
|
||||
};
|
||||
watch(currentMediaIndex, (newIndex) => {
|
||||
const item = previewList.value[newIndex];
|
||||
if (item && (item.type === "image" || item.type === "formImage")) {
|
||||
imageLoading.value = true;
|
||||
imageLoadError.value = false;
|
||||
} else {
|
||||
imageLoading.value = false;
|
||||
imageLoadError.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
// --- 生命周期 ---
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
@ -1248,57 +1031,6 @@ onMounted(() => {
|
||||
/* 为绝对定位元素提供参考(如果需要) */
|
||||
}
|
||||
|
||||
.media-list-container {
|
||||
background-color: rgb(234, 241, 251);
|
||||
padding: 10px;
|
||||
|
||||
.list-item {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.file-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&.select {
|
||||
color: #ffffff;
|
||||
background-color: rgb(37, 93, 138);
|
||||
}
|
||||
|
||||
.list-item-delete {
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
margin-left: 8px;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .list-item-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttonStyle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div class="approval-detail-search">
|
||||
<BasicSearch ref="basicSearchRef" :searchList="searchList" :initial-values="initSearchData" :zhujianfujian="'fu'" @reset="handleReset"
|
||||
@finish="onSearchFinish" @values-change="onValuesChange">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
:zhujianfujian="'fu'"
|
||||
@reset="handleReset"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
>
|
||||
<template #ftp="{ onChange }">
|
||||
<fishSearch v-model="localTypeDate" width="200px" @update:modelValue="onChange" />
|
||||
</template>
|
||||
@ -62,10 +69,10 @@ const searchList: any = computed(() => [
|
||||
type: "RangePicker",
|
||||
name: "strdt",
|
||||
label: "过鱼时间",
|
||||
picker: "month",
|
||||
picker: "date",
|
||||
fieldProps: {
|
||||
format: "YYYY-MM",
|
||||
valueFormat: "YYYY-MM",
|
||||
format: "YYYY-MM-DD",
|
||||
valueFormat: "YYYY-MM-DD",
|
||||
allowClear: false,
|
||||
},
|
||||
presets: DateSetting.RangeButton.month,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,116 +1,121 @@
|
||||
<template>
|
||||
<div class="guoYuSheShiShuJuTianBao-search">
|
||||
<BasicSearch ref="basicSearchRef" :searchList="searchList" :initial-values="initSearchData" :zhujianfujian="'zhu'"
|
||||
@finish="onSearchFinish" @values-change="onValuesChange" @reset="handleReset">
|
||||
<template #actions>
|
||||
<a-tooltip title="批量审批">
|
||||
<a-button :disabled="selectedCount === 0" @click="$emit('batch-approve')">
|
||||
<template #icon>
|
||||
<CheckSquareOutlined />
|
||||
</template>
|
||||
批量审批
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip title="批量驳回">
|
||||
<a-button :disabled="selectedCount === 0" @click="$emit('batch-reject')">
|
||||
<template #icon>
|
||||
<CloseCircleOutlined />
|
||||
</template>
|
||||
批量驳回
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<div class="guoYuSheShiShuJuTianBao-search">
|
||||
<BasicSearch
|
||||
ref="basicSearchRef"
|
||||
:searchList="searchList"
|
||||
:initial-values="initSearchData"
|
||||
:zhujianfujian="'zhu'"
|
||||
@finish="onSearchFinish"
|
||||
@values-change="onValuesChange"
|
||||
@reset="handleReset"
|
||||
>
|
||||
<template #actions>
|
||||
<a-tooltip title="批量审批">
|
||||
<a-button :disabled="selectedCount === 0" @click="$emit('batch-approve')">
|
||||
<template #icon>
|
||||
<CheckSquareOutlined />
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
批量审批
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip title="批量驳回">
|
||||
<a-button :disabled="selectedCount === 0" @click="$emit('batch-reject')">
|
||||
<template #icon>
|
||||
<CloseCircleOutlined />
|
||||
</template>
|
||||
批量驳回
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="批量删除">
|
||||
<a-button :disabled="selectedCount === 0" @click="$emit('batch-delete')">
|
||||
批量删除
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</BasicSearch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import BasicSearch from "@/components/BasicSearch/index.vue"; // 确保路径正确
|
||||
import { getDictItemsByCode } from '@/api/dict';
|
||||
import {
|
||||
CheckSquareOutlined,
|
||||
CloseCircleOutlined,
|
||||
} from "@ant-design/icons-vue";
|
||||
import { getDictItemsByCode } from "@/api/dict";
|
||||
import { CheckSquareOutlined, CloseCircleOutlined } from "@ant-design/icons-vue";
|
||||
// --- Props & Emits ---
|
||||
interface Props {
|
||||
selectedCount?: number;
|
||||
selectedCount?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
selectedCount: 0
|
||||
selectedCount: 0,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "reset", values: any): void;
|
||||
(e: "searchFinish", values: any): void;
|
||||
(e: "batch-approve"): void;
|
||||
(e: "batch-reject"): void;
|
||||
(e: "reset", values: any): void;
|
||||
(e: "searchFinish", values: any): void;
|
||||
(e: "batch-approve"): void;
|
||||
(e: "batch-reject"): void;
|
||||
(e: "batch-delete"): void;
|
||||
}>();
|
||||
|
||||
|
||||
// 模拟 initSearchData
|
||||
const initSearchData = {
|
||||
hbrvcd:'all',
|
||||
stcd:'',
|
||||
status: '',
|
||||
hbrvcd: "all",
|
||||
stcd: "",
|
||||
status: "",
|
||||
};
|
||||
|
||||
const searchData = ref<any>({ ...initSearchData });
|
||||
|
||||
const searchList: any = computed(() => [
|
||||
{
|
||||
type: "waterStation",
|
||||
name: "hbrvcd",
|
||||
label: "流域",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
options: [],
|
||||
{
|
||||
type: "waterStation",
|
||||
name: "hbrvcd",
|
||||
label: "流域",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
options: [],
|
||||
},
|
||||
|
||||
{
|
||||
type: "Select",
|
||||
name: "status",
|
||||
label: "审批状态",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
options: statusData.value,
|
||||
{
|
||||
type: "Select",
|
||||
name: "status",
|
||||
label: "审批状态",
|
||||
fieldProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
|
||||
options: statusData.value,
|
||||
},
|
||||
]);
|
||||
// --- Methods ---
|
||||
|
||||
|
||||
|
||||
// 2. 搜索表单逻辑
|
||||
const onSearchFinish = (values: any) => {
|
||||
console.log(values);
|
||||
console.log(values);
|
||||
|
||||
emit("searchFinish", values);
|
||||
emit("searchFinish", values);
|
||||
};
|
||||
const handleReset = () => {
|
||||
emit("reset", initSearchData);
|
||||
emit("reset", initSearchData);
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
// 同步更新本地 searchData,以便其他逻辑使用
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
// 同步更新本地 searchData,以便其他逻辑使用
|
||||
searchData.value = { ...searchData.value, ...allValues };
|
||||
};
|
||||
|
||||
// --- Lifecycle ---
|
||||
onMounted(() => {
|
||||
emit("searchFinish", initSearchData);
|
||||
getstatusData()
|
||||
emit("searchFinish", initSearchData);
|
||||
getstatusData();
|
||||
});
|
||||
const statusData = ref(false)
|
||||
const statusData = ref(false);
|
||||
const getstatusData = () => {
|
||||
getDictItemsByCode({ dictCode: "approvalStatus" }).then((res) => {
|
||||
statusData.value = res.data;
|
||||
});
|
||||
getDictItemsByCode({ dictCode: "approvalStatus" }).then((res) => {
|
||||
statusData.value = res.data;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
Loading…
Reference in New Issue
Block a user