39 changed files with 2330 additions and 436 deletions
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
import request from '@/utils/request' |
||||
export default { |
||||
getZscsTableList(searchModel) { |
||||
return request({ |
||||
url: "/day/getDayZscsList", |
||||
method: 'get', |
||||
params: { |
||||
pageNum: searchModel.pageNum, |
||||
pageSize: searchModel.pageSize, |
||||
startTime: searchModel.startTime, |
||||
endTime: searchModel.endTime, |
||||
stcd:searchModel.stcd, |
||||
stnm:searchModel.stnm |
||||
} |
||||
}) |
||||
}, |
||||
exportRainDataList(){ |
||||
return request({ |
||||
url: "/export/exportMonthRainList", |
||||
method: 'get', |
||||
responseType: 'blob' |
||||
}) |
||||
}, |
||||
|
||||
} |
@ -0,0 +1,124 @@
@@ -0,0 +1,124 @@
|
||||
<template> |
||||
<el-cascader |
||||
:key="componentKey" |
||||
v-model="selectedValues" |
||||
:options="options" |
||||
:props="props" |
||||
@change="handleChange" |
||||
collapse-tags |
||||
filterable |
||||
clearable> |
||||
</el-cascader> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import stationApi from "@/api/basic/station"; |
||||
|
||||
export default { |
||||
name: "station", |
||||
props: { |
||||
startTime: { type: String, required: true, default: null }, |
||||
endTime: { type: String, required: true, default: null }, |
||||
type: { |
||||
type: String, |
||||
required: true, |
||||
default:null// 强制要求父组件传递 |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
props: { |
||||
multiple: true, |
||||
checkStrictly: true,// 允许独立选择节点 |
||||
value: 'value', // 确保与数据源字段名一致 |
||||
label: 'label', |
||||
disabled: 'disabled' |
||||
}, |
||||
componentKey: 0, |
||||
options: [], |
||||
stcds: '', |
||||
selectedValues: [], // 绑定选中值 |
||||
} |
||||
}, |
||||
watch: { |
||||
// 监听时间参数变化 |
||||
startTime(newVal) { |
||||
this.checkAndFetchData(newVal, this.endTime); |
||||
}, |
||||
endTime(newVal) { |
||||
this.checkAndFetchData(this.startTime, newVal); |
||||
} |
||||
}, |
||||
methods: { |
||||
formatDateTime(date) { |
||||
if (!date) return ''; |
||||
const d = new Date(date); |
||||
if (isNaN(d.getTime())) return ''; |
||||
|
||||
const year = d.getFullYear(); |
||||
const month = String(d.getMonth() + 1).padStart(2, '0'); |
||||
const day = String(d.getDate()).padStart(2, '0'); |
||||
const hours = String(d.getHours()).padStart(2, '0'); // 小时补零 |
||||
const minutes = String(d.getMinutes()).padStart(2, '0'); // 分钟补零 |
||||
const seconds = String(d.getSeconds()).padStart(2, '0'); // 秒数补零 |
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
||||
}, |
||||
// 检查是否满足查询条件 |
||||
checkAndFetchData(start, end) { |
||||
if (start && end) { |
||||
this.componentKey++; |
||||
this.options=[] |
||||
this.selectedValues=[] |
||||
if (this.type.includes("Day") || this.type.includes("Dp")){ |
||||
// 触发查询 |
||||
this.getStaionList(this.formatDateTime(start), this.formatDateTime(end),this.type); |
||||
}else { |
||||
this.getStaionList(start, end,this.type); |
||||
} |
||||
} |
||||
}, |
||||
async getStaionList(startTime, endTime, type) { |
||||
const res = await stationApi.getStnmAndStcdList(startTime, endTime, type); |
||||
// 新增数据处理逻辑 |
||||
const processTree = (nodes) => { |
||||
return nodes.map(node => { |
||||
const hasChildren = node.children && node.children.length > 0; |
||||
return { |
||||
...node, |
||||
disabled: hasChildren, // 有子节点的父类自动禁用 |
||||
children: hasChildren ? processTree(node.children) : null |
||||
}; |
||||
}); |
||||
}; |
||||
this.options = processTree([res.data]); // 注意保持数组结构 |
||||
}, |
||||
|
||||
handleChange(selectedValues, selectedNodes) { |
||||
const value=this.selectedValues.map(path => path[path.length - 1])[0]; |
||||
if (value==='all') { |
||||
this.selectedValues = ["1,all"]; |
||||
} |
||||
const lastValue = selectedValues.map(path => path[path.length - 1]); |
||||
this.stcds = lastValue.join(",") |
||||
this.$emit('stcd-update', this.stcds); // 触发事件 |
||||
}, |
||||
getStcds() { |
||||
this.$emit('childEvent', stcds); |
||||
} |
||||
|
||||
}, |
||||
mounted() { |
||||
if (this.startTime !=null || this.endTime !=null) { |
||||
this.getStaionList(this.startTime,this.endTime,this.type) |
||||
}else { |
||||
this.getStaionList(null,null,this.type) |
||||
} |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
|
||||
</style> |
@ -0,0 +1,338 @@
@@ -0,0 +1,338 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form :inline="true" class="demo-form-inline"> |
||||
<el-form-item label="起始日期"> |
||||
<el-date-picker |
||||
v-model="searchModel.startTime" |
||||
type="datetime" |
||||
placeholder="选择日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="截止日期"> |
||||
<el-date-picker |
||||
v-model="searchModel.endTime" |
||||
type="datetime" |
||||
placeholder="选择日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="站点"> |
||||
<SelectStaion |
||||
v-if="isComponentReady" |
||||
ref="selectStaionRef" |
||||
:startTime="this.formatDate(this.searchModel.startTime)" |
||||
:endTime="this.formatDate(this.searchModel.endTime)" |
||||
:type="this.type"> |
||||
</SelectStaion> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" @click="getList">查询</el-button> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" @click="exportDate">导出</el-button> |
||||
</el-form-item> |
||||
<!-- <el-form-item>--> |
||||
<!-- <el-button--> |
||||
<!-- type="primary"--> |
||||
<!-- @click="importSoft"--> |
||||
<!-- >导入南方片--> |
||||
<!-- </el-button>--> |
||||
<!-- </el-form-item>--> |
||||
</el-form> |
||||
|
||||
<div class="main-content"> |
||||
<div class="main-title"> |
||||
<div class="table-title">逐时潮水位表</div> |
||||
<div class="table-header"> |
||||
<div class="table-time" style="float: right">单位:水位: m)</div> |
||||
</div> |
||||
</div> |
||||
<el-table |
||||
:data="tableData" |
||||
height="500" |
||||
border |
||||
style="width: 100%"> |
||||
<el-table-column label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.$index + 1 }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column |
||||
align="center" |
||||
prop="stcd" |
||||
label="站码" |
||||
> |
||||
</el-table-column> |
||||
<el-table-column |
||||
align="center" |
||||
prop="stnm" |
||||
label="站名" |
||||
> |
||||
</el-table-column> |
||||
<el-table-column |
||||
align="center" |
||||
prop="tm" |
||||
label="日期"> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
align="center" |
||||
prop="tdr" |
||||
label="潮时"> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
align="center" |
||||
prop="tdz" |
||||
label="潮水位"> |
||||
</el-table-column> |
||||
|
||||
<el-table-column |
||||
align="center" |
||||
prop="tdzrcd" |
||||
label="潮水位注解码"> |
||||
</el-table-column> |
||||
</el-table> |
||||
<el-pagination |
||||
@size-change="handleSizeChange" |
||||
@current-change="handleCurrentChange" |
||||
:current-page="searchModel.pageNum" |
||||
:page-sizes="[15, 30, 50,100]" |
||||
:page-size="searchModel.pageSize" |
||||
layout="total, sizes, prev, pager, next, jumper" |
||||
style="padding: 30px 0; text-align: center;" |
||||
:total="total" |
||||
> |
||||
</el-pagination> |
||||
</div> |
||||
<el-dialog :title="title" :visible.sync="softOpen" width="400px" append-to-body> |
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item label="起年"> |
||||
<el-date-picker |
||||
v-model="form.startTime" |
||||
type="datetime" |
||||
placeholder="选择日期" |
||||
> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="截止年"> |
||||
<el-date-picker |
||||
v-model="form.endTime" |
||||
type="datetime" |
||||
placeholder="选择日期" |
||||
> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button type="primary" @click="submitForm">确 定</el-button> |
||||
<el-button @click="cancel">取 消</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
|
||||
<script> |
||||
import dayZscsApi from "@/api/day/dayZscs"; |
||||
import SelectStaion from "@/components/SelectStaion/index.vue"; |
||||
|
||||
export default { |
||||
components: {SelectStaion}, |
||||
data() { |
||||
return { |
||||
tableData: [], |
||||
total: 0, |
||||
searchModel: { |
||||
startTime: '2014-01-01 00:00:00', |
||||
endTime: '2015-01-01 00:00:00', |
||||
stcd: '', |
||||
stnm: '', |
||||
pageNum: 1, |
||||
pageSize: 15 |
||||
}, |
||||
upload: { |
||||
title: '导入数据', |
||||
open: false |
||||
}, |
||||
|
||||
softOpen: false, |
||||
title: '', |
||||
form: { |
||||
startTime: '', |
||||
endTime: '' |
||||
}, |
||||
// 表单校验 |
||||
rules: { |
||||
startTime: [ |
||||
{required: true, message: '开始时间不能为空', trigger: 'blur'} |
||||
], |
||||
endTime: [ |
||||
{required: true, message: '结束时间不能为空', trigger: 'blur'} |
||||
] |
||||
}, |
||||
isComponentReady: false, |
||||
type:"DayZscs", |
||||
} |
||||
}, |
||||
created() { |
||||
this.getList() |
||||
}, |
||||
mounted() { |
||||
this.$nextTick(() => { |
||||
this.isComponentReady = true; |
||||
}); |
||||
this.$nextTick(() => { |
||||
if (this.$refs.selectStaionRef) { |
||||
this.searchModel.stcd = this.$refs.selectStaionRef.stcds; |
||||
} |
||||
}); |
||||
}, |
||||
methods: { |
||||
formatDate(date) { |
||||
if (date == null) { |
||||
return ''; |
||||
} |
||||
const d = new Date(date); |
||||
if (isNaN(d.getTime())) { |
||||
return ''; |
||||
} else { |
||||
return date |
||||
} |
||||
}, |
||||
|
||||
async getList() { |
||||
this.searchModel.stcd = this.$refs.selectStaionRef?.stcds || ''; |
||||
const startYear = this.$common.formatDate(this.searchModel.startTime) |
||||
const endYear = this.$common.formatDate(this.searchModel.endTime) |
||||
const param = { |
||||
pageNum: this.searchModel.pageNum, |
||||
pageSize: this.searchModel.pageSize, |
||||
startTime: this.formatDate(startYear), |
||||
endTime: this.formatDate(endYear), |
||||
stcd: this.searchModel.stcd, |
||||
stnm: this.searchModel.stnm |
||||
} |
||||
const res = await dayZscsApi.getZscsTableList(param) |
||||
this.tableData = res.data; |
||||
this.total = res.count; |
||||
}, |
||||
handleSizeChange(pageSize) { |
||||
this.searchModel.pageSize = pageSize |
||||
this.getList() |
||||
}, |
||||
handleCurrentChange(pageNum) { |
||||
this.searchModel.pageNum = pageNum |
||||
this.getList() |
||||
}, |
||||
async exportDate() { |
||||
const startYear = this.$common.formatDate(this.searchModel.startTime) |
||||
const endYear = this.$common.formatDate(this.searchModel.endTime) |
||||
const stcd = this.searchModel.stcd || ''; // 处理undefined |
||||
const stnm = this.searchModel.stnm || ''; |
||||
const res = await this.$axiosPost('/report/dayZscs?startTime=' + |
||||
this.formatDate(startYear) + '&endTime=' + this.formatDate(endYear) + |
||||
'&stcd=' + stcd + '&stnm=' + stnm); |
||||
if (res.code === 0) { |
||||
this.$modal.msgSuccess(res.msg) |
||||
} |
||||
// |
||||
// this.download('/report/dayRain?startTime='+ |
||||
// startYear+'&endTime='+endYear+ |
||||
// '&stcd='+this.searchModel.stcd+'&stnm='+this.searchModel.stnm, {}, '日降水表.xls') |
||||
}, |
||||
importSoft() { |
||||
this.reset(); |
||||
this.softOpen = true; |
||||
this.title = "导入数据到南方片"; |
||||
}, |
||||
reset() { |
||||
this.form = { |
||||
startTime: '', |
||||
endTime: '' |
||||
} |
||||
this.resetForm("form"); |
||||
}, |
||||
/** 提交按钮 */ |
||||
submitForm() { |
||||
const startYear = this.$common.formatDate(this.form.startTime) |
||||
const endYear = this.$common.formatDate(this.form.endTime) |
||||
const param = { |
||||
startTime: this.formatDate(startYear), |
||||
endTime: this.formatDate(endYear), |
||||
} |
||||
this.$refs["form"].validate(valid => { |
||||
if (valid) { |
||||
dayRainApi.importDateToSoft(param).then(res => { |
||||
if (res.code === 0) { |
||||
this.$modal.msgSuccess(res.msg) |
||||
this.softOpen = false; |
||||
} |
||||
}) |
||||
} |
||||
}); |
||||
}, |
||||
cancel() { |
||||
this.softOpen = false; |
||||
this.reset(); |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
.app-container { |
||||
padding: 20px; |
||||
background: #F2F2F2; |
||||
height: calc(100vh - 100px); |
||||
|
||||
.el-form { |
||||
background: #fff; |
||||
padding: 10px; |
||||
height: 6vh; |
||||
border-radius: 4px; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
} |
||||
|
||||
.main-content { |
||||
height: calc(100vh - 150px); |
||||
background: #fff; |
||||
margin-top: 20px; |
||||
padding: 5px; |
||||
border-radius: 4px; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
|
||||
.main-title { |
||||
height: 90px; |
||||
|
||||
.table-title { |
||||
font-size: 25px; |
||||
font-weight: bold; |
||||
width: 100%; |
||||
height: 60px; |
||||
text-align: center; |
||||
} |
||||
|
||||
.table-header { |
||||
width: 100%; |
||||
height: 30px; |
||||
line-height: 30px; |
||||
display: inline; |
||||
padding: 0 20px; |
||||
font-size: 14px; |
||||
|
||||
.table-time { |
||||
display: inline; |
||||
float: left; |
||||
margin-left: 20px; |
||||
font-size: 14px; |
||||
color: #606266; |
||||
font-weight: 700; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
:hover::-webkit-scrollbar { |
||||
width: 0; /* 鼠标 hover 时显示滚动条 */ |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,729 @@
@@ -0,0 +1,729 @@
|
||||
<template> |
||||
<div class="app-container"> |
||||
<div class="el-header"> |
||||
<el-form :inline="true" ref="mainForm" |
||||
:model="formData" |
||||
:rules="formRules" |
||||
class="demo-form-inline"> |
||||
<!-- 服务器配置部分 --> |
||||
<el-form-item label="数据服务器IP:" prop="sqlseverIp"> |
||||
<el-input v-model="formData.sqlseverIp"></el-input> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="登录名" prop="userName"> |
||||
<el-input v-model="formData.userName"></el-input> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="密码" prop="password"> |
||||
<el-input v-model="formData.password" type="password"></el-input> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="数据库名称:" prop="dataBase"> |
||||
<el-input v-model="formData.dataBase"></el-input> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button type="primary" @click="testConnection">测试连接</el-button> |
||||
</el-form-item> |
||||
|
||||
|
||||
</el-form> |
||||
</div> |
||||
<div class="el-left"> |
||||
<div class="table-title">南方片数据交互</div> |
||||
<el-form> |
||||
<el-form-item style="margin-left: 15%" label="交互类型:" prop="softTypeValue"> |
||||
<el-select style="margin-left: 5%" v-model="formData.softTypeValue" clearable placeholder="请选择交互类型"> |
||||
<el-option |
||||
v-for="item in softType" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value"> |
||||
</el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item style="margin-left: 15%" label="开始时间:" prop="startTime"> |
||||
<el-date-picker |
||||
style="margin-left: 5%" |
||||
v-model="formData.startTime" |
||||
type="month" |
||||
placeholder="选择日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
|
||||
<el-form-item style="margin-left: 15%" label="结束时间:" prop="endTime"> |
||||
<el-date-picker |
||||
style="margin-left: 5%" |
||||
v-model="formData.endTime" |
||||
type="month" |
||||
placeholder="选择日期"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
|
||||
<el-form-item label="类型:" style="margin-left: 15%" prop="stationTypeValue"> |
||||
<el-select style="margin-left: 12%" v-model="formData.stationTypeValue" clearable placeholder="请选择类型"> |
||||
<el-option |
||||
v-for="item in stationType" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value"> |
||||
</el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
|
||||
<el-form-item> |
||||
<el-button style="float: right" type="primary" @click="submitForm">提交</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
<div class="el-middle"> |
||||
<div class="table-title">可选测站</div> |
||||
<div style="width: 60%; margin-bottom: 5px; margin-left: 22%"> |
||||
<el-input placeholder="请输入站点名称" v-model="filterText" clearable /> |
||||
</div> |
||||
<!-- 新增滚动容器 --> |
||||
<div style="margin-left: 20%" class="tree-scroll-container"> |
||||
<el-tree |
||||
ref="tree" |
||||
:data="options" |
||||
:props="props" |
||||
node-key="value" |
||||
:filter-node-method="filterNode" |
||||
@check-change="handleCheckChange" |
||||
:highlight-current="true" |
||||
default-expand-all |
||||
show-checkbox |
||||
/> |
||||
</div> |
||||
</div> |
||||
<div class="el-main"> |
||||
<el-table |
||||
:data="tableData" |
||||
ref="treeTable" |
||||
:row-class-name="getRowClassName" |
||||
row-key="id" |
||||
:tree-props="{children: 'children'}" |
||||
@select="handleSelect" |
||||
@select-all="handleSelectAll" |
||||
default-expand-all |
||||
border |
||||
> |
||||
<!-- 多选列 --> |
||||
<el-table-column |
||||
type="selection" |
||||
width="55" |
||||
:reserve-selection="true"> |
||||
</el-table-column> |
||||
|
||||
<!-- 树形内容列 --> |
||||
<el-table-column label="所有表项"> |
||||
<template slot-scope="{ row }"> |
||||
<span :style="{ paddingLeft: (row.level * 18) + 'px' }"> |
||||
{{ row.label }} |
||||
</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import {treeselect} from "@/api/system/dept"; |
||||
import Treeselect from "@riophae/vue-treeselect"; |
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
||||
import stationApi from "@/api/basic/station"; |
||||
import dayRainApi from "@/api/day/dayRain"; |
||||
|
||||
|
||||
export default { |
||||
data() { |
||||
return { |
||||
formData: { |
||||
sqlseverIp: '', |
||||
userName: '', |
||||
password: '', |
||||
dataBase: '', |
||||
softTypeValue: '', |
||||
startTime: '', |
||||
endTime: '', |
||||
stationTypeValue: '', |
||||
selectedValues: [] |
||||
}, |
||||
// 表单验证规则 |
||||
formRules: { |
||||
sqlseverIp: [ |
||||
{required: true, message: '请输入数据服务器IP', trigger: 'blur'} |
||||
], |
||||
userName: [ |
||||
{required: true, message: '请输入登录名', trigger: 'blur'} |
||||
], |
||||
password: [ |
||||
{required: true, message: '请输入密码', trigger: 'blur'} |
||||
], |
||||
dataBase: [ |
||||
{required: true, message: '请输入数据库名称', trigger: 'blur'} |
||||
], |
||||
softTypeValue: [ |
||||
{required: true, message: '请选择交互类型', trigger: 'change'} |
||||
], |
||||
startTime: [ |
||||
{required: true, message: '请选择开始时间', trigger: 'change'} |
||||
], |
||||
endTime: [ |
||||
{required: true, message: '请选择结束时间', trigger: 'change'} |
||||
], |
||||
stationTypeValue: [ |
||||
{required: true, message: '请选择类型', trigger: 'change'} |
||||
], |
||||
selectedValues: [ |
||||
{required: true, message: '请选择站点', trigger: 'change'} |
||||
] |
||||
}, |
||||
isAllSelected: false, |
||||
tableData: [ |
||||
{ |
||||
id: 1, |
||||
label: '基本信息', |
||||
parentId: null, |
||||
level: 0, |
||||
checked: false, |
||||
indeterminate: false, // 添加半选状态标识 |
||||
children: [ |
||||
{id: 11, parentId: 1, label: '测站信息一览表', level: 1, checked: false}, |
||||
] |
||||
}, |
||||
{ |
||||
id: 2, |
||||
label: '雨量资料', |
||||
level: 0, |
||||
parentId: null, |
||||
checked: false, |
||||
indeterminate: false, // 添加半选状态标识 |
||||
children: [ |
||||
{id: 21, parentId: 2, label: '逐日降水表', level: 1, checked: false}, |
||||
{id: 22, parentId: 2, label: '各时段最大降水表(1)', level: 1, checked: false}, |
||||
{id: 23, parentId: 2, label: '各时段最大降水表(2)', level: 1, checked: false}, |
||||
{id: 24, parentId: 2, label: '降水量摘录表', level: 1, checked: false}, |
||||
] |
||||
}, |
||||
{ |
||||
id: 3, |
||||
label: '水位资料', |
||||
level: 0, |
||||
parentId: null, |
||||
checked: false, |
||||
indeterminate: false, // 添加半选状态标识 |
||||
children: [ |
||||
{id: 31, parentId: 3, label: '逐日平均水位表', level: 1, checked: false}, |
||||
{id: 32, parentId: 3, label: '水闸洪水水文要素摘录表', level: 1, checked: false}, |
||||
{id: 33, parentId: 4, label: '逐潮高低潮位表', level: 1, checked: false}, |
||||
{id: 34, parentId: 4, label: '潮位月年统计表', level: 1, checked: false}, |
||||
] |
||||
}, |
||||
{ |
||||
id: 5, |
||||
label: '流量资料', |
||||
level: 0, |
||||
parentId: null, |
||||
checked: false, |
||||
indeterminate: false, // 添加半选状态标识 |
||||
children: [ |
||||
{id: 51, parentId: 5, label: '逐日平均流量表', level: 1, checked: false}, |
||||
] |
||||
}, |
||||
], |
||||
softType: [{ |
||||
value: '0', |
||||
label: '导出数据到云服务数据库' |
||||
}, { |
||||
value: '1', |
||||
label: '导入数据到南方片数据库' |
||||
}], |
||||
softTypeValue: '', |
||||
stationType: [ |
||||
{ |
||||
value: 'P', |
||||
label: '雨量站' |
||||
}, |
||||
{ |
||||
value: 'H', |
||||
label: '水文站' |
||||
}, |
||||
{ |
||||
value: 'Q', |
||||
label: '水位站' |
||||
} |
||||
], |
||||
stationTypeValue: '', |
||||
props: { |
||||
multiple: true, |
||||
checkStrictly: true,// 允许独立选择节点 |
||||
value: 'value', // 确保与数据源字段名一致 |
||||
label: 'label', |
||||
disabled: 'disabled' |
||||
}, |
||||
componentKey: 0, |
||||
options: [], |
||||
stcds: '', |
||||
filterText:"", |
||||
selectedValues: [], // 绑定选中值 |
||||
// 遮罩层 |
||||
loading: true, |
||||
// 显示搜索条件 |
||||
showSearch: true, |
||||
// 总条数 |
||||
total: 0, |
||||
// 弹出层标题 |
||||
title: "", |
||||
// 表单参数 |
||||
form: {}, |
||||
// 表单校验 |
||||
rules: {}, |
||||
dateYear: [], |
||||
deptOptions: undefined, |
||||
isHandlingCheckChange: false |
||||
}; |
||||
}, |
||||
created() { |
||||
}, |
||||
watch: { |
||||
filterText(val) { |
||||
this.$refs['tree'].filter(val); |
||||
}, |
||||
'formData.startTime': { |
||||
handler(newVal) { |
||||
this.checkAndFetchData(newVal, this.formData.endTime, this.formData.stationTypeValue); |
||||
}, |
||||
immediate: true // 初始立即执行 |
||||
}, |
||||
'formData.endTime'(newVal) { |
||||
this.checkAndFetchData(this.formData.startTime, newVal, this.formData.stationTypeValue); |
||||
}, |
||||
'formData.stationTypeValue'(newVal) { |
||||
this.checkAndFetchData(this.formData.startTime, this.formData.endTime, newVal); |
||||
} |
||||
}, |
||||
methods: { |
||||
filterNode(value, data) { |
||||
if (!value) return true; |
||||
return data.label.indexOf(value) !== -1; |
||||
}, |
||||
handleCheckChange(data, checked, indeterminate) { |
||||
// 防止递归调用 |
||||
if (this.isHandlingCheckChange) return; |
||||
this.isHandlingCheckChange = true; |
||||
|
||||
try { |
||||
// 获取当前所有选中的节点(包括非叶子节点) |
||||
const checkedKeys = this.$refs.tree.getCheckedKeys(); |
||||
|
||||
// 情况1:当前选中了"all"节点 |
||||
if (data.value === 'all' && checked) { |
||||
// 只保留"all"节点 |
||||
this.$refs.tree.setCheckedKeys(['all']); |
||||
this.stcds = 'all'; |
||||
} |
||||
// 情况2:当前选中了其他节点(非all) |
||||
else if (checked && data.value !== 'all') { |
||||
// 如果已存在"all"节点,先移除 |
||||
if (checkedKeys.includes('all')) { |
||||
const newCheckedKeys = checkedKeys.filter(key => key !== 'all'); |
||||
this.$refs.tree.setCheckedKeys(newCheckedKeys); |
||||
this.stcds = newCheckedKeys.join(","); |
||||
} else { |
||||
// 直接更新为当前选中的节点 |
||||
this.stcds = this.$refs.tree.getCheckedKeys(true).join(","); |
||||
} |
||||
} |
||||
// 情况3:取消选中操作 |
||||
else { |
||||
this.stcds = this.$refs.tree.getCheckedKeys(true).join(","); |
||||
} |
||||
} finally { |
||||
this.isHandlingCheckChange = false; |
||||
} |
||||
}, |
||||
getRowClassName({row}) { |
||||
if (row.indeterminate) { |
||||
return 'indeterminate-row'; // 应用半选样式 |
||||
} |
||||
return ''; |
||||
}, |
||||
// 查找父节点 |
||||
findParent(parentId) { |
||||
if (!parentId) return null; |
||||
|
||||
// 广度优先搜索父节点 |
||||
const queue = [...this.tableData]; |
||||
while (queue.length) { |
||||
const node = queue.shift(); |
||||
if (node.id === parentId) return node; |
||||
if (node.children) queue.push(...node.children); |
||||
} |
||||
return null; |
||||
}, |
||||
|
||||
// 1. 单行选择处理(父子联动) |
||||
handleSelect(selection, row) { |
||||
if (row.indeterminate && !selection.includes(row)) { |
||||
this.clearIndeterminateState(row); // 新增方法 |
||||
} else { |
||||
row.checked = selection.includes(row); |
||||
|
||||
// 处理子节点 |
||||
if (row.children) { |
||||
this.toggleChildren(row, row.checked); |
||||
} |
||||
} |
||||
// 更新父节点状态 |
||||
this.updateParentStatus(row); |
||||
}, |
||||
// 新增:清除半选节点及子节点状态 |
||||
clearIndeterminateState(node) { |
||||
// 重置当前节点状态 |
||||
node.checked = false; |
||||
node.indeterminate = false; |
||||
this.$refs.treeTable.toggleRowSelection(node, false); |
||||
|
||||
// 递归清除子节点 |
||||
if (node.children) { |
||||
node.children.forEach(child => { |
||||
this.clearIndeterminateState(child); |
||||
}); |
||||
} |
||||
}, |
||||
// 2. 递归设置子节点状态 |
||||
toggleChildren(node, isSelected) { |
||||
if (node.children) { |
||||
node.children.forEach(child => { |
||||
// 设置子节点选中状态 |
||||
this.$refs.treeTable.toggleRowSelection(child, isSelected); |
||||
child.checked = isSelected; |
||||
|
||||
// 递归处理孙子节点 |
||||
if (child.children) this.toggleChildren(child, isSelected); |
||||
}); |
||||
} |
||||
}, |
||||
|
||||
// 3. 更新父节点状态(关键修复) |
||||
// 在 updateParentStatus 中强化半选处理 |
||||
updateParentStatus(childNode) { |
||||
const parent = this.findParent(childNode.parentId); |
||||
if (!parent) return; |
||||
|
||||
const checkedCount = parent.children.filter(c => c.checked).length; |
||||
const indeterminateCount = parent.children.filter(c => c.indeterminate).length; // 新增 |
||||
|
||||
// 强化半选判断逻辑 |
||||
parent.checked = checkedCount === parent.children.length; |
||||
parent.indeterminate = |
||||
(checkedCount > 0 && checkedCount < parent.children.length) || |
||||
indeterminateCount > 0; // 关键修复[7](@ref) |
||||
|
||||
// 更新UI |
||||
this.$refs.treeTable.toggleRowSelection(parent, parent.checked); |
||||
this.$set(parent, 'indeterminate', parent.indeterminate); |
||||
|
||||
// 半选状态特殊处理 |
||||
if (parent.indeterminate && !parent.checked) { |
||||
// 强制清除可能残留的半选状态 |
||||
parent.children.forEach(child => { |
||||
if (child.indeterminate) { |
||||
this.clearIndeterminateState(child); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
}, |
||||
|
||||
// 4. 全选/全不选处理(修复版) |
||||
handleSelectAll(selection) { |
||||
const isAllSelected = selection.length > 0; |
||||
|
||||
// 深度递归设置所有节点状态 |
||||
const setAllSelection = (nodes, status) => { |
||||
nodes.forEach(node => { |
||||
// 设置当前节点状态 |
||||
node.checked = status; |
||||
node.indeterminate = false; // 清除半选状态 |
||||
this.$refs.treeTable.toggleRowSelection(node, status); |
||||
|
||||
// 递归处理子节点 |
||||
if (node.children && node.children.length) { |
||||
setAllSelection(node.children, status); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
setAllSelection(this.tableData, isAllSelected); |
||||
|
||||
// 特殊处理:取消全选时强制清空选中项 |
||||
if (!isAllSelected) { |
||||
this.$nextTick(() => { |
||||
this.$refs.treeTable.clearSelection(); // 关键修复[1,3](@ref) |
||||
}); |
||||
} |
||||
}, |
||||
formatDateToYearMonth(date) { |
||||
if (date == null) { |
||||
return ''; |
||||
} |
||||
const d = new Date(date); |
||||
if (isNaN(d.getTime())) { |
||||
return ''; |
||||
} |
||||
const year = d.getFullYear(); |
||||
const month = (d.getMonth() + 1).toString().padStart(2, '0'); |
||||
return `${year}-${month}`; |
||||
}, |
||||
// 检查是否满足查询条件 |
||||
checkAndFetchData(start, end, stationTypeValue) { |
||||
if (start && end && stationTypeValue) { |
||||
this.componentKey++; |
||||
this.options = [] |
||||
this.formData.selectedValues = [] |
||||
this.getStaionList(start, end, stationTypeValue); |
||||
|
||||
} |
||||
}, |
||||
async testConnection() { |
||||
const res = await stationApi.testSqlConnection(this.formData) |
||||
if (res.code === 0) { |
||||
this.$modal.msgSuccess(res.data) |
||||
} else { |
||||
this.$modal.msgError("链接失败") |
||||
} |
||||
}, |
||||
async getStaionList(start, end, type) { |
||||
const res = await stationApi.getStnmAndStcdByType(this.formatDateToYearMonth(start), |
||||
this.formatDateToYearMonth(end), type); |
||||
// 新增数据处理逻辑 |
||||
const processTree = (nodes) => { |
||||
return nodes.map(node => { |
||||
const hasChildren = node.children && node.children.length > 0; |
||||
return { |
||||
...node, |
||||
disabled: hasChildren, // 有子节点的父类自动禁用 |
||||
children: hasChildren ? processTree(node.children) : null |
||||
}; |
||||
}); |
||||
}; |
||||
this.options = processTree([res.data]); // 注意保持数组结构 |
||||
}, |
||||
|
||||
|
||||
submitForm() { |
||||
this.$refs.mainForm.validate(valid => { |
||||
if (valid) { |
||||
// 所有验证通过,执行提交操作 |
||||
this.executeSubmit(this.formData); |
||||
} else { |
||||
// 验证失败,显示错误提示 |
||||
this.$message.error('请填写所有必填项'); |
||||
return false; |
||||
} |
||||
}); |
||||
// this.executeSubmit(this.formData); |
||||
}, |
||||
getFilteredSelection() { |
||||
const allSelected = this.$refs.treeTable.selection; // 获取所有选中节点[1](@ref) |
||||
const result = []; |
||||
|
||||
// 遍历选中节点,按规则过滤 |
||||
allSelected.forEach(node => { |
||||
const isParent = node.children && node.children.length > 0; |
||||
|
||||
// 规则1:父节点被选中时,忽略其所有子节点 |
||||
if (isParent && allSelected.some(n => n.parentId === node.id)) { |
||||
return; // 跳过子节点 |
||||
} |
||||
|
||||
// 规则2:子节点被选中时保留 |
||||
result.push(node); |
||||
}); |
||||
|
||||
return result; |
||||
}, |
||||
executeSubmit(formData) { |
||||
const filteredData = this.getFilteredSelection(); |
||||
const ids = filteredData.length |
||||
? filteredData.map(item => item.id).join(',') |
||||
: ''; |
||||
const params = { |
||||
sqlseverIp: this.formData.sqlseverIp, |
||||
userName: this.formData.userName, |
||||
password: this.formData.password, |
||||
dataBase: this.formData.dataBase, |
||||
startTime: this.formatDateToYearMonth(this.formData.startTime), |
||||
endTime: this.formatDateToYearMonth(this.formData.endTime), |
||||
softTypeValue: this.formData.softTypeValue, |
||||
stationTypeValue: this.formData.stationTypeValue, |
||||
stcds: this.stcds, |
||||
ids: ids |
||||
} |
||||
stationApi.importDateToSoftOrExportSoft(params).then(res => { |
||||
if (res.code === 0) { |
||||
this.$modal.msgSuccess(res.msg); |
||||
} else { |
||||
this.$modal.msgError(res.msg); |
||||
} |
||||
}); |
||||
}, |
||||
// 取消按钮 |
||||
cancel() { |
||||
this.open = false; |
||||
this.softOpen = false; |
||||
this.reset(); |
||||
}, |
||||
// 表单重置 |
||||
reset() { |
||||
this.form = { |
||||
startTime: '', |
||||
endTime: '' |
||||
} |
||||
this.resetForm("form"); |
||||
}, |
||||
/** 搜索按钮操作 */ |
||||
handleQuery() { |
||||
this.queryParams.page = 1; |
||||
this.getList(); |
||||
}, |
||||
/** 重置按钮操作 */ |
||||
resetQuery() { |
||||
this.resetForm("queryForm"); |
||||
this.handleQuery(); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
} |
||||
}; |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
.app-container { |
||||
background: #F2F2F2; |
||||
|
||||
.el-header { |
||||
border-radius: 4px; |
||||
background: #FFFFFF; |
||||
color: #333; |
||||
padding: 10px; |
||||
height: 55px; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
} |
||||
|
||||
//.el-header { |
||||
// border-radius: 4px; |
||||
// background: #FFFFFF; |
||||
// color: #333; |
||||
// padding: 10px; |
||||
// height: 100px; |
||||
// box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
//} |
||||
|
||||
|
||||
.el-middle { |
||||
.table-title{ |
||||
font-size: 25px; |
||||
font-weight: bold; |
||||
width: 100%; |
||||
height: 60px; |
||||
// line-height: 30px; |
||||
text-align: center; |
||||
} |
||||
border-radius: 4px; |
||||
color: #333; |
||||
overflow: hidden; /* 改为允许滚动条 */ |
||||
background: #FFFFFF; |
||||
text-align: center; |
||||
height: calc(95vh - 120px); |
||||
padding: 5px !important; |
||||
float: left; |
||||
width: 30%; |
||||
margin-left: 20px; |
||||
margin-top: 20px; |
||||
padding-bottom: 15px !important; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
/* 专用滚动容器样式 */ |
||||
.tree-scroll-container { |
||||
height: calc(100% - 40px); /* 减去输入框高度 */ |
||||
overflow: auto; /* 双向滚动 */ |
||||
} |
||||
/* 修复横向滚动 */ |
||||
.tree-scroll-container .el-tree { |
||||
min-width: 100%; |
||||
} |
||||
.el-table .el-checkbox__input.is-indeterminate .el-checkbox__inner { |
||||
background-color: #409EFF; |
||||
border-color: #409EFF; |
||||
} |
||||
} |
||||
|
||||
.el-left { |
||||
.table-title{ |
||||
font-size: 25px; |
||||
font-weight: bold; |
||||
width: 100%; |
||||
height: 60px; |
||||
// line-height: 30px; |
||||
text-align: center; |
||||
} |
||||
border-radius: 4px; |
||||
color: #333; |
||||
background: #FFFFFF; |
||||
text-align: center; |
||||
height: calc(95vh - 120px); |
||||
padding: 5px !important; |
||||
float: left; |
||||
width: 25%; |
||||
margin-top: 20px; |
||||
padding-bottom: 15px !important; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
|
||||
.el-table .el-checkbox__input.is-indeterminate .el-checkbox__inner { |
||||
background-color: #409EFF; |
||||
border-color: #409EFF; |
||||
} |
||||
} |
||||
|
||||
.el-main { |
||||
border-radius: 4px; |
||||
color: #333; |
||||
background: #FFFFFF; |
||||
text-align: center; |
||||
height: calc(95vh - 120px); |
||||
padding: 5px !important; |
||||
float: right; |
||||
width: 43%; |
||||
margin-top: 20px; |
||||
padding-bottom: 15px !important; |
||||
box-shadow: 0 0 10px 1px rgba(123, 123, 123, 0.4); |
||||
|
||||
.el-table .el-checkbox__input.is-indeterminate .el-checkbox__inner { |
||||
background-color: #409EFF; |
||||
border-color: #409EFF; |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
<!-- 在组件中添加CSS样式 --> |
||||
<style> |
||||
/* 半选状态样式 */ |
||||
.el-table .indeterminate-row .el-checkbox__inner { |
||||
background-color: #409EFF; |
||||
border-color: #409EFF; |
||||
} |
||||
|
||||
.el-table .indeterminate-row .el-checkbox__inner::after { |
||||
content: ""; |
||||
position: absolute; |
||||
display: block; |
||||
background-color: white; |
||||
height: 2px; |
||||
width: 55%; |
||||
top: 50%; |
||||
left: 20%; |
||||
transform: translateY(-50%); |
||||
} |
||||
</style> |
Loading…
Reference in new issue