bug修改,添加过鱼到数统计,添加公共弹框基础信息

This commit is contained in:
扈兆增 2026-05-08 19:11:10 +08:00
parent 2d9ff44ef9
commit 0d5c79bd2e
11 changed files with 7317 additions and 112 deletions

View File

@ -6,9 +6,15 @@ NODE_ENV='development'
VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台'
VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/dev-api'
## 开发环境API地址
# 本地环境
# VITE_APP_BASE_URL = 'http://localhost:8093'
# 测试环境
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
# 汤伟
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093'
# 开发环境导入预览地址
VITE_APP_BASE_API_URL = 'http://172.16.21.14:8096'
## 开发环境预览 图片视频地址
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'

View File

@ -27,6 +27,7 @@ interface Props {
scrollY?: string | number;
//
listUrl: (params: any) => Promise<any>;
data?: any[];
//
enableRowSelection?: boolean;
// Key Table
@ -44,6 +45,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
enableRowSelection: false,
rowKey: "id",
data: () => ([]),
isOneLoad: true,
searchParams: () => ({}),
defaultPageSize: 20,
@ -105,6 +107,7 @@ const paginationConfig = computed(() => ({
* @param extraParams 额外的临时参数可选
*/
const getList = async (filter?: Record<string, any>) => {
if(props.data.length > 0) return
loading.value = true;
tableData.value = [];
total.value = 0;
@ -215,6 +218,7 @@ watch(
// --- Lifecycle ---
onMounted(() => {
if(props.data && props.data.length > 0) tableData.value = props.data || [];
});
</script>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +1,44 @@
<template>
<a-modal
v-model:open="visible"
:open="visible"
:title="title"
width="800px"
width="80vw"
:footer="null"
:closable="true"
@cancel="handleClose"
:destroyOnClose="true"
class="map-modal"
>
<div class="map-modal-content">
<a-tabs v-model:activeKey="currentActiveKey">
<a-tab-pane
v-for="tab in tabsConfig"
:key="tab.key"
:tab="tab.title"
>
<!-- 根据 key 动态渲染子组件 -->
<div v-if="currentActiveKey === 'basicInfo'" class="tab-pane-container">
<!-- 假设 BasicInfo 是预定义的组件 -->
<BasicInfo :data="modalData" />
</div>
<div v-else-if="currentActiveKey === 'mapView'" class="tab-pane-container">
<!-- 假设 MapView 是预定义的组件 -->
<MapView :data="modalData" />
</div>
<div v-else-if="currentActiveKey === 'surrounding'" class="tab-pane-container">
<!-- 其他预定义组件 -->
<SurroundingInfo :data="modalData" />
</div>
<div v-else class="empty-placeholder">
未找到对应 Key ({{ currentActiveKey }}) 的组件配置
<a-tabs :active-key="currentActiveKey" @change="onTabChange">
<a-tab-pane v-for="tab in tabsConfig" :key="tab.key" :tab="tab.title">
<div class="content">
<!-- 基本信息组件 -->
<BasicInfo v-if="currentActiveKey === 'basicInfo'" :url="tab.url" />
<!-- 地图组件 -->
<!-- <MapView v-else-if="currentActiveKey === 'mapView'" :data="modalData" /> -->
<!-- 周边配套组件 -->
<!-- <SurroundingInfo
v-else-if="currentActiveKey === 'surrounding'"
:data="modalData"
/> -->
</div>
</a-tab-pane>
</a-tabs>
</div>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { ref, watch } from "vue";
// Tab
//
import BasicInfo from './components/BasicInfo.vue';
import MapView from './components/MapView.vue';
import SurroundingInfo from './components/SurroundingInfo.vue';
import BasicInfo from "./components/BasicInfo.vue";
// import MapView from './components/MapView.vue';
// import SurroundingInfo from './components/SurroundingInfo.vue';
// Tab
interface TabItem {
key: string;
title: string;
url: string;
}
// Props
@ -64,56 +51,55 @@ const props = defineProps<{
}>();
// Emits
// 'update:activeKey' v-model:active-key
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
(e: 'change', key: string): void; // tab
(e: "update:visible", value: boolean): void;
(e: "update:activeKey", key: string): void;
(e: "change", key: string): void;
}>();
// activeKey
const currentActiveKey = ref<string>(props.activeKey || '');
const currentActiveKey = ref<string>(props.activeKey || "");
// activeKey
watch(() => props.activeKey, (newVal) => {
if (newVal) {
// activeKey
watch(
() => props.activeKey,
(newVal) => {
if (newVal && newVal !== currentActiveKey.value) {
currentActiveKey.value = newVal;
}
}, { immediate: true });
},
{ immediate: true }
);
// tab
watch(currentActiveKey, (newVal) => {
emit('change', newVal);
});
// tab
const onTabChange = (key: string) => {
currentActiveKey.value = key;
// activeKey ( v-model)
emit("update:activeKey", key);
// ()
emit("change", key);
};
//
const handleClose = () => {
emit('update:visible', false);
emit("update:visible", false);
};
// 便使 props.data
const modalData = ref(props.data);
watch(() => props.data, (newVal) => {
watch(
() => props.data,
(newVal) => {
modalData.value = newVal;
});
}
);
</script>
<style lang="scss" scoped>
.map-modal {
:deep(.ant-modal-body) {
padding: 24px;
}
.map-modal-content {
min-height: 300px; //
.tab-pane-container {
padding: 10px 0;
}
.empty-placeholder {
color: #999;
text-align: center;
padding: 40px 0;
}
.content {
min-height: 600px;
}
}
</style>

View File

@ -0,0 +1,14 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useModelStore = defineStore('model', () => {
// state
const info = ref<{
type: string;
}>({
type: 'zh'
});
return {
info,
};
});

View File

@ -1,9 +1,13 @@
<script setup lang="ts">
import { onMounted } from "vue";
import { onMounted, ref } from "vue";
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();
// import { getQgcStaticData } from "@/api/ecoFlow";
onMounted(() => {
// const params = {
@ -21,6 +25,31 @@ onMounted(() => {
// console.log(res);
// });
});
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";
};
const showMapModal1 = () => {
modalVisible.value = true;
currentTabKey.value = "basicInfo";
modelInfo.info.type = "zh";
};
const onTabChange = (key: string) => {
console.log("Tab 切换为:", key);
};
</script>
<template>
@ -30,6 +59,17 @@ onMounted(() => {
</div>
<div class="rightContent">
<RightDrawer>
<!-- <a-button @click="showMapModal">打开电站地图弹窗</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>

View File

@ -856,6 +856,9 @@ onMounted(() => {
.ant-tabs-nav {
height: 38px;
}
:deep(.ant-checkbox+span){
padding-right: 0;
}
}
/* 验证码布局 */

View File

@ -0,0 +1,326 @@
<template>
<div class="guoYuDaoShuTongJi-page">
<!-- 搜索组件 -->
<ApprovalDetailSearch
:guoyu-status="guoyuStatus"
:direction="direction"
@search-finish="handleDetailSearchFinish"
@reset="handleDetailReset"
/>
<!-- 表格组件 -->
<BasicTable
ref="detailTableRef"
:columns="columns"
:isOneLoad="false"
:data="tableData"
:list-url="getFishDraftPage"
:scroll-y="'500px'"
:transform-data="customTransform"
>
</BasicTable>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, h, computed, nextTick } from "vue";
import {
batchApproveByApprovalId,
batchReject,
} from "@/api/shengPiJiLu";
import { Tag, message } from "ant-design-vue";
import BasicTable from "@/components/BasicTable/index.vue";
import ApprovalDetailSearch from "../shengPiJiLu/approvalDetailSearch.vue";
import { getDictItemsByCode } from "@/api/dict";
import { getFishDraftPage } from "@/api/guoYuSheShiShuJuTianBao";
const baseUrl = import.meta.env.VITE_APP_PREVIEW_URL;
let columns = ref([
{ dataIndex: "hbrvnm", key: "hbrvnm", title: "流域",
customCell: (_, index) => {
if (index === 0) {
return { rowSpan: 2 };
}
// These two are merged into above cell
if (index === 1) {
return { rowSpan: 0 };
}
if (index === 2) {
return { colSpan: 1 };
}
},
},
{ dataIndex: "ennm", key: "ennm", title: "电站名称",
customCell: (_, index) => {
if (index === 0) {
return { rowSpan: 2 };
}
// These two are merged into above cell
if (index === 1) {
return { rowSpan: 0 };
}
if (index === 2) {
return { colSpan: 1 };
}
},},
{ dataIndex: "stnm", key: "stnm", title: "月份" },
{ dataIndex: "startTime", key: "startTime", title: "过鱼开始时间" },
{ dataIndex: "endTime", key: "endTime", title: "过鱼结束时间" },
{ dataIndex: "ftpName", key: "ftpName", title: "本月过鱼总数" },
{ dataIndex: "ftpName1", key: "ftpName1", title: "联系人/电话", width: 250 },
]);
const tableData = ref([
{
hbrvnm: "黄河干流上游",
ennm: "玛尔挡",
stnm: "2026-03",
ftpName: 61,
ftpName1: "张三13800000000",
startTime: "2026-03-01",
endTime: "2026-03-31",
},
{
hbrvnm: "黄河干流上游",
ennm: "玛尔挡",
stnm: "2026-04",
ftpName: 666,
ftpName1: "张三13800000000",
startTime: "2026-04-01",
endTime: "2026-04-31",
},
{
hbrvnm: "雅鲁藏布江流域",
ennm: "ZM",
stnm: "2026-04",
ftpName: 777,
ftpName1: "李四13800000000",
startTime: "2026-04-01",
endTime: "2026-04-31",
},
]);
const tableRef = ref();
const handleSearchFinish = (values: any) => {
console.log(values);
const filters = [
values.status && {
field: "status",
operator: "eq",
dataType: "string",
value: values.status,
},
values.hbrvcd !== "all" && {
field: "hbrvcd",
operator: "eq",
dataType: "string",
value: values.hbrvcd,
},
values.stcd && {
field: "stcd",
operator: "eq",
dataType: "string",
value: values.stcd,
},
].filter(Boolean);
const filter = {
logic: "and",
filters: filters,
};
tableRef.value?.getList(filter);
};
const handleReset = (values) => {
handleSearchFinish(values);
};
//
const approvalLogVisible = ref(false);
const approvalLogTableRef = ref();
//
const changeLogVisible = ref(false);
const changeLogTableRef = ref();
const currentApprovalId = ref("");
const actionTypeDict = ref([]);
const operationTypeDict = ref([]);
//
const detailVisible = ref(false);
const detailTableRef = ref();
const guoyuStatus = ref([]);
const direction = ref([]);
//
const viewModalVisible = ref(false);
const editModalRef = ref<any>(null);
const currentViewRecord = ref<any>(null);
//
const mediaPreviewVisible = ref(false);
const videoPreviewTitle = ref("预览");
interface MediaItem {
id: string;
type: "image" | "video" | "formVideo" | "formImage";
name: string;
url: string;
}
const previewList = ref<MediaItem[]>([]);
const currentMediaIndex = ref(0);
//
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 handleDetailSearchFinish = (values: any) => {
console.log("详情搜索:", values);
const filters = [
values.ftp && {
field: "ftp",
operator: "eq",
dataType: "string",
value: values.ftp,
},
values.strdt && {
field: "strdt",
operator: "gte",
dataType: "date",
value: values.strdt[0] + " 00:00:00",
},
values.strdt && {
field: "strdt",
operator: "lte",
dataType: "date",
value: values.strdt[1] + " 23:59:59",
},
values.direction && {
field: "direction",
operator: "eq",
dataType: "string",
value: values.direction,
},
values.rstcd && {
field: "rstcd",
operator: "eq",
dataType: "string",
value: values.rstcd,
},
values.hbrvcd !== "all" && {
field: "hbrvcd",
operator: "eq",
dataType: "string",
value: values.hbrvcd,
},
approvalId.value && {
field: "approvalId", //
operator: "eq", //
dataType: "string", //
value: approvalId.value, // record
},
].filter(Boolean);
const filter = {
logic: "and",
filters: filters,
};
detailTableRef.value?.getList(filter);
};
//
const handleDetailReset = (values: any) => {
console.log("详情重置:", values);
handleDetailSearchFinish(values);
};
//
const approvalId = ref("");
//
onMounted(() => {
dictNmae();
//
getDictItemsByCode({ dictCode: "direction" }).then((res) => {
direction.value = res.data;
});
getDictItemsByCode({ dictCode: "approvalStatus" }).then((res) => {
guoyuStatus.value = res.data;
});
});
const shenStatus = ref([]);
const yeWuType = ref([]);
const dictNmae = () => {
getDictItemsByCode({ dictCode: "approvalStatus" }).then((res) => {
shenStatus.value = res.data;
});
getDictItemsByCode({ dictCode: "yeWuType" }).then((res) => {
yeWuType.value = res.data;
});
// TODO:
getDictItemsByCode({ dictCode: "caoType" }).then((res) => {
res.data.forEach((item: any) => {
if (item.itemCode == "UPDATE" || item.itemCode == "DELETE") {
operationTypeDict.value.push(item);
} else {
actionTypeDict.value.push(item);
}
});
});
};
const handName = (val: any, arr: any) => {
let dictName1 = "";
arr.forEach((item: any) => {
if (item.itemCode == val) {
dictName1 = item.dictName;
}
});
return dictName1;
};
//
const searchData = ref<any>({
hbrvcd: "all",
status: "",
});
//
const paramsTab = ref({
sort: [
{
field: "applyTime",
dir: "desc",
needSortFlag: true,
},
],
});
// 使 computed searchParams
const computedSearchParams = computed(() => ({
sort: paramsTab.value.sort,
}));
</script>
<style scoped lang="scss">
.guoYuDaoShuTongJi-page {
width: 100%;
height: 100%;
background-color: #ffffff;
padding: 20px;
}
</style>

View File

@ -57,46 +57,18 @@ const searchList: any = computed(() => [
},
options: [],
},
{
type: "Select",
name: "stcd",
label: "过鱼设施",
values: { name: "stnm", value: "stcd" },
fieldProps: {
allowClear: true,
},
options: shuJuTianBaoStore.fpssOption,
},
{
type: "Select",
name: "direction",
label: "游向",
width: 120,
options: props.direction,
fieldProps: {
allowClear: true,
},
},
{
type: "custom",
name: "ftp",
label: "鱼种类",
fieldProps: {
allowClear: true,
},
},
{
span: 12,
type: "RangePicker",
name: "strdt",
label: "过鱼时间",
picker: "date",
picker: "month",
fieldProps: {
format: "YYYY-MM-DD",
valueFormat: "YYYY-MM-DD",
format: "YYYY-MM",
valueFormat: "YYYY-MM",
allowClear: false,
},
presets: DateSetting.RangeButton.days,
presets: DateSetting.RangeButton.month,
},
]);

View File

@ -994,12 +994,12 @@ function handleClearSelection() {
<el-table-column prop="phone" label="手机号" width="160"></el-table-column>
<el-table-column prop="username" label="登录账号" ></el-table-column>
<!-- <el-table-column prop="custom1" label="登录账号"></el-table-column> -->
<el-table-column prop="rolename" label="所属角色" >
<!-- <el-table-column prop="rolename" label="所属角色" >
<template #default="scope">
<span v-for="(item, index) in scope.row.roles" :key="index">{{ item.rolename }} <span></span>
</span>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column prop="regStatus" label="审核状态" width="90" align="center">
<template #default="scope">
<el-tag :type="getRegStatusColor(scope.row.regStatus)" size="small">
@ -1007,7 +1007,7 @@ function handleClearSelection() {
</el-tag>
</template>
</el-table-column>
<el-table-column prop="lastmodifier" label="最近修改者" width="120"></el-table-column>
<!-- <el-table-column prop="lastmodifier" label="最近修改者" width="120"></el-table-column> -->
<el-table-column prop="lastmodifydate" label="最近修改日期" width="160">
<template #default="scope">
{{ dateFormat(scope.row.lastmodifydate) }}