16 changed files with 2314 additions and 3 deletions
@ -0,0 +1,497 @@
@@ -0,0 +1,497 @@
|
||||
// Extend the Array class
|
||||
Array.prototype.max = function () { |
||||
return Math.max.apply(null, this); |
||||
}; |
||||
Array.prototype.min = function () { |
||||
return Math.min.apply(null, this); |
||||
}; |
||||
Array.prototype.mean = function () { |
||||
var i, sum; |
||||
for (i = 0, sum = 0; i < this.length; i++) |
||||
sum += this[i]; |
||||
return sum / this.length; |
||||
}; |
||||
Array.prototype.pip = function (x, y) { |
||||
var i, j, c = false; |
||||
for (i = 0, j = this.length - 1; i < this.length; j = i++) { |
||||
if (((this[i][1] > y) != (this[j][1] > y)) && |
||||
(x < (this[j][0] - this[i][0]) * (y - this[i][1]) / (this[j][1] - this[i][1]) + this[i][0])) { |
||||
c = !c; |
||||
} |
||||
} |
||||
return c; |
||||
} |
||||
|
||||
var kriging = function () { |
||||
var kriging = {}; |
||||
|
||||
var createArrayWithValues = function (value, n) { |
||||
var array = []; |
||||
for (var i = 0; i < n; i++) { |
||||
array.push(value); |
||||
} |
||||
return array; |
||||
}; |
||||
|
||||
// Matrix algebra
|
||||
var kriging_matrix_diag = function (c, n) { |
||||
var Z = createArrayWithValues(0, n * n); |
||||
for (i = 0; i < n; i++) Z[i * n + i] = c; |
||||
return Z; |
||||
}; |
||||
var kriging_matrix_transpose = function (X, n, m) { |
||||
var i, j, Z = Array(m * n); |
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < m; j++) |
||||
Z[j * n + i] = X[i * m + j]; |
||||
return Z; |
||||
}; |
||||
var kriging_matrix_scale = function (X, c, n, m) { |
||||
var i, j; |
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < m; j++) |
||||
X[i * m + j] *= c; |
||||
}; |
||||
var kriging_matrix_add = function (X, Y, n, m) { |
||||
var i, j, Z = Array(n * m); |
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < m; j++) |
||||
Z[i * m + j] = X[i * m + j] + Y[i * m + j]; |
||||
return Z; |
||||
}; |
||||
// Naive matrix multiplication
|
||||
var kriging_matrix_chol = function (X, n) { |
||||
var i, j, k, sum, p = Array(n); |
||||
for (i = 0; i < n; i++) p[i] = X[i * n + i]; |
||||
for (i = 0; i < n; i++) { |
||||
for (j = 0; j < i; j++) |
||||
p[i] -= X[i * n + j] * X[i * n + j]; |
||||
if (p[i] <= 0) return false; |
||||
p[i] = Math.sqrt(p[i]); |
||||
for (j = i + 1; j < n; j++) { |
||||
for (k = 0; k < i; k++) |
||||
X[j * n + i] -= X[j * n + k] * X[i * n + k]; |
||||
X[j * n + i] /= p[i]; |
||||
} |
||||
} |
||||
for (i = 0; i < n; i++) X[i * n + i] = p[i]; |
||||
return true; |
||||
}; |
||||
// Cholesky decomposition
|
||||
kriging_matrix_chol = function (X, n) { |
||||
var i, j, k, sum, p = Array(n); |
||||
for (i = 0; i < n; i++) p[i] = X[i * n + i]; |
||||
for (i = 0; i < n; i++) { |
||||
for (j = 0; j < i; j++) |
||||
p[i] -= X[i * n + j] * X[i * n + j]; |
||||
if (p[i] <= 0) return false; |
||||
p[i] = Math.sqrt(p[i]); |
||||
for (j = i + 1; j < n; j++) { |
||||
for (k = 0; k < i; k++) |
||||
X[j * n + i] -= X[j * n + k] * X[i * n + k]; |
||||
X[j * n + i] /= p[i]; |
||||
} |
||||
} |
||||
for (i = 0; i < n; i++) X[i * n + i] = p[i]; |
||||
return true; |
||||
}; |
||||
// Inversion of cholesky decomposition
|
||||
var kriging_matrix_chol2inv = function (X, n) { |
||||
var i, j, k, sum; |
||||
for (i = 0; i < n; i++) { |
||||
X[i * n + i] = 1 / X[i * n + i]; |
||||
for (j = i + 1; j < n; j++) { |
||||
sum = 0; |
||||
for (k = i; k < j; k++) |
||||
sum -= X[j * n + k] * X[k * n + i]; |
||||
X[j * n + i] = sum / X[j * n + j]; |
||||
} |
||||
} |
||||
for (i = 0; i < n; i++) |
||||
for (j = i + 1; j < n; j++) |
||||
X[i * n + j] = 0; |
||||
for (i = 0; i < n; i++) { |
||||
X[i * n + i] *= X[i * n + i]; |
||||
for (k = i + 1; k < n; k++) |
||||
X[i * n + i] += X[k * n + i] * X[k * n + i]; |
||||
for (j = i + 1; j < n; j++) |
||||
for (k = j; k < n; k++) |
||||
X[i * n + j] += X[k * n + i] * X[k * n + j]; |
||||
} |
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < i; j++) |
||||
X[i * n + j] = X[j * n + i]; |
||||
|
||||
}; |
||||
// Inversion via gauss-jordan elimination
|
||||
var kriging_matrix_solve = function (X, n) { |
||||
var m = n; |
||||
var b = Array(n * n); |
||||
var indxc = Array(n); |
||||
var indxr = Array(n); |
||||
var ipiv = Array(n); |
||||
var i, icol, irow, j, k, l, ll; |
||||
var big, dum, pivinv, temp; |
||||
|
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < n; j++) { |
||||
if (i == j) b[i * n + j] = 1; |
||||
else b[i * n + j] = 0; |
||||
} |
||||
for (j = 0; j < n; j++) ipiv[j] = 0; |
||||
for (i = 0; i < n; i++) { |
||||
big = 0; |
||||
for (j = 0; j < n; j++) { |
||||
if (ipiv[j] != 1) { |
||||
for (k = 0; k < n; k++) { |
||||
if (ipiv[k] == 0) { |
||||
if (Math.abs(X[j * n + k]) >= big) { |
||||
big = Math.abs(X[j * n + k]); |
||||
irow = j; |
||||
icol = k; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
++(ipiv[icol]); |
||||
|
||||
if (irow != icol) { |
||||
for (l = 0; l < n; l++) { |
||||
temp = X[irow * n + l]; |
||||
X[irow * n + l] = X[icol * n + l]; |
||||
X[icol * n + l] = temp; |
||||
} |
||||
for (l = 0; l < m; l++) { |
||||
temp = b[irow * n + l]; |
||||
b[irow * n + l] = b[icol * n + l]; |
||||
b[icol * n + l] = temp; |
||||
} |
||||
} |
||||
indxr[i] = irow; |
||||
indxc[i] = icol; |
||||
|
||||
if (X[icol * n + icol] == 0) return false; // Singular
|
||||
|
||||
pivinv = 1 / X[icol * n + icol]; |
||||
X[icol * n + icol] = 1; |
||||
for (l = 0; l < n; l++) X[icol * n + l] *= pivinv; |
||||
for (l = 0; l < m; l++) b[icol * n + l] *= pivinv; |
||||
|
||||
for (ll = 0; ll < n; ll++) { |
||||
if (ll != icol) { |
||||
dum = X[ll * n + icol]; |
||||
X[ll * n + icol] = 0; |
||||
for (l = 0; l < n; l++) X[ll * n + l] -= X[icol * n + l] * dum; |
||||
for (l = 0; l < m; l++) b[ll * n + l] -= b[icol * n + l] * dum; |
||||
} |
||||
} |
||||
} |
||||
for (l = (n - 1); l >= 0; l--) |
||||
if (indxr[l] != indxc[l]) { |
||||
for (k = 0; k < n; k++) { |
||||
temp = X[k * n + indxr[l]]; |
||||
X[k * n + indxr[l]] = X[k * n + indxc[l]]; |
||||
X[k * n + indxc[l]] = temp; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
// Variogram models
|
||||
var kriging_variogram_gaussian = function (h, nugget, range, sill, A) { |
||||
return nugget + ((sill - nugget) / range) * |
||||
(1.0 - Math.exp(-(1.0 / A) * Math.pow(h / range, 2))); |
||||
}; |
||||
var kriging_variogram_exponential = function (h, nugget, range, sill, A) { |
||||
return nugget + ((sill - nugget) / range) * |
||||
(1.0 - Math.exp(-(1.0 / A) * (h / range))); |
||||
}; |
||||
var kriging_variogram_spherical = function (h, nugget, range, sill, A) { |
||||
if (h > range) return nugget + (sill - nugget) / range; |
||||
return nugget + ((sill - nugget) / range) * |
||||
(1.5 * (h / range) - 0.5 * Math.pow(h / range, 3)); |
||||
}; |
||||
|
||||
// Train using gaussian processes with bayesian priors
|
||||
kriging.train = function (t, x, y, model, sigma2, alpha) { |
||||
var variogram = { |
||||
t: t, |
||||
x: x, |
||||
y: y, |
||||
nugget: 0.0, |
||||
range: 0.0, |
||||
sill: 0.0, |
||||
A: 1 / 3, |
||||
n: 0 |
||||
}; |
||||
switch (model) { |
||||
case "gaussian": |
||||
variogram.model = kriging_variogram_gaussian; |
||||
break; |
||||
case "exponential": |
||||
variogram.model = kriging_variogram_exponential; |
||||
break; |
||||
case "spherical": |
||||
variogram.model = kriging_variogram_spherical; |
||||
break; |
||||
}; |
||||
|
||||
// Lag distance/semivariance
|
||||
var i, j, k, l, n = t.length; |
||||
var distance = Array((n * n - n) / 2); |
||||
for (i = 0, k = 0; i < n; i++) |
||||
for (j = 0; j < i; j++, k++) { |
||||
distance[k] = Array(2); |
||||
distance[k][0] = Math.pow( |
||||
Math.pow(x[i] - x[j], 2) + |
||||
Math.pow(y[i] - y[j], 2), 0.5); |
||||
distance[k][1] = Math.abs(t[i] - t[j]); |
||||
} |
||||
distance.sort(function (a, b) { return a[0] - b[0]; }); |
||||
variogram.range = distance[(n * n - n) / 2 - 1][0]; |
||||
|
||||
// Bin lag distance
|
||||
var lags = ((n * n - n) / 2) > 30 ? 30 : (n * n - n) / 2; |
||||
var tolerance = variogram.range / lags; |
||||
var lag = createArrayWithValues(0, lags); |
||||
var semi = createArrayWithValues(0, lags); |
||||
if (lags < 30) { |
||||
for (l = 0; l < lags; l++) { |
||||
lag[l] = distance[l][0]; |
||||
semi[l] = distance[l][1]; |
||||
} |
||||
} |
||||
else { |
||||
for (i = 0, j = 0, k = 0, l = 0; i < lags && j < ((n * n - n) / 2); i++, k = 0) { |
||||
while (distance[j][0] <= ((i + 1) * tolerance)) { |
||||
lag[l] += distance[j][0]; |
||||
semi[l] += distance[j][1]; |
||||
j++; k++; |
||||
if (j >= ((n * n - n) / 2)) break; |
||||
} |
||||
if (k > 0) { |
||||
lag[l] /= k; |
||||
semi[l] /= k; |
||||
l++; |
||||
} |
||||
} |
||||
if (l < 2) return variogram; // Error: Not enough points
|
||||
} |
||||
|
||||
// Feature transformation
|
||||
n = l; |
||||
variogram.range = lag[n - 1] - lag[0]; |
||||
var X = createArrayWithValues(1, 2 * n); |
||||
var Y = Array(n); |
||||
var A = variogram.A; |
||||
for (i = 0; i < n; i++) { |
||||
switch (model) { |
||||
case "gaussian": |
||||
X[i * 2 + 1] = 1.0 - Math.exp(-(1.0 / A) * Math.pow(lag[i] / variogram.range, 2)); |
||||
break; |
||||
case "exponential": |
||||
X[i * 2 + 1] = 1.0 - Math.exp(-(1.0 / A) * lag[i] / variogram.range); |
||||
break; |
||||
case "spherical": |
||||
X[i * 2 + 1] = 1.5 * (lag[i] / variogram.range) - |
||||
0.5 * Math.pow(lag[i] / variogram.range, 3); |
||||
break; |
||||
}; |
||||
Y[i] = semi[i]; |
||||
} |
||||
|
||||
// Least squares
|
||||
var Xt = kriging_matrix_transpose(X, n, 2); |
||||
var Z = kriging_matrix_multiply(Xt, X, 2, n, 2); |
||||
Z = kriging_matrix_add(Z, kriging_matrix_diag(1 / alpha, 2), 2, 2); |
||||
var cloneZ = Z.slice(0); |
||||
if (kriging_matrix_chol(Z, 2)) |
||||
kriging_matrix_chol2inv(Z, 2); |
||||
else { |
||||
kriging_matrix_solve(cloneZ, 2); |
||||
Z = cloneZ; |
||||
} |
||||
var W = kriging_matrix_multiply(kriging_matrix_multiply(Z, Xt, 2, 2, n), Y, 2, n, 1); |
||||
|
||||
// Variogram parameters
|
||||
variogram.nugget = W[0]; |
||||
variogram.sill = W[1] * variogram.range + variogram.nugget; |
||||
variogram.n = x.length; |
||||
|
||||
// Gram matrix with prior
|
||||
n = x.length; |
||||
var K = Array(n * n); |
||||
for (i = 0; i < n; i++) { |
||||
for (j = 0; j < i; j++) { |
||||
K[i * n + j] = variogram.model(Math.pow(Math.pow(x[i] - x[j], 2) + |
||||
Math.pow(y[i] - y[j], 2), 0.5), |
||||
variogram.nugget, |
||||
variogram.range, |
||||
variogram.sill, |
||||
variogram.A); |
||||
K[j * n + i] = K[i * n + j]; |
||||
} |
||||
K[i * n + i] = variogram.model(0, variogram.nugget, |
||||
variogram.range, |
||||
variogram.sill, |
||||
variogram.A); |
||||
} |
||||
|
||||
// Inverse penalized Gram matrix projected to target vector
|
||||
var C = kriging_matrix_add(K, kriging_matrix_diag(sigma2, n), n, n); |
||||
var cloneC = C.slice(0); |
||||
if (kriging_matrix_chol(C, n)) |
||||
kriging_matrix_chol2inv(C, n); |
||||
else { |
||||
kriging_matrix_solve(cloneC, n); |
||||
C = cloneC; |
||||
} |
||||
|
||||
// Copy unprojected inverted matrix as K
|
||||
var K = C.slice(0); |
||||
var M = kriging_matrix_multiply(C, t, n, n, 1); |
||||
variogram.K = K; |
||||
variogram.M = M; |
||||
|
||||
return variogram; |
||||
}; |
||||
|
||||
// Model prediction
|
||||
kriging.predict = function (x, y, variogram) { |
||||
var i, k = Array(variogram.n); |
||||
for (i = 0; i < variogram.n; i++) |
||||
k[i] = variogram.model(Math.pow(Math.pow(x - variogram.x[i], 2) + |
||||
Math.pow(y - variogram.y[i], 2), 0.5), |
||||
variogram.nugget, variogram.range, |
||||
variogram.sill, variogram.A); |
||||
return kriging_matrix_multiply(k, variogram.M, 1, variogram.n, 1)[0]; |
||||
}; |
||||
kriging.variance = function (x, y, variogram) { |
||||
var i, k = Array(variogram.n); |
||||
for (i = 0; i < variogram.n; i++) |
||||
k[i] = variogram.model(Math.pow(Math.pow(x - variogram.x[i], 2) + |
||||
Math.pow(y - variogram.y[i], 2), 0.5), |
||||
variogram.nugget, variogram.range, |
||||
variogram.sill, variogram.A); |
||||
return variogram.model(0, variogram.nugget, variogram.range, |
||||
variogram.sill, variogram.A) + |
||||
kriging_matrix_multiply(kriging_matrix_multiply(k, variogram.K, |
||||
1, variogram.n, variogram.n), |
||||
k, 1, variogram.n, 1)[0]; |
||||
}; |
||||
|
||||
// Gridded matrices or contour paths
|
||||
kriging.grid = function (polygons, variogram, width) { |
||||
var i, j, k, n = polygons.length; |
||||
if (n == 0) return; |
||||
|
||||
// Boundaries of polygons space
|
||||
var xlim = [polygons[0][0][0], polygons[0][0][0]]; |
||||
var ylim = [polygons[0][0][1], polygons[0][0][1]]; |
||||
for (i = 0; i < n; i++) // Polygons
|
||||
for (j = 0; j < polygons[i].length; j++) { // Vertices
|
||||
if (polygons[i][j][0] < xlim[0]) |
||||
xlim[0] = polygons[i][j][0]; |
||||
if (polygons[i][j][0] > xlim[1]) |
||||
xlim[1] = polygons[i][j][0]; |
||||
if (polygons[i][j][1] < ylim[0]) |
||||
ylim[0] = polygons[i][j][1]; |
||||
if (polygons[i][j][1] > ylim[1]) |
||||
ylim[1] = polygons[i][j][1]; |
||||
} |
||||
|
||||
// Alloc for O(n^2) space
|
||||
var xtarget, ytarget; |
||||
var a = Array(2), b = Array(2); |
||||
var lxlim = Array(2); // Local dimensions
|
||||
var lylim = Array(2); // Local dimensions
|
||||
var x = Math.ceil((xlim[1] - xlim[0]) / width); |
||||
var y = Math.ceil((ylim[1] - ylim[0]) / width); |
||||
|
||||
var A = Array(x + 1); |
||||
for (i = 0; i <= x; i++) A[i] = Array(y + 1); |
||||
for (i = 0; i < n; i++) { |
||||
// Range for polygons[i]
|
||||
lxlim[0] = polygons[i][0][0]; |
||||
lxlim[1] = lxlim[0]; |
||||
lylim[0] = polygons[i][0][1]; |
||||
lylim[1] = lylim[0]; |
||||
for (j = 1; j < polygons[i].length; j++) { // Vertices
|
||||
if (polygons[i][j][0] < lxlim[0]) |
||||
lxlim[0] = polygons[i][j][0]; |
||||
if (polygons[i][j][0] > lxlim[1]) |
||||
lxlim[1] = polygons[i][j][0]; |
||||
if (polygons[i][j][1] < lylim[0]) |
||||
lylim[0] = polygons[i][j][1]; |
||||
if (polygons[i][j][1] > lylim[1]) |
||||
lylim[1] = polygons[i][j][1]; |
||||
} |
||||
|
||||
// Loop through polygon subspace
|
||||
a[0] = Math.floor(((lxlim[0] - ((lxlim[0] - xlim[0]) % width)) - xlim[0]) / width); |
||||
a[1] = Math.ceil(((lxlim[1] - ((lxlim[1] - xlim[1]) % width)) - xlim[0]) / width); |
||||
b[0] = Math.floor(((lylim[0] - ((lylim[0] - ylim[0]) % width)) - ylim[0]) / width); |
||||
b[1] = Math.ceil(((lylim[1] - ((lylim[1] - ylim[1]) % width)) - ylim[0]) / width); |
||||
for (j = a[0]; j <= a[1]; j++) |
||||
for (k = b[0]; k <= b[1]; k++) { |
||||
xtarget = xlim[0] + j * width; |
||||
ytarget = ylim[0] + k * width; |
||||
if (polygons[i].pip(xtarget, ytarget)) |
||||
A[j][k] = kriging.predict(xtarget, |
||||
ytarget, |
||||
variogram); |
||||
} |
||||
} |
||||
A.xlim = xlim; |
||||
A.ylim = ylim; |
||||
A.zlim = [variogram.t.min(), variogram.t.max()]; |
||||
A.width = width; |
||||
return A; |
||||
}; |
||||
kriging.contour = function (value, polygons, variogram) { |
||||
|
||||
}; |
||||
|
||||
// Plotting on the DOM
|
||||
kriging.plot = function (canvas, grid, xlim, ylim, colors) { |
||||
// Clear screen
|
||||
var ctx = canvas.getContext("2d"); |
||||
ctx.clearRect(0, 0, canvas.width, canvas.height); |
||||
|
||||
// Starting boundaries
|
||||
var range = [xlim[1] - xlim[0], ylim[1] - ylim[0], grid.zlim[1] - grid.zlim[0]]; |
||||
var i, j, x, y, z; |
||||
var n = grid.length; |
||||
var m = grid[0].length; |
||||
var wx = Math.ceil(grid.width * canvas.width / (xlim[1] - xlim[0])); |
||||
var wy = Math.ceil(grid.width * canvas.height / (ylim[1] - ylim[0])); |
||||
for (i = 0; i < n; i++) |
||||
for (j = 0; j < m; j++) { |
||||
if (grid[i][j] == undefined) continue; |
||||
x = canvas.width * (i * grid.width + grid.xlim[0] - xlim[0]) / range[0]; |
||||
y = canvas.height * (1 - (j * grid.width + grid.ylim[0] - ylim[0]) / range[1]); |
||||
z = (grid[i][j] - grid.zlim[0]) / range[2]; |
||||
if (z < 0.0) z = 0.0; |
||||
if (z > 1.0) z = 1.0; |
||||
|
||||
ctx.fillStyle = colors[Math.floor((colors.length - 1) * z)]; |
||||
ctx.fillRect(Math.round(x - wx / 2), Math.round(y - wy / 2), wx, wy); |
||||
} |
||||
|
||||
}; |
||||
|
||||
|
||||
return kriging; |
||||
}(); |
||||
|
||||
// 修改为支持两种模块系统的写法
|
||||
if (typeof module !== 'undefined' && module.exports) { |
||||
module.exports = kriging; |
||||
} else if (typeof define === 'function' && define.amd) { |
||||
define(function () { return kriging; }); |
||||
} |
||||
|
||||
// 添加 ES6 默认导出
|
||||
export default kriging; |
||||
@ -0,0 +1,321 @@
@@ -0,0 +1,321 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="测站名称" prop="stnmId"> |
||||
<ESelectSingle ref="eSelectSingle" :stationType="stationType" @stationChange="handleStationChange" @loadingChange="handleStationLoading" /> |
||||
</el-form-item> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker v-model="queryParams.startTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" placeholder="选择开始时间" :disabled-date="disabledStartDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker v-model="queryParams.endTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择结束时间" :disabled-date="disabledEndDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
</el-form-item> |
||||
<el-form-item class="classification"> |
||||
<div style="margin: -6px 0 0 0">设备故障: <span class="red">{{gzCount}}</span></div> |
||||
<div style="margin: -5px 0 0 0">数据异常: <span class="red">{{ycCount}}</span></div> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
<splitpanes horizontal class="el-card-p card-shadow carder-border mt10 pad10 default-theme container-box" :push-other-panes="false"> |
||||
<pane size="70" ref="firstPane" class="mr10"> |
||||
<splitpanes :horizontal="device === 'mobile'" class=" default-theme" :push-other-panes="false"> |
||||
<pane :size="100 - firstSize" class="mr10"> |
||||
<div v-table-height='{bottom:0}' style="width:100%;"> |
||||
<TimeBarChart v-loading="echartsLoading" :legendData='legendData' :xAxisData="xAxisData" :seriesData="seriesData" :textTitle="textTitle" :unit="unit" :echartType="echartType" /> |
||||
</div> |
||||
</pane> |
||||
<pane :size="firstSize" :min-size="SPLITPANES_CONFIG.MIN_SIZE" :max-size="SPLITPANES_CONFIG.MAX_SIZE" ref="firstPane"> |
||||
<div style="display:flex;align-items: center;" class="mb20"> |
||||
<div class="ml10">主设备:<span>{{zsbStcd}}</span></div> |
||||
</div> |
||||
<el-table min-height="500" v-loading="rightLoading" :data="tableData1" border style="height:88%;overflow: auto;"> |
||||
<el-table-column prop="tm" label="时间" width="180" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column prop="value" label="数值" :align="alignment"></el-table-column> |
||||
</el-table> |
||||
</pane> |
||||
</splitpanes> |
||||
</pane> |
||||
<pane size="30"> |
||||
<el-table v-table-height v-loading="loading" :data="alarmList" border> |
||||
<el-table-column label="测站类型" :align="alignment" prop="type" /> |
||||
<el-table-column label="预警类型" :align="alignment" prop="alarmType" /> |
||||
<el-table-column label="预警级别" :align="alignment" prop="alarmLevel" /> |
||||
<el-table-column label="预警内容" :align="alignment" prop="alarmContent" width="600" /> |
||||
<el-table-column label="预警时间" :align="alignment" prop="alarmTime" /> |
||||
<el-table-column label="预警时长(时)" :align="alignment" prop="alarmTotalLength" /> |
||||
<el-table-column label="预警状态" :align="alignment" prop="flag"> |
||||
<template #default="scope"> |
||||
<span v-if="scope.row.flag == 0 " class="red">预警中</span> |
||||
<span v-if="scope.row.flag == 1 " class="green">预警结束</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="是否处理" :align="alignment" prop="isDeal"> |
||||
<template #default="scope"> |
||||
<span v-if="scope.row.isDeal == 'n' " class="red">否</span> |
||||
<span v-if="scope.row.isDeal == 'y' " class="green">是</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
||||
</pane> |
||||
</splitpanes> |
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import { ref, reactive, watch, toRaw, computed, onMounted } from 'vue' |
||||
import dayjs from 'dayjs'; |
||||
import ESelectSingle from '@/components/ESelectSingle/index.vue' |
||||
import TimeBarChart from '@/components/ChartsTimeBar/index.vue' |
||||
|
||||
import { |
||||
Splitpanes, |
||||
Pane |
||||
} from 'splitpanes' |
||||
import 'splitpanes/dist/splitpanes.css' |
||||
import useAppStore from '@/store/modules/app' |
||||
const device = computed(() => useAppStore().device); |
||||
|
||||
|
||||
const props = defineProps({ |
||||
stationType: { |
||||
type: String, |
||||
default: 'A' |
||||
}, |
||||
requestSuffix: { |
||||
type: String, |
||||
default: '/historydata' |
||||
}, |
||||
fixed: { |
||||
type: Number, |
||||
default: 1 |
||||
} |
||||
|
||||
}) |
||||
|
||||
const { |
||||
proxy |
||||
} = getCurrentInstance() |
||||
const requestPrefix = '/history/data' |
||||
const alignment = 'center' |
||||
|
||||
const textTitle = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'A': |
||||
return '雨量过程线'; |
||||
case 'B': |
||||
return '水位过程线'; |
||||
case 'C': |
||||
return '水位过程线'; |
||||
case 'D': |
||||
return '潮位过程线'; |
||||
case 'E': |
||||
return '流量过程线'; |
||||
} |
||||
}); |
||||
const unit = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'A': |
||||
return 'mm'; |
||||
case 'B': |
||||
return 'm'; |
||||
case 'C': |
||||
return 'm'; |
||||
case 'D': |
||||
return 'm'; |
||||
case 'E': |
||||
return 'm³/s'; |
||||
} |
||||
}); |
||||
const echartType = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'A': |
||||
return 'bar'; |
||||
case 'B': |
||||
return 'line'; |
||||
case 'C': |
||||
return 'line'; |
||||
case 'D': |
||||
return 'line'; |
||||
case 'E': |
||||
return 'line'; |
||||
} |
||||
}); |
||||
const firstSize = ref(proxy.SPLITPANES_CONFIG.DEFAULT_SIZE) |
||||
|
||||
const eSelectSingle = ref(null) |
||||
|
||||
const handleStationLoading = (loadingState) => { |
||||
loading.value = loadingState; |
||||
} |
||||
// 新增处理站点变化的函数 |
||||
const handleStationChange = async (stnmId) => { |
||||
queryParams.stnmId = stnmId |
||||
if (stnmId == undefined) { |
||||
proxy.$modal.msgWarning("请选择站点后查询"); |
||||
return |
||||
} else { |
||||
try { |
||||
await Promise.all([ |
||||
getList(), |
||||
drawTable1(), |
||||
getEchartsData() |
||||
]); |
||||
} catch (error) { |
||||
console.error('请求执行出错:', error); |
||||
} |
||||
} |
||||
} |
||||
|
||||
const loading = ref(false); |
||||
const tableData = ref([]); |
||||
|
||||
const queryParams = reactive({ |
||||
stnmId: "", |
||||
startTime: dayjs().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), |
||||
endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), |
||||
pageNum: 1, |
||||
pageSize: 10, |
||||
stationType: props.stationType |
||||
|
||||
}) |
||||
const gzCount = ref(0) |
||||
const ycCount = ref(0) |
||||
const total = ref(0) |
||||
const alarmList = ref([]) |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
try { |
||||
const res = await proxy.axiosGet('/alarm/alarm/queryByStnmIdAndTm', queryParams) |
||||
if (res.code == 0) { |
||||
let data = res.data |
||||
total.value = res.count |
||||
gzCount.value = res.gzCount |
||||
ycCount.value = res.ycCount |
||||
for (var i = 0; i < data.length; i++) { |
||||
data[i].value = data[i].value.toFixed(proxy.fixed) |
||||
} |
||||
alarmList.value = data |
||||
} |
||||
} catch (error) { |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
}; |
||||
const tableData1 = ref([]); |
||||
const rightLoading = ref(false); |
||||
// 修改 drawTable1 函数,保存原始数据 |
||||
const drawTable1 = async () => { |
||||
let params = getParams(); |
||||
rightLoading.value = true; |
||||
try { |
||||
let url = requestPrefix + '/originaldata'; |
||||
let res = await proxy.axiosPost2(url, params); |
||||
if (res.code === 0) { |
||||
let data = res.data; |
||||
tableData1.value = data; |
||||
// 保存原始数据副本 |
||||
originalTableData1.value = JSON.parse(JSON.stringify(data)); |
||||
isDataModified.value = false; // 重置修改状态 |
||||
} |
||||
} catch (error) { |
||||
console.error(error); |
||||
} finally { |
||||
rightLoading.value = false; |
||||
} |
||||
}; |
||||
// 获取echarts数据 |
||||
const zsbStcd = ref('') |
||||
const legendData = ref([]) |
||||
const xAxisData = ref([]) |
||||
const seriesData = ref([]) |
||||
const echartsLoading = ref(false) |
||||
const getEchartsData = async () => { |
||||
let params = getParams() |
||||
echartsLoading.value = true |
||||
let url = requestPrefix + props.requestSuffix |
||||
try { |
||||
let res = await proxy.axiosPost2(url, params); |
||||
if (res.code === 0) { |
||||
zsbStcd.value = res.data.zstcd |
||||
legendData.value = res.data.legend |
||||
// 提取每个series中data的第一个元素并格式化时间 |
||||
if (res.data.series && res.data.series.length > 0) { |
||||
// 假设第一个series的data包含完整的时间点 |
||||
xAxisData.value = res.data.series[0].data.map(item => { |
||||
// 如果item是对象且包含时间字段 |
||||
if (typeof item === 'object' && item !== null) { |
||||
// 假设时间字段可能是tm, time, or the first element |
||||
const timeValue = item.tm || item.time || item[0]; |
||||
return dayjs(timeValue).format('YYYY-MM-DD HH:mm'); |
||||
} else { |
||||
// 如果item直接就是时间值 |
||||
return dayjs(item).format('YYYY-MM-DD HH:mm'); |
||||
} |
||||
}); |
||||
} |
||||
seriesData.value = res.data.series |
||||
console.log(res, '======获取echarts数据', res.data, xAxisData) |
||||
} |
||||
} catch (error) { |
||||
|
||||
} finally { |
||||
echartsLoading.value = false |
||||
} |
||||
}; |
||||
// 查询按钮 |
||||
const handleQuery = async () => { |
||||
try { |
||||
await Promise.all([ |
||||
getList(), |
||||
drawTable1(), |
||||
getEchartsData() |
||||
]); |
||||
} catch (error) { |
||||
console.error('请求执行出错:', error); |
||||
} |
||||
} |
||||
|
||||
|
||||
onMounted(() => { |
||||
|
||||
}) |
||||
const getParams = () => { |
||||
let params = { |
||||
stnmId: queryParams.stnmId, |
||||
startTime: queryParams.startTime, |
||||
endTime: queryParams.endTime, |
||||
stationType: props.stationType |
||||
} |
||||
return params |
||||
} |
||||
|
||||
// 禁用开始时间选择器中大于当前时间和结束时间的日期 |
||||
const disabledStartDate = (time) => { |
||||
const endTime = queryParams.endTime ? dayjs(queryParams.endTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(endTime && dayjs(time).isAfter(endTime)); |
||||
}; |
||||
|
||||
// 禁用结束时间选择器中大于当前时间和小于开始时间的日期 |
||||
const disabledEndDate = (time) => { |
||||
const startTime = queryParams.startTime ? dayjs(queryParams.startTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(startTime && dayjs(time).isBefore(startTime)); |
||||
}; |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
.classification :deep(.el-form-item__content) { |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.splitpanes__splitter { |
||||
margin-bottom: 20px |
||||
} |
||||
</style> |
||||
@ -0,0 +1,345 @@
@@ -0,0 +1,345 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="选择站点"> |
||||
<el-tree-select filterable :props="{ value: 'stnmId', label: 'name' }" v-model="queryParams.stnmId" style="width: 240px" :data="treeSelectOptions" node-key="id" /> |
||||
</el-form-item> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker :clearable="false" v-model="queryParams.startTime" type="datetime" value-format="MM-DD HH:mm" format="YYYY-MM-DD HH:mm:ss" placeholder="选择开始时间" :disabled-date="disabledStartDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker :clearable="false" v-model="queryParams.endTime" type="datetime" value-format="MM-DD HH:mm" format="YYYY-MM-DD HH:mm:ss" placeholder="选择结束时间" :disabled-date="disabledEndDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<br /> |
||||
<el-form-item label="年份区间"> |
||||
<el-date-picker :clearable="false" class="picker-year" style="width:180px" v-model="yearstart" type="year" value-format="YYYY" placeholder="选择开始年" @change="changeYearStart"> |
||||
</el-date-picker> |
||||
<span class="pr10 pl10"> -</span> |
||||
<el-date-picker :clearable="false" class="picker-year" style="width:180px" v-model="yearend" type="year" value-format="YYYY" placeholder="选择结束年" @change="changeYearEnd"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
<!-- <el-button type="warning" icon="Download" @click="handleExport">下载</el-button> --> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
|
||||
<div class="el-card-p card-shadow carder-border mt10 pad10" style="max-width: 100%; overflow-x: hidden;padding-top:0" v-loading="loading"> |
||||
<div class="main-table-header sticky-header"> |
||||
<div class="table-title"> |
||||
<span class="pr10" v-if="stnm!==''">{{stnm}}</span> |
||||
<span v-else>{{tableTitle}}</span> |
||||
</div> |
||||
<div class="table-time mb5"> |
||||
<div> |
||||
<span>年份: </span><span id="title1">{{queryParams.years }}</span> |
||||
</div> |
||||
<div> |
||||
<span>单位: </span><span id="title2">{{stationType=='E'?'m³/s':'m'}}</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table v-table-height border :data="tableData" :span-method="arraySpanMethod" style="width: 100%;"> |
||||
<el-table-column prop="year" label="年份" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType == 'D'" prop="nvalue" label="当前潮位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType != 'D' && stationType != 'E'" prop="nvalue" label="当前水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType == 'E'" prop="nvalue" label="当前流量" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType == 'D'" prop="value" label="平均潮位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType != 'D' && stationType != 'E'" prop="value" label="平均水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="stationType == 'E'" prop="value" label="平均流量" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="最高潮位" :align="alignment" v-if="stationType == 'D'"> |
||||
<el-table-column prop="maxvalue" label="潮位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.maxtm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最高水位" :align="alignment" v-if="stationType != 'D' && stationType != 'E'"> |
||||
<el-table-column prop="maxvalue" label="水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.maxtm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最高流量" :align="alignment" v-if="stationType == 'E'"> |
||||
<el-table-column prop="maxvalue" label="流量" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.maxtm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最低潮位" :align="alignment" v-if="stationType == 'D'"> |
||||
<el-table-column prop="minvalue" label="潮位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.mintm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最低水位" :align="alignment" v-if="stationType != 'D' && stationType != 'E'"> |
||||
<el-table-column prop="minvalue" label="水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.mintm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最低流量" :align="alignment" v-if="stationType == 'E'"> |
||||
<el-table-column prop="minvalue" label="流量" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180"> |
||||
<template #default="scope"> |
||||
<span>{{ parseTime(scope.row.mintm) }}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
|
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import dayjs from 'dayjs'; |
||||
import singleStation from '@/components/SingleStation/index.vue' |
||||
import { ref, reactive, onMounted } from 'vue'; |
||||
|
||||
const props = defineProps({ |
||||
tableTitle: { |
||||
type: String, |
||||
default: '表格标题' |
||||
}, |
||||
stationType: { |
||||
type: String, |
||||
default: 'A' |
||||
}, |
||||
requestPrefix: { |
||||
type: String, |
||||
default: "" |
||||
} |
||||
}) |
||||
|
||||
const { proxy } = getCurrentInstance() |
||||
const alignment = 'center' |
||||
const type = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'A': |
||||
return 'rain'; |
||||
case 'B': |
||||
return 'river'; |
||||
case 'C': |
||||
return 'rsvr'; |
||||
case 'D': |
||||
return 'tide'; |
||||
case 'E': |
||||
return 'q_qflow'; |
||||
} |
||||
}); |
||||
const tablename = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'D': |
||||
return '潮位过程表'; |
||||
case 'E': |
||||
return '流量过程表'; |
||||
default: |
||||
return '水位过程表'; |
||||
} |
||||
}); |
||||
const loading = ref(false); |
||||
const tableData = ref([]); |
||||
const yearstart = ref(dayjs().subtract(1, 'year').format('YYYY')) |
||||
const yearend = ref(dayjs().format('YYYY')) |
||||
const queryParams = reactive({ |
||||
startTime: dayjs().subtract(30, 'day').format('MM-DD 08:00'), |
||||
endTime: dayjs().format('MM-DD 08:00'), |
||||
years: `${yearstart.value}-${yearend.value}`, |
||||
stnmIds: '', |
||||
type: type.value |
||||
}); |
||||
|
||||
let total = ref(0) |
||||
let dataCount = ref(0) |
||||
const stnm = ref('') |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
let url = `/report/${props.requestPrefix}` |
||||
try { |
||||
const res = await proxy.axiosGet(url, queryParams) |
||||
if (res.code == 0) { |
||||
let data = res.data.list |
||||
let { avg, max, min, list } = res.data |
||||
tableData.value = data; |
||||
if (data && data.length > 0) { |
||||
stnm.value = `${data[0].stnm}${queryParams.startTime} ~ ${queryParams.endTime}${tablename.value}` |
||||
} |
||||
console.log(avg[0], avg[1], avg[2], avg[3]) |
||||
tableData.value.push({ |
||||
year: "平均", |
||||
nvalue: (avg[0] == 0 ? "" : avg[0]), |
||||
value: (avg[1] == 0 ? "" : avg[1]), |
||||
maxvalue: (avg[2] == 0 ? "" : avg[2]), |
||||
minvalue: (avg[3] == 0 ? "" : avg[3]), |
||||
}); |
||||
tableData.value.push({ |
||||
year: "最高", |
||||
nvalue: (typeof (max[0].nvalue) == "undefined" ? "" : max[0].nvalue), |
||||
value: (typeof (max[1].value) == "undefined" ? "" : max[1].value), |
||||
maxvalue: (typeof (max[3].maxvalue) == "undefined" ? "" : max[3].maxvalue), |
||||
minvalue: (typeof (max[4].minvalue) == "undefined" ? "" : max[4].minvalue), |
||||
}); |
||||
tableData.value.push({ |
||||
year: "时间", |
||||
nvalue: (typeof (max[0].year) == "undefined" ? "" : max[0].year), |
||||
value: (typeof (max[1].year) == "undefined" ? "" : max[1].year), |
||||
maxvalue: (proxy.parseTime(typeof (max[3].maxtm)) == "undefined" ? "" : proxy.parseTime(max[3].maxtm)), |
||||
minvalue: (proxy.parseTime(typeof (max[4].mintm)) == "undefined" ? "" : proxy.parseTime(max[4].mintm)), |
||||
}); |
||||
tableData.value.push({ |
||||
year: "最低", |
||||
nvalue: (typeof (min[0].nvalue) == "undefined" ? "" : min[0].nvalue), |
||||
value: (typeof (min[1].value) == "undefined" ? "" : min[1].value), |
||||
maxvalue: (typeof (min[2].maxvalue) == "undefined" ? "" : min[2].maxvalue), |
||||
minvalue: (typeof (min[3].minvalue) == "undefined" ? "" : min[3].minvalue), |
||||
}); |
||||
tableData.value.push({ |
||||
year: "时间", |
||||
nvalue: (typeof (min[0].year) == "undefined" ? "" : min[0].year), |
||||
value: (typeof (min[1].year) == "undefined" ? "" : min[1].year), |
||||
maxvalue: (proxy.parseTime(typeof (min[2].maxtm)) == "undefined" ? "" : proxy.parseTime(min[2].maxtm)), |
||||
minvalue: (proxy.parseTime(typeof (min[3].mintm)) == "undefined" ? "" : proxy.parseTime(min[3].mintm)), |
||||
}); |
||||
dataCount.value = tableData.value.length; |
||||
} |
||||
} catch (error) { |
||||
console.error(error) |
||||
} finally { |
||||
// 确保在请求完成后隐藏loading |
||||
loading.value = false |
||||
} |
||||
} |
||||
const changeYearStart = (val) => { |
||||
yearstart.value = val |
||||
queryParams.years = `${yearstart.value}-${yearend.value}` |
||||
getList() |
||||
} |
||||
const changeYearEnd = (val) => { |
||||
yearend.value = val |
||||
queryParams.years = `${yearstart.value}-${yearend.value}` |
||||
getList() |
||||
} |
||||
|
||||
// 优化后的获取上一行月份的方法 |
||||
const getPrevRow = (scope, field, type) => { |
||||
const rowIndex = scope.$index; |
||||
const data = scope.store.states.data; |
||||
|
||||
// 如果是第一行,返回null |
||||
if (rowIndex === 0) return null; |
||||
|
||||
// 找到上一个非空行的月份 |
||||
let prevRowIndex = rowIndex - 1; |
||||
while (prevRowIndex >= 0 && (!data.value[prevRowIndex][field] || data.value[prevRowIndex][field] === '')) { |
||||
prevRowIndex--; |
||||
} |
||||
if (type == '1') { |
||||
field = 'month' |
||||
} |
||||
let result = prevRowIndex >= 0 ? data.value[prevRowIndex][field] : null; |
||||
// 如果找到有效的上一行数据,返回其月份;否则返回null |
||||
return result |
||||
}; |
||||
|
||||
const treeSelectOptions = ref([]) |
||||
const getTreeStation = async () => { |
||||
loading.value = true; |
||||
try { |
||||
let res = await proxy.axiosGet('/basic/stype/getTreeStation2/' + proxy.stationType); |
||||
if (res.code == 0) { |
||||
treeSelectOptions.value = res.data |
||||
// 设置默认值为第一个叶子节点的stnmId |
||||
if (treeSelectOptions.value.length > 0) { |
||||
const firstLeafNode = findFirstLeafNode(treeSelectOptions.value); |
||||
if (firstLeafNode) { |
||||
queryParams.stnmId = firstLeafNode.stnmId; |
||||
nextTick(() => { |
||||
getList() |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
} catch (error) { |
||||
|
||||
} |
||||
} |
||||
// 查找树结构中的第一个叶子节点 |
||||
const findFirstLeafNode = (nodes) => { |
||||
for (let node of nodes) { |
||||
// 如果节点有子节点,则递归查找 |
||||
if (node.children && node.children.length > 0) { |
||||
const leaf = findFirstLeafNode(node.children); |
||||
if (leaf) { |
||||
return leaf; |
||||
} |
||||
} |
||||
// 如果节点没有子节点,则为叶子节点 |
||||
else if (node.stnmId) { |
||||
return node; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
// 搜索按钮操作 |
||||
const handleQuery = () => { |
||||
getList() |
||||
|
||||
} |
||||
// 下载按钮操作 |
||||
const handleExport = () => { } |
||||
onMounted(() => { |
||||
getTreeStation() |
||||
}) |
||||
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => { |
||||
if (dataCount.value > 4) { |
||||
if (rowIndex > dataCount.value - 6) { |
||||
if (columnIndex === 3 || columnIndex === 5) { |
||||
return [1, 2]; |
||||
} else if (columnIndex === 4 || columnIndex === 6) { |
||||
return [0, 0]; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
.no-border-table :deep(.el-table__body-wrapper .el-table__cell) { |
||||
border-bottom: 0 !important; |
||||
} |
||||
|
||||
.no-border-table :deep(.el-table__body-wrapper .el-table__cell) { |
||||
padding: 2px 0 !important; |
||||
} |
||||
|
||||
.no-border-table :deep(.el-table__body-wrapper .el-table__row:nth-child(6n) .el-table__cell) { |
||||
padding: 10px 0 !important; |
||||
background-color: #f9f9f9; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,173 @@
@@ -0,0 +1,173 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker v-model="queryParams.startTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" placeholder="选择开始时间" :disabled-date="disabledStartDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker v-model="queryParams.endTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" placeholder="选择结束时间" :disabled-date="disabledEndDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
<splitpanes :horizontal="device === 'mobile'" class="el-card-p card-shadow carder-border mt10 pad10 default-theme container-box" :push-other-panes="false"> |
||||
<pane :size="firstSize" :min-size="SPLITPANES_CONFIG.MIN_SIZE" :max-size="SPLITPANES_CONFIG.MAX_SIZE" ref="firstPane" class="mr10"> |
||||
<e-tree ref="eTreeRef" :stationType="stationType" @stationChange="handleStationChange" @loadingChange="handleStationLoading"></e-tree> |
||||
</pane> |
||||
<pane :size="100 - firstSize" style="height: 100%;"> |
||||
<div class="main-table-header"> |
||||
<div class="table-title">{{tableTitle}}</div> |
||||
</div> |
||||
<el-table v-table-height v-loading="loading" :data="tableData" border> |
||||
<el-table-column v-if="rsvrsdFlag" prop="typename" label="类型" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column v-if="!rsvrsdFlag" prop="area" label="区域" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column prop="stnm" label="站名" :align="alignment" width="200"> |
||||
</el-table-column> |
||||
<el-table-column prop="minvalue" label="当前水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column prop="value" label="平均水位" :align="alignment"> |
||||
</el-table-column> |
||||
<el-table-column label="最高水位" :align="alignment"> |
||||
<el-table-column prop="maxvalue" label="水位" :align="alignment" width="80"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180" prop="maxtm"></el-table-column> |
||||
</el-table-column> |
||||
<el-table-column label="最低水位" :align="alignment"> |
||||
<el-table-column prop="minvalue" label="水位" :align="alignment" width="80"> |
||||
</el-table-column> |
||||
<el-table-column label="时间" :align="alignment" width="180" prop="mintm"></el-table-column> |
||||
</el-table-column> |
||||
<el-table-column prop="lsmaxvalue" label="历史最高" :align="alignment"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</pane> |
||||
</splitpanes> |
||||
|
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import dayjs from 'dayjs'; |
||||
import { |
||||
Splitpanes, |
||||
Pane |
||||
} from 'splitpanes' |
||||
import 'splitpanes/dist/splitpanes.css' |
||||
import ETree from '@/components/ETree/index.vue' |
||||
import useAppStore from '@/store/modules/app' |
||||
const device = computed(() => useAppStore().device); |
||||
|
||||
const props = defineProps({ |
||||
stationType: { |
||||
type: String, |
||||
default: 'A' |
||||
}, |
||||
requestPrefix: { |
||||
type: String, |
||||
default: "" |
||||
} |
||||
}) |
||||
const { |
||||
proxy |
||||
} = getCurrentInstance() |
||||
const type = computed(() => { |
||||
switch (props.stationType) { |
||||
case 'A': |
||||
return 'rain'; |
||||
case 'B': |
||||
return 'river'; |
||||
case 'C': |
||||
return 'rsvr'; |
||||
case 'D': |
||||
return 'tide'; |
||||
case 'E': |
||||
return 'q_qflow'; |
||||
} |
||||
}); |
||||
const alignment = 'center' |
||||
const firstSize = ref(proxy.SPLITPANES_CONFIG.DEFAULT_SIZE) |
||||
const eTreeRef = ref(null) |
||||
let stnmIdsList = [] |
||||
const handleStationLoading = (loadingState) => { |
||||
loading.value = loadingState; |
||||
} |
||||
// 新增处理站点变化的函数 |
||||
const handleStationChange = (stnmIds) => { |
||||
stnmIdsList = stnmIds |
||||
queryParams.stnmIds = stnmIds.join(',') |
||||
if (stnmIdsList.length == 0) { |
||||
proxy.$modal.msgWarning("请选择站点后查询"); |
||||
return |
||||
} else if (stnmIdsList.length > 50) { |
||||
proxy.$modal.msg("站点最多可选择50个"); |
||||
return |
||||
} else { |
||||
getList() |
||||
|
||||
} |
||||
} |
||||
const queryParams = reactive({ |
||||
startTime: dayjs().subtract(30, 'day').format('YYYY-MM-DD 08:00:00'), |
||||
endTime: dayjs().format('YYYY-MM-DD 08:00:00'), |
||||
type: type.value, |
||||
stnmIds: '', |
||||
}); |
||||
|
||||
// 禁用开始时间选择器中大于当前时间和结束时间的日期 |
||||
const disabledStartDate = (time) => { |
||||
const endTime = queryParams.endTime ? dayjs(queryParams.endTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(endTime && dayjs(time).isAfter(endTime)); |
||||
}; |
||||
|
||||
// 禁用结束时间选择器中大于当前时间和小于开始时间的日期 |
||||
const disabledEndDate = (time) => { |
||||
const startTime = queryParams.startTime ? dayjs(queryParams.startTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(startTime && dayjs(time).isBefore(startTime)); |
||||
}; |
||||
|
||||
const tableTitle = '水位时段统计(m)' |
||||
// 根据stationType判断是否为河道 |
||||
const rsvrsdFlag = computed(() => { |
||||
return props.stationType == 'C' |
||||
}) |
||||
const tableData = ref([]) |
||||
const loading = ref(false) |
||||
|
||||
// 修改 getList 函数来处理动态列和数据 |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
let url = `/report/${props.requestPrefix}` |
||||
try { |
||||
let res = await proxy.axiosPost2(url, queryParams) |
||||
if (res.code == 0) { |
||||
let data = res.data |
||||
data.map(item => { |
||||
item.maxtm = dayjs(item.maxtm).format('YYYY-MM-DD HH:mm:ss') |
||||
item.mintm = dayjs(item.mintm).format('YYYY-MM-DD HH:mm:ss') |
||||
return item |
||||
}) |
||||
tableData.value = data |
||||
} |
||||
} catch (error) { |
||||
tableData.value = []; |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
|
||||
// 查询 |
||||
const handleQuery = async () => { |
||||
getList() |
||||
} |
||||
|
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
||||
@ -0,0 +1,245 @@
@@ -0,0 +1,245 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="时间维度"> |
||||
<el-select v-model="queryParams.dataType" placeholder="请选择时间维度" class="w150" @change="changeDataType"> |
||||
<el-option v-for="item in dataTypes" :key="item.value" :label="item.label" :value="item.value"> |
||||
</el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker v-model="queryParams.startTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" placeholder="选择开始时间" :disabled-date="disabledStartDate" @change="(val)=>changeTime(val,'start')"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker v-model="queryParams.endTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" placeholder="选择结束时间" :disabled-date="disabledEndDate" @change="(val)=>changeTime(val,'end')"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
<splitpanes :horizontal="device === 'mobile'" class="el-card-p card-shadow carder-border mt10 pad10 default-theme container-box" :push-other-panes="false"> |
||||
<pane :size="firstSize" :min-size="SPLITPANES_CONFIG.MIN_SIZE" :max-size="SPLITPANES_CONFIG.MAX_SIZE" ref="firstPane" class="mr10"> |
||||
<e-tree ref="eTreeRef" :stationType="stationType" @stationChange="handleStationChange"></e-tree> |
||||
</pane> |
||||
<pane :size="100 - firstSize"> |
||||
<splitpanes horizontal class="default-theme" :push-other-panes="false"> |
||||
<pane size="50"> |
||||
<TimeBarChart v-loading="echartsLoading" :legendData='legendData' :xAxisData="xAxisData" :seriesData="seriesData" :echartType="echartType" :grid="grid" :BarFormatter="false" :unit="unit" /> |
||||
</pane> |
||||
<pane size="50" class="mr10"> |
||||
<div class="main-table-header"> |
||||
<div class="table-title">{{tableTitle}}</div> |
||||
<div class="table-time mb5"> |
||||
<div> |
||||
<span>时间: </span><span id="title1">{{ tableTime}}</span> |
||||
</div> |
||||
<div> |
||||
<span>单位: </span><span id="title2">mm</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<el-table v-loading="loading" ref="myTable" :data="tableData" v-table-height="{bottom:90}" border> |
||||
<el-table-column :align="alignment" :width="item.label == '时间' ? '180': '' " :prop="item.prop" :label="item.label" v-for="(item, index) in tableHead" :key="index"></el-table-column> |
||||
</el-table> |
||||
</pane> |
||||
</splitpanes> |
||||
</pane> |
||||
</splitpanes> |
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import dayjs from 'dayjs'; |
||||
import { |
||||
Splitpanes, |
||||
Pane |
||||
} from 'splitpanes' |
||||
import 'splitpanes/dist/splitpanes.css' |
||||
import BarChart from '@/components/ChartsBar/index.vue' |
||||
import TimeBarChart from '@/components/ChartsTimeBar/index.vue' |
||||
import ETree from '@/components/ETree/index.vue' |
||||
|
||||
import useAppStore from '@/store/modules/app' |
||||
const device = computed(() => useAppStore().device); |
||||
|
||||
const props = defineProps({ |
||||
stationType: { |
||||
type: String, |
||||
default: 'A' |
||||
}, |
||||
tableTitle: { |
||||
type: String, |
||||
default: '表格标题' |
||||
}, |
||||
requestPrefix: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
requestPrefixTable: { |
||||
type: String, |
||||
default: '' |
||||
} |
||||
}) |
||||
const { proxy } = getCurrentInstance() |
||||
const alignment = 'center' |
||||
let unit = ref('m') |
||||
const eTreeRef = ref(null) |
||||
let stnmIdsList = [] |
||||
// 新增处理站点变化的函数 |
||||
const handleStationChange = (stnmIds) => { |
||||
stnmIdsList = stnmIds |
||||
queryParams.stnmIds = stnmIds.join(',') |
||||
if (stnmIdsList.length == 0) { |
||||
proxy.$modal.msgWarning("请选择站点后查询"); |
||||
return |
||||
} else if (stnmIdsList.length > 50) { |
||||
proxy.$modal.msg("站点最多可选择50个"); |
||||
return |
||||
} else { |
||||
getList() |
||||
getEchartsData() |
||||
} |
||||
} |
||||
const queryParams = reactive({ |
||||
startTime: dayjs().subtract(7, 'day').format('YYYY-MM-DD 08:00:00'), |
||||
endTime: dayjs().format('YYYY-MM-DD 08:00:00'), |
||||
dataType: '0', |
||||
}); |
||||
|
||||
// 禁用开始时间选择器中大于当前时间和结束时间的日期 |
||||
const disabledStartDate = (time) => { |
||||
const endTime = queryParams.endTime ? dayjs(queryParams.endTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(endTime && dayjs(time).isAfter(endTime)); |
||||
}; |
||||
|
||||
// 禁用结束时间选择器中大于当前时间和小于开始时间的日期 |
||||
const disabledEndDate = (time) => { |
||||
const startTime = queryParams.startTime ? dayjs(queryParams.startTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(startTime && dayjs(time).isBefore(startTime)); |
||||
}; |
||||
const tableTime = ref(queryParams.startTime.substring(0, 16) + " 至 " + queryParams.endTime.substring(0, 16)) |
||||
const timeType = ref('day') |
||||
// 改变时间纬度 |
||||
const changeDataType = (val) => { |
||||
queryParams.dataType = val |
||||
if (val == 0) { |
||||
tableTime.value = queryParams.startTime.substring(0, 16) + " 至 " + queryParams.endTime.substring(0, 16); |
||||
} else { |
||||
tableTime.value = queryParams.startTime.substring(0, 10) + " 至 " + queryParams.endTime.substring(0, 10); |
||||
} |
||||
getList() |
||||
getEchartsData() |
||||
} |
||||
// 改变时间 |
||||
const changeTime = (val, type = 'start') => { |
||||
if (type == 'start') { |
||||
queryParams.startTime = dayjs(val).format('YYYY-MM-DD HH:mm:ss') |
||||
} else { |
||||
queryParams.endTime = dayjs(val).format('YYYY-MM-DD HH:mm:ss') |
||||
} |
||||
} |
||||
const firstSize = ref(proxy.SPLITPANES_CONFIG.DEFAULT_SIZE) |
||||
const loading = ref(false) |
||||
const tableData = ref([]) |
||||
const tableHead = ref([]) |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
try { |
||||
let res = await proxy.axiosPost2(props.requestPrefixTable, queryParams) |
||||
if (res.code == 0) { |
||||
tableHead.value = handleTableHead(res.data) |
||||
let data = res.data.slice(1) |
||||
if (queryParams.dataType == 1) { |
||||
data.map(item => { item.tm = item.tm.slice(0, 10) }) |
||||
} else { |
||||
data.map(item => { item.tm = item.tm.slice(0, 16) }) |
||||
} |
||||
tableData.value = data |
||||
} |
||||
} catch (error) { |
||||
tableHead.value = []; |
||||
tableData.value = []; |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
// 假设 res.data 是从接口返回的数据 |
||||
const handleTableHead = (data) => { |
||||
if (!data || data.length === 0) return []; |
||||
|
||||
const firstRow = data[0]; // 第一条数据,包含所有字段名 |
||||
const head = []; |
||||
|
||||
// 添加 "时间" 列 |
||||
head.push({ prop: 'tm', label: '时间' }); |
||||
|
||||
// 遍历 firstRow 的 key-value,提取站点名称作为列名 |
||||
Object.keys(firstRow).forEach(key => { |
||||
if (key !== 'avg' && key !== 'tm') { |
||||
head.push({ prop: key, label: firstRow[key] }); |
||||
} |
||||
}); |
||||
return head; |
||||
}; |
||||
const legendData = ref([]) |
||||
const xAxisData = ref([]) |
||||
const seriesData = ref([]) |
||||
const echartsLoading = ref(false) |
||||
const getEchartsData = async () => { |
||||
echartsLoading.value = true |
||||
try { |
||||
let res = await proxy.axiosPost2(props.requestPrefix, queryParams); |
||||
if (res.code === 0) { |
||||
legendData.value = res.data.legend |
||||
// 提取每个series中data的第一个元素并格式化时间 |
||||
if (res.data.series && res.data.series.length > 0) { |
||||
// 假设第一个series的data包含完整的时间点 |
||||
xAxisData.value = res.data.series[0].data.map(item => { |
||||
// 如果item是对象且包含时间字段 |
||||
if (typeof item === 'object' && item !== null) { |
||||
// 假设时间字段可能是tm, time, or the first element |
||||
const timeValue = item.tm || item.time || item[0]; |
||||
return dayjs(timeValue).format('YYYY-MM-DD HH:mm'); |
||||
} else { |
||||
// 如果item直接就是时间值 |
||||
return dayjs(item).format('YYYY-MM-DD HH:mm'); |
||||
} |
||||
}); |
||||
} |
||||
seriesData.value = res.data.series |
||||
} |
||||
} catch (error) { |
||||
|
||||
} finally { |
||||
echartsLoading.value = false |
||||
} |
||||
}; |
||||
const echartType = ref('line') |
||||
const handleQuery = () => { |
||||
getList() |
||||
getEchartsData() |
||||
} |
||||
const dataTypes = ref([ |
||||
{ label: '5分钟', value: '-1' }, |
||||
{ label: '小时', value: '0' }, |
||||
{ label: '日', value: '1' } |
||||
]) |
||||
const grid = { |
||||
left: "5%", |
||||
right: "5%", |
||||
bottom: "10%", |
||||
top: "10%", |
||||
containLabel: true, |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
:deep(.el-tabs), |
||||
:deep(.el-tabs .el-tabs__content) { |
||||
height: 100%; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,283 @@
@@ -0,0 +1,283 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="年份区间"> |
||||
<el-date-picker class="picker-year" style="width:180px" v-model="queryParams.startTime" type="year" value-format="YYYY" placeholder="选择开始年" @change="handleQuery"> |
||||
</el-date-picker> |
||||
<span class="pr10 pl10"> - </span> |
||||
<el-date-picker class="picker-year" style="width:180px" v-model="queryParams.endTime" type="year" value-format="YYYY" placeholder="选择结束年" @change="handleQuery"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
</el-form-item> |
||||
<br /> |
||||
<el-form-item label="报表排列方式(按站点)"> |
||||
<el-radio-group v-model="direction" @change="getList"> |
||||
<el-radio label="zx">纵向</el-radio> |
||||
<el-radio label="hx">横向</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
<splitpanes :horizontal="device === 'mobile'" class="el-card-p card-shadow carder-border mt10 pad10 default-theme container-box" :push-other-panes="false"> |
||||
<pane :size="firstSize" :min-size="SPLITPANES_CONFIG.MIN_SIZE" :max-size="SPLITPANES_CONFIG.MAX_SIZE" ref="firstPane" class="mr10"> |
||||
<e-tree ref="eTreeRef" :stationType="stationType" @stationChange="handleStationChange"></e-tree> |
||||
</pane> |
||||
<pane :size="100 - firstSize"> |
||||
<div class="main-table-header"> |
||||
<div class="table-title">{{tableTitle}}</div> |
||||
</div> |
||||
<el-table v-if="direction=='zx'" v-loading="loading" ref="myTable" :data="tableData" v-table-height="{bottom:90}" border :span-method="arraySpanMethod"> |
||||
<el-table-column prop="station" label="站点" :align="alignment" :rowspan="getRowspan"></el-table-column> |
||||
<el-table-column prop="type" label="" :align="alignment"></el-table-column> |
||||
<el-table-column :align="alignment" :prop="item.prop" :label="item.label" v-for="(item, index) in tableColumns.filter(col => col.prop !== 'station' && col.prop !== 'type')" :key="index"></el-table-column> |
||||
</el-table> |
||||
<el-table v-if="direction=='hx'" v-table-height v-loading="loading" :data="tableData" border :span-method="arraySpanMethod"> |
||||
<el-table-column label="年份" prop="time" :align="alignment"></el-table-column> |
||||
<el-table-column :align="alignment" v-for="(column, index) in tableColumns" :key="column.prop" :prop="column.prop" :label="column.label" :min-width="120"> |
||||
<el-table-column label="平均水位" :prop="'avg'+index" :align="alignment"></el-table-column> |
||||
<el-table-column label="最高水位" :prop="'maxValue'+index" :align="alignment"></el-table-column> |
||||
<el-table-column label="时间" :prop="'maxtm'+index" :align="alignment"></el-table-column> |
||||
<el-table-column label="最低水位" :prop="'minValue'+index" :align="alignment"></el-table-column> |
||||
<el-table-column label="时间" :prop="'mintm'+index" :align="alignment"></el-table-column> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
</pane> |
||||
</splitpanes> |
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import dayjs from 'dayjs'; |
||||
import { |
||||
Splitpanes, |
||||
Pane |
||||
} from 'splitpanes' |
||||
import 'splitpanes/dist/splitpanes.css' |
||||
import ETree from '@/components/ETree/index.vue' |
||||
|
||||
import useAppStore from '@/store/modules/app' |
||||
const device = computed(() => useAppStore().device); |
||||
|
||||
const props = defineProps({ |
||||
// 类型 |
||||
stationType: { |
||||
type: String, |
||||
default: 'A' |
||||
}, |
||||
// 请求接口 |
||||
requestPrefix: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 数据库表名 |
||||
tableName: { |
||||
type: String, |
||||
default: "" |
||||
}, |
||||
}) |
||||
const { proxy } = getCurrentInstance() |
||||
const alignment = 'center' |
||||
let direction = ref('zx') |
||||
const eTreeRef = ref(null) |
||||
const tableTitle = '水位年特征值表(m)' |
||||
let stnmIdsList = [] |
||||
// 新增处理站点变化的函数 |
||||
const handleStationChange = (stnmIds) => { |
||||
stnmIdsList = stnmIds |
||||
queryParams.stnmIds = stnmIds.join(',') |
||||
if (stnmIdsList.length == 0) { |
||||
proxy.$modal.msgWarning("请选择站点后查询"); |
||||
return |
||||
} else if (stnmIdsList.length > 50) { |
||||
proxy.$modal.msg("站点最多可选择50个"); |
||||
return |
||||
} else { |
||||
getList() |
||||
} |
||||
} |
||||
|
||||
const queryParams = reactive({ |
||||
startTime: dayjs().subtract(1, 'year').format('YYYY'), |
||||
endTime: dayjs().format('YYYY'), |
||||
tableName: props.tableName, |
||||
valueType: "all" |
||||
}); |
||||
|
||||
|
||||
const firstSize = ref(proxy.SPLITPANES_CONFIG.DEFAULT_SIZE) |
||||
const loading = ref(false) |
||||
const tableColumns = ref([]) |
||||
const tableData = ref([]) |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
let url = `/report/${props.requestPrefix}` |
||||
try { |
||||
let res = await proxy.axiosPost2(url, queryParams) |
||||
if (res.code == 0) { |
||||
if (direction.value == 'zx') { |
||||
getZXTableData(res) |
||||
} else { |
||||
getHXTableData(res) |
||||
} |
||||
} |
||||
} catch (error) { |
||||
tableColumns.value = []; |
||||
tableData.value = []; |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
// 修复后的 getZXTableData 方法 |
||||
const getZXTableData = (res) => { |
||||
let { year, list, name } = res.data; |
||||
let columns = [ |
||||
{ |
||||
prop: "station", |
||||
label: "站点" |
||||
}, |
||||
{ |
||||
prop: "type", |
||||
label: "" |
||||
} |
||||
] |
||||
|
||||
// 添加年份列 |
||||
year.forEach(item => { |
||||
columns.push({ |
||||
prop: item, |
||||
label: item |
||||
}); |
||||
}); |
||||
|
||||
tableColumns.value = columns |
||||
|
||||
// 处理数据部分 |
||||
let processedData = []; |
||||
|
||||
list.forEach((item, index) => { |
||||
// 平均水位行 |
||||
const row1 = { |
||||
station: name[index], |
||||
type: "平均水位" |
||||
}; |
||||
|
||||
year.forEach((y, yIndex) => { |
||||
row1[y] = item[yIndex] && item[yIndex].value !== undefined ? item[yIndex].value : '-'; |
||||
}); |
||||
|
||||
// 最高水位行 |
||||
const row2 = { |
||||
station: name[index], |
||||
type: "最高水位" |
||||
}; |
||||
|
||||
year.forEach((y, yIndex) => { |
||||
row2[y] = item[yIndex] && item[yIndex].maxValue !== undefined ? item[yIndex].maxValue : '-'; |
||||
}); |
||||
|
||||
// 最高水位时间行 |
||||
const row3 = { |
||||
station: name[index], |
||||
type: "时间" |
||||
}; |
||||
|
||||
year.forEach((y, yIndex) => { |
||||
row3[y] = item[yIndex] && item[yIndex].maxtm !== undefined ? |
||||
proxy.parseTime(item[yIndex].maxtm, '{y}-{m}-{d}') : '-'; |
||||
}); |
||||
|
||||
// 最低水位行 |
||||
const row4 = { |
||||
station: name[index], |
||||
type: "最低水位" |
||||
}; |
||||
|
||||
year.forEach((y, yIndex) => { |
||||
row4[y] = item[yIndex] && item[yIndex].minValue !== undefined ? item[yIndex].minValue : '-'; |
||||
}); |
||||
|
||||
// 最低水位时间行 |
||||
const row5 = { |
||||
station: name[index], |
||||
type: "时间" |
||||
}; |
||||
|
||||
year.forEach((y, yIndex) => { |
||||
row5[y] = item[yIndex] && item[yIndex].mintm !== undefined ? |
||||
proxy.parseTime(item[yIndex].mintm, '{y}-{m}-{d}') : '-'; |
||||
}); |
||||
|
||||
processedData.push(row1); |
||||
processedData.push(row2); |
||||
processedData.push(row3); |
||||
processedData.push(row4); |
||||
processedData.push(row5); |
||||
}); |
||||
|
||||
// 关键:确保将处理好的数据赋值给 tableData |
||||
tableData.value = processedData; |
||||
} |
||||
const getHXTableData = (res) => { |
||||
const { year, list, name, } = res.data; |
||||
|
||||
if (!year || !list || !name) { |
||||
tableData.value = []; |
||||
return; |
||||
} |
||||
|
||||
const columns = name.map(stationName => ({ |
||||
prop: stationName, |
||||
label: stationName |
||||
})); |
||||
|
||||
tableColumns.value = columns; |
||||
const processedData = []; |
||||
|
||||
// 添加年份行 |
||||
year.forEach(y => { |
||||
const row = { time: y }; |
||||
name.forEach((stationName, idx) => { |
||||
const stationIndex = name.indexOf(stationName); |
||||
const stationList = list[stationIndex]; |
||||
if (!stationList || stationList.length === 0) { |
||||
row[stationName] = { avg: "-", maxValue: '-', maxtm: '-', minValue: '-', mintm: '-' }; |
||||
return; |
||||
} |
||||
const valueItem = stationList[0]; // 假设只有一个记录 |
||||
row['avg' + idx] = valueItem.value ? valueItem.value : '-' |
||||
row['maxValue' + idx] = valueItem.maxValue ? valueItem.maxValue : '-' |
||||
row['maxtm' + idx] = valueItem.maxtm ? valueItem.maxtm : '-' |
||||
row['minValue' + idx] = valueItem.minValue ? valueItem.minValue : '-' |
||||
row['mintm' + idx] = valueItem.mintm ? valueItem.mintm : '-' |
||||
}); |
||||
processedData.push(row); |
||||
}); |
||||
tableData.value = processedData; |
||||
}; |
||||
|
||||
// 行列合并 |
||||
|
||||
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => { |
||||
if (direction.value == 'zx') { |
||||
if (columnIndex === 0) { |
||||
// 每两行合并一次 |
||||
if (rowIndex % 5 === 0) { |
||||
// 偶数行显示,奇数行隐藏 |
||||
return [5, 1]; |
||||
} else { |
||||
// 隐藏奇数行 |
||||
return [0, 0]; |
||||
} |
||||
} |
||||
} |
||||
return [1, 1]; |
||||
} |
||||
|
||||
const handleQuery = () => { |
||||
getList() |
||||
} |
||||
|
||||
</script> |
||||
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
<template> |
||||
<div class="report-rain"> |
||||
<div class="tjfx-menu"> |
||||
<el-select v-model="menu" placeholder="请选择"> |
||||
<el-option v-for="dict in tjfxMenus" :key="dict.value" :label="dict.label" :value="dict.value" /> |
||||
</el-select> |
||||
</div> |
||||
<!-- 添加加载状态和错误提示 --> |
||||
<el-empty v-if="componentError" class="error-message" description="组件加载失败,请刷新页面重试" /> |
||||
<component :is="currentComponent" :tableTitle="tableTitle"></component> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup> |
||||
import { ref, computed, defineAsyncComponent } from 'vue' |
||||
|
||||
|
||||
// 定义菜单选项 |
||||
const tjfxMenus = [ |
||||
{ |
||||
value: '1', |
||||
label: '时段过程' |
||||
}, |
||||
{ |
||||
value: '2', |
||||
label: '年特征值' |
||||
}, { |
||||
value: '3', |
||||
label: '时段统计' |
||||
}, { |
||||
value: '4', |
||||
label: '历史同期对比' |
||||
} |
||||
] |
||||
|
||||
// 当前选中的菜单 |
||||
const menu = ref(tjfxMenus.length > 0 ? tjfxMenus[0].value : '') |
||||
|
||||
// 动态组件映射 |
||||
const componentMap = { |
||||
'1': defineAsyncComponent(() => import('@/views/statistic/rsvr/sdrsvr.vue')), |
||||
'2': defineAsyncComponent(() => import('@/views/statistic/rsvr/rsvrtzz.vue')), |
||||
'3': defineAsyncComponent(() => import('@/views/statistic/rsvr/rsvrsd.vue')), |
||||
'4': defineAsyncComponent(() => import('@/views/statistic/rsvr/rsvrls.vue')) |
||||
} |
||||
// 添加错误处理 |
||||
const componentError = ref(false) |
||||
|
||||
onErrorCaptured((error) => { |
||||
componentError.value = true |
||||
return true |
||||
}) |
||||
|
||||
// 计算当前应该显示的组件 |
||||
const currentComponent = computed(() => { |
||||
return componentMap[menu.value] |
||||
}) |
||||
// 原代码有误,tjfxMenus 中的对象没有 name 属性 |
||||
const tableTitle = computed(() => { |
||||
const currentItem = tjfxMenus.find(item => item.value === menu.value); |
||||
return currentItem ? currentItem.label : ''; |
||||
}) |
||||
</script> |
||||
|
||||
<style lang="scss"> |
||||
.tjfx-menu { |
||||
position: absolute; |
||||
right: 25px; |
||||
top: 30px; |
||||
z-index: 999999; |
||||
|
||||
.el-input__wrapper { |
||||
background: #10163A; |
||||
} |
||||
|
||||
.el-input__inner { |
||||
background: #10163A; |
||||
color: #fff; |
||||
border-color: #10163A; |
||||
} |
||||
|
||||
.el-select .el-input .el-select__caret { |
||||
color: #fff !important; |
||||
} |
||||
} |
||||
</style> |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
<template> |
||||
<history-yoy :stationType="stationType" :fixed="fixed" :requestPrefix="requestPrefix" :tableTitle="title"></history-yoy> |
||||
</template> |
||||
<script setup> |
||||
import HistoryYoy from '@/components/HistoryYOY/index.vue' |
||||
const stationType = ref('C') |
||||
const fixed = ref(1) |
||||
const requestPrefix = ref('history') |
||||
const title = '水库水位历史同期对比' |
||||
</script> |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
<template> |
||||
<time-count :stationType="stationType" :fixed="fixed" :requestPrefix="requestPrefix" :tableTitle="title"></time-count> |
||||
</template> |
||||
<script setup> |
||||
import TimeCount from '@/components/TimeCount/index.vue' |
||||
const stationType = ref('C') |
||||
const fixed = ref(1) |
||||
const requestPrefix = ref('sddata') |
||||
const title = '水库水位时段统计(m)' |
||||
</script> |
||||
@ -0,0 +1,307 @@
@@ -0,0 +1,307 @@
|
||||
<template> |
||||
<div class="app-container app-container-bg"> |
||||
<el-card class="first-card" ref='firstCard' shadow="always"> |
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker v-model="queryParams.startTime" type="datetime" value-format="MM-DD" format="YYYY-MM-DD HH:mm:ss" placeholder="选择开始时间" :disabled-date="disabledStartDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker v-model="queryParams.endTime" type="datetime" value-format="MM-DD" format="YYYY-MM-DD HH:mm:ss" placeholder="选择结束时间" :disabled-date="disabledEndDate"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="年份区间"> |
||||
<el-date-picker class="picker-year" style="width:120px" v-model="yearstart" type="year" value-format="YYYY" placeholder="选择开始年"> |
||||
</el-date-picker> |
||||
<span class="pr10 pl10"> - </span> |
||||
<el-date-picker class="picker-year" style="width:120px" v-model="yearend" type="year" value-format="YYYY" placeholder="选择结束年"> |
||||
</el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button> |
||||
</el-form-item> |
||||
<br /> |
||||
<el-form-item label="报表排列方式(按站点)"> |
||||
<el-radio-group v-model="direction" @change="getList"> |
||||
<el-radio label="zx">纵向</el-radio> |
||||
<el-radio label="hx">横向</el-radio> |
||||
</el-radio-group> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
<splitpanes :horizontal="device === 'mobile'" class="el-card-p card-shadow carder-border mt10 pad10 default-theme container-box" :push-other-panes="false"> |
||||
<pane :size="firstSize" :min-size="SPLITPANES_CONFIG.MIN_SIZE" :max-size="SPLITPANES_CONFIG.MAX_SIZE" ref="firstPane" class="mr10"> |
||||
<e-tree ref="eTreeRef" :stationType="stationType" @stationChange="handleStationChange" @loadingChange="handleStationLoading"></e-tree> |
||||
</pane> |
||||
<pane :size="100 - firstSize" style="height: 100%;"> |
||||
<div class="main-table-header"> |
||||
<div class="table-title">{{tableTitle}}</div> |
||||
</div> |
||||
<el-table v-table-height v-loading="loading" :data="tableData" border :span-method="arraySpanMethod"> |
||||
<el-table-column :align="alignment" v-for="column in tableColumns" :key="column.prop" :prop="column.prop" :label="column.label" :min-width="column.width || 120"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</pane> |
||||
</splitpanes> |
||||
|
||||
</div> |
||||
</template> |
||||
<script setup> |
||||
import dayjs from 'dayjs'; |
||||
import { |
||||
Splitpanes, |
||||
Pane |
||||
} from 'splitpanes' |
||||
import 'splitpanes/dist/splitpanes.css' |
||||
import ETree from '@/components/ETree/index.vue' |
||||
import useAppStore from '@/store/modules/app' |
||||
const device = computed(() => useAppStore().device); |
||||
|
||||
const props = defineProps({ |
||||
}) |
||||
const { |
||||
proxy |
||||
} = getCurrentInstance() |
||||
const { update_type_options } = proxy.useDict("update_type_options") |
||||
const stationType = 'A' |
||||
const alignment = 'center' |
||||
const firstSize = ref(proxy.SPLITPANES_CONFIG.DEFAULT_SIZE) |
||||
const direction = ref('zx') |
||||
const eTreeRef = ref(null) |
||||
let stnmIdsList = [] |
||||
const handleStationLoading = (loadingState) => { |
||||
loading.value = loadingState; |
||||
} |
||||
// 新增处理站点变化的函数 |
||||
const handleStationChange = (stnmIds) => { |
||||
stnmIdsList = stnmIds |
||||
queryParams.stnmIds = stnmIds.join(',') |
||||
if (stnmIdsList.length == 0) { |
||||
proxy.$modal.msgWarning("请选择站点后查询"); |
||||
return |
||||
} else if (stnmIdsList.length > 50) { |
||||
proxy.$modal.msg("站点最多可选择50个"); |
||||
return |
||||
} else { |
||||
getList() |
||||
|
||||
} |
||||
} |
||||
const yearstart = ref(dayjs().subtract(1, 'year').format('YYYY')) |
||||
const yearend = ref(dayjs().format('YYYY')) |
||||
const queryParams = reactive({ |
||||
startTime: dayjs().subtract(7, 'day').format('MM-DD'), |
||||
endTime: dayjs().format('MM-DD'), |
||||
years: `${yearstart.value}-${yearend.value}`, |
||||
stnmIds: '', |
||||
}); |
||||
|
||||
// 禁用开始时间选择器中大于当前时间和结束时间的日期 |
||||
const disabledStartDate = (time) => { |
||||
const endTime = queryParams.endTime ? dayjs(queryParams.endTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(endTime && dayjs(time).isAfter(endTime)); |
||||
}; |
||||
|
||||
// 禁用结束时间选择器中大于当前时间和小于开始时间的日期 |
||||
const disabledEndDate = (time) => { |
||||
const startTime = queryParams.startTime ? dayjs(queryParams.startTime) : null; |
||||
return dayjs(time).isAfter(dayjs()) || |
||||
(startTime && dayjs(time).isBefore(startTime)); |
||||
}; |
||||
|
||||
const tableTitle = computed(() => { |
||||
const startFormatted = dayjs(queryParams.startTime, 'MM-DD').format('MM月DD日'); |
||||
const endFormatted = dayjs(queryParams.endTime, 'MM-DD').format('MM月DD日'); |
||||
return `${startFormatted}~${endFormatted}历史同期降水量表(mm)`; |
||||
}); |
||||
const tableColumns = ref([]) |
||||
const tableData = ref([]) |
||||
const loading = ref(false) |
||||
|
||||
// 修改 getList 函数来处理动态列和数据 |
||||
const getList = async () => { |
||||
loading.value = true; |
||||
try { |
||||
let res = await proxy.axiosPost2('/report/rainhistorycount', queryParams) |
||||
if (res.code == 0) { |
||||
if (direction.value == 'zx') { |
||||
getZXTableData(res) |
||||
} else { |
||||
getHXTableData(res) |
||||
} |
||||
|
||||
} |
||||
} catch (error) { |
||||
tableColumns.value = []; |
||||
tableData.value = []; |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
const getZXTableData = (res) => { |
||||
let { year, list, name, max, min } = res.data; |
||||
let columns = [ |
||||
{ |
||||
prop: "station", |
||||
label: "站点" |
||||
}, |
||||
{ |
||||
prop: "type", |
||||
label: "" |
||||
} |
||||
] |
||||
// 添加站点列 |
||||
year.forEach(item => { |
||||
columns.push({ |
||||
prop: item, |
||||
label: item |
||||
}); |
||||
}); |
||||
tableColumns.value = columns |
||||
// 处理数据部分 - 构造两行合并的数据结构 |
||||
const processedData = []; |
||||
|
||||
list.forEach((item, index) => { |
||||
// 第一行:显示站点名称和"雨量" |
||||
const row1 = { |
||||
station: name[index], |
||||
type: "平均水位" |
||||
}; |
||||
year.forEach(y => { |
||||
row1[y] = item[0].value ? item[0].value.toFixed(1) : '-'; |
||||
}); |
||||
// const row2 = { |
||||
// station: name[index], |
||||
// type: "最高水位" |
||||
// }; |
||||
// year.forEach(y => { |
||||
// row2[y] = item[0].value ? item[0].value.toFixed(1) : '-'; |
||||
// }); |
||||
// const row3 = { |
||||
// station: name[index], |
||||
// type: "时间" |
||||
// }; |
||||
// year.forEach(y => { |
||||
// row3[y] = item[0].tm ? item[0].tm : '-'; |
||||
// }); |
||||
// const row4 = { |
||||
// station: name[index], |
||||
// type: "最高水位" |
||||
// }; |
||||
// year.forEach(y => { |
||||
// row4[y] = item[0].value ? item[0].value.toFixed(1) : '-'; |
||||
// }); |
||||
// const row5 = { |
||||
// station: name[index], |
||||
// type: "时间" |
||||
// }; |
||||
// year.forEach(y => { |
||||
// row5[y] = item[0].tm ? item[0].tm : '-'; |
||||
// }); |
||||
processedData.push(row1); |
||||
// processedData.push(row2); |
||||
// processedData.push(row3); |
||||
// processedData.push(row4); |
||||
// processedData.push(row5); |
||||
}); |
||||
console.log(processedData, 'processedData') |
||||
tableData.value = processedData; |
||||
} |
||||
const getHXTableData = (res) => { |
||||
const { year, list, name, max, min } = res.data; |
||||
|
||||
if (!year || !list || !name || !max || !min) { |
||||
console.error('数据缺失:', { year, list, name, max, min }); |
||||
tableData.value = []; |
||||
return; |
||||
} |
||||
|
||||
const columns = name.map(stationName => ({ |
||||
prop: stationName, |
||||
label: stationName |
||||
})); |
||||
|
||||
tableColumns.value = columns; |
||||
console.log(columns, 'tableColumns') |
||||
const processedData = []; |
||||
|
||||
// 添加年份行 |
||||
year.forEach(y => { |
||||
const row = { time: y }; |
||||
name.forEach((stationName, idx) => { |
||||
const stationIndex = name.indexOf(stationName); |
||||
const stationList = list[stationIndex]; |
||||
if (!stationList || stationList.length === 0) { |
||||
row[stationName] = { rain: '-', tm: '-' }; |
||||
return; |
||||
} |
||||
const valueItem = stationList[0]; // 假设只有一个记录 |
||||
row['rain' + idx] = valueItem.value ? valueItem.value.toFixed(1) : '-' |
||||
row['tm' + idx] = valueItem.tm ? valueItem.tm.slice(5) : '-' |
||||
}); |
||||
processedData.push(row); |
||||
}); |
||||
// 添加最大值行 |
||||
processedData.push({ |
||||
time: '最大值', |
||||
...name.reduce((acc, stationName, index) => { |
||||
acc['rain' + index] = max[index]?.value ? max[index]?.value.toFixed(1) : '-'; |
||||
acc['tm' + index] = max[index]?.tm ? max[index].tm : '-'; |
||||
return acc; |
||||
}, {}) |
||||
}); |
||||
|
||||
// 添加最小值行 |
||||
processedData.push({ |
||||
time: '最小值', |
||||
...name.reduce((acc, stationName, index) => { |
||||
acc['rain' + index] = min[index]?.value ? min[index]?.value.toFixed(1) : '-'; |
||||
acc['tm' + index] = min[index]?.tm ? min[index].tm : '-'; |
||||
return acc; |
||||
}, {}) |
||||
}); |
||||
|
||||
tableData.value = processedData; |
||||
}; |
||||
|
||||
// 查询 |
||||
const handleQuery = async () => { |
||||
getList() |
||||
} |
||||
// 行列合并 |
||||
|
||||
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => { |
||||
// 获取总列数 |
||||
const columnCount = tableColumns.value.length; |
||||
|
||||
// 如果是最后一列(最大值/最小值列),不进行合并 |
||||
if (columnIndex === columnCount - 1 || columnIndex === columnCount - 2) { |
||||
return [1, 1]; |
||||
} |
||||
|
||||
// 第一列(站点名称列)的合并逻辑 |
||||
if (columnIndex === 0) { |
||||
// 每两行合并一次 |
||||
if (rowIndex % 2 === 0) { |
||||
// 偶数行显示,奇数行隐藏 |
||||
return [2, 1]; |
||||
} else { |
||||
// 隐藏奇数行 |
||||
return [0, 0]; |
||||
} |
||||
} |
||||
|
||||
// 其他数据列的合并逻辑 |
||||
if (rowIndex % 2 === 0) { |
||||
// 偶数行显示,奇数行隐藏 |
||||
return [2, 1]; |
||||
} else { |
||||
// 隐藏奇数行 |
||||
return [0, 0]; |
||||
} |
||||
} |
||||
|
||||
</script> |
||||
<style lang="scss" scoped> |
||||
</style> |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<template> |
||||
<year-eigenvalue :stationType="stationType" :fixed="fixed" :requestPrefix="requestPrefix" :tableTitle="title" :tableName="tableName"></year-eigenvalue> |
||||
</template> |
||||
<script setup> |
||||
import YearEigenvalue from '@/components/YearEigenvalue/index.vue' |
||||
const stationType = ref('C') |
||||
const fixed = ref(1) |
||||
const requestPrefix = ref('tzzdatahistory') |
||||
let title = '水位年特征值表(m)' |
||||
let tableName=ref('arch_char_rsvr') |
||||
</script> |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<template> |
||||
<time-process :stationType="stationType" :fixed="fixed" :requestPrefix="requestPrefix" :requestPrefixTable="requestPrefixTable" :tableTitle="title"></time-process> |
||||
</template> |
||||
<script setup> |
||||
import TimeProcess from '@/components/TimeProcess/index.vue' |
||||
const stationType = ref('C') |
||||
const fixed = ref(1) |
||||
const requestPrefix = ref('/ycrsvrdata/chartdata') |
||||
const requestPrefixTable = ref('/ycrsvrdata/gettabledataopen') |
||||
const title = '水位时段过程' |
||||
</script> |
||||
Loading…
Reference in new issue