|
@@ -0,0 +1,810 @@
|
|
|
+<script setup name="combine">
|
|
|
+import searchCop from "./components/search.vue";
|
|
|
+import excelCop from "@/components/excel.vue";
|
|
|
+import treeCop from "@/components/tree.vue";
|
|
|
+import tableCop from "@/views/powerGenerating/dataFilter/components/table.vue";
|
|
|
+import {
|
|
|
+ getWindFittingExcelShow,
|
|
|
+ getWindFittingData,
|
|
|
+ getProcessData,
|
|
|
+ getProcessTree,
|
|
|
+ getWindFittingTree,
|
|
|
+ getWindFittingShow,
|
|
|
+ getWindFittingFilter,
|
|
|
+ getWindFittingAlarms,
|
|
|
+} from "@/api/powerGenerating/index.js";
|
|
|
+import SubmitBtn from "@/components/SubmitBtn.vue";
|
|
|
+import { ref, nextTick, onActivated, onMounted, reactive } from "vue";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+import CurrentScatterChart from "./components/current-scatter-chart.vue";
|
|
|
+const currentId = ref("");
|
|
|
+/**excel 开始 */
|
|
|
+const excelCheckboxShow = ref(false);
|
|
|
+const excelType = ref("");
|
|
|
+const excelCheckIds = ref([]);
|
|
|
+const excelList = ref([]);
|
|
|
+const funExcelChange = async (obj) => {
|
|
|
+ //点击excel项时
|
|
|
+ activeTab.value = "1";
|
|
|
+ isChartArea.value = false;
|
|
|
+ tableShowId.value = obj.id;
|
|
|
+ currentId.value = obj.id;
|
|
|
+ tableName.value = obj.name;
|
|
|
+ excelType.value = obj.type; // 接收excel的type 用于控制右侧tab展示
|
|
|
+
|
|
|
+ let res = null;
|
|
|
+ let chartRes = {
|
|
|
+ scatterhs: [[]],
|
|
|
+ scatterls: [[]],
|
|
|
+ sjgl: [[]],
|
|
|
+ llgl: [[]],
|
|
|
+ cpz: [[]],
|
|
|
+ };
|
|
|
+ let chartResponse = null;
|
|
|
+ tableLoading.value = true;
|
|
|
+ if (obj.type === "process") {
|
|
|
+ res = await getProcessData({ id: obj.id });
|
|
|
+ } else if (obj.type === "fitting") {
|
|
|
+ activeTab.value = "2";
|
|
|
+ res = await getWindFittingShow({ id: obj.id });
|
|
|
+ // res = tableRes
|
|
|
+ // chartResponse = dotRes
|
|
|
+ chartResponse = await getWindFittingExcelShow({ id: obj.id, p: 1 });
|
|
|
+ }
|
|
|
+ if (res.code === 200) {
|
|
|
+ tableColumn.value = res.data.title.map((o) => {
|
|
|
+ return {
|
|
|
+ prop: o.key,
|
|
|
+ width: o.des === "时间" ? 100 : 80,
|
|
|
+ label: o.des,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ tableData.value = res.data.data;
|
|
|
+ tableLoading.value = false;
|
|
|
+ } else {
|
|
|
+ tableLoading.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (chartResponse && chartResponse.code === 200) {
|
|
|
+ chartRes = chartResponse.data;
|
|
|
+ markDot.pcl5 = chartRes.obj.pc5ratio;
|
|
|
+ markDot.pcl10 = chartRes.obj.pc10ratio;
|
|
|
+ markDot.pcl12 = chartRes.obj.pc12ratio;
|
|
|
+ markDot.pcl25 = chartRes.obj.pc25ratio;
|
|
|
+ avgObj.title = chartRes.obj.path
|
|
|
+ .substring(
|
|
|
+ chartRes.obj.path.indexOf(chartRes.obj.station + "_") +
|
|
|
+ (chartRes.obj.station + "_").length
|
|
|
+ )
|
|
|
+ .split("_")[0];
|
|
|
+ avgObj.cpavg = Number(chartRes.obj.cpavg).toFixed(2);
|
|
|
+ avgObj.frequency = Number(chartRes.obj.frequency).toFixed(2);
|
|
|
+ avgObj.pcratio = Number(chartRes.obj.pcratio).toFixed(2);
|
|
|
+ dataSet.value = JSON.stringify([
|
|
|
+ {
|
|
|
+ source: chartRes.wyd,
|
|
|
+ // source: chartRes.scatterls
|
|
|
+ },
|
|
|
+ {
|
|
|
+ source: chartRes.yyd,
|
|
|
+ // source: chartRes.scatterhs
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+ const color = [
|
|
|
+ "#1C99FF",
|
|
|
+ "#FF8700",
|
|
|
+ "#3D54BE",
|
|
|
+ "#fa8c16",
|
|
|
+ "#1DA0D7",
|
|
|
+ "#DD5044",
|
|
|
+ ];
|
|
|
+ seriesData.value = [
|
|
|
+ {
|
|
|
+ name: "拟合功率",
|
|
|
+ type: "line",
|
|
|
+ symbol: "line", //设定为实心点
|
|
|
+ symbolSize: 0, //设定实心点的大小
|
|
|
+ smooth: true, //这个是把线变成曲线
|
|
|
+ data: chartRes.sjgl,
|
|
|
+ xAxisIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "保证功率",
|
|
|
+ type: "line",
|
|
|
+ symbol: "line", //设定为实心点
|
|
|
+ symbolSize: 0, //设定实心点的大小
|
|
|
+ smooth: true, //这个是把线变成曲线
|
|
|
+ data: chartRes.llgl,
|
|
|
+ xAxisIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "effectScatter",
|
|
|
+ showEffectOn: "emphasis",
|
|
|
+ rippleEffect: {
|
|
|
+ scale: 1,
|
|
|
+ },
|
|
|
+ name: "无用点",
|
|
|
+ symbolSize: (data) => {
|
|
|
+ return data.s ? (data.s > 10 ? 10 : data.s) : 4;
|
|
|
+ },
|
|
|
+ datasetIndex: 0,
|
|
|
+ encode: {
|
|
|
+ x: "x",
|
|
|
+ y: "y",
|
|
|
+ },
|
|
|
+ xAxisIndex: 0,
|
|
|
+ yAxisIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "effectScatter",
|
|
|
+ showEffectOn: "emphasis",
|
|
|
+ rippleEffect: {
|
|
|
+ scale: 1,
|
|
|
+ },
|
|
|
+ name: "有用点",
|
|
|
+ symbolSize: (data) => {
|
|
|
+ return data.s ? (data.s > 10 ? 10 : data.s) : 4;
|
|
|
+ },
|
|
|
+ datasetIndex: 1,
|
|
|
+ encode: {
|
|
|
+ x: "x",
|
|
|
+ y: "y",
|
|
|
+ },
|
|
|
+ xAxisIndex: 0,
|
|
|
+ yAxisIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "Cp值",
|
|
|
+ type: "line",
|
|
|
+ symbol: "line", //设定为实心点
|
|
|
+ symbolSize: 0, //设定实心点的大小
|
|
|
+ smooth: true, //这个是把线变成曲线
|
|
|
+ data: chartRes.cpz,
|
|
|
+ xAxisIndex: 0,
|
|
|
+ yAxisIndex: 1,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ }
|
|
|
+};
|
|
|
+const funExcelCheckChange = ({ checkArr, data }) => {
|
|
|
+ //bug
|
|
|
+ excelCheckIds.value = checkArr;
|
|
|
+};
|
|
|
+/**excel fitData */
|
|
|
+const excelFitList = ref([]);
|
|
|
+/**prepare tree 开始 */
|
|
|
+const treeData = ref([]);
|
|
|
+const actTreeNode = ref(null); //当前激活的treeNode
|
|
|
+const funRepeatMap = (arr, type = "prepare") => {
|
|
|
+ return arr.map((o) => {
|
|
|
+ if (o.children) {
|
|
|
+ const findIndex = o.children.findIndex((p) => !!p.type);
|
|
|
+ if (findIndex !== -1) {
|
|
|
+ o.childs = o.children;
|
|
|
+ o.children = [];
|
|
|
+ if (!actTreeNode.value && type === "process") {
|
|
|
+ //判断当且仅有process获取tree时 赋值
|
|
|
+ actTreeNode.value = o;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ ...o,
|
|
|
+ children: o.children ? funRepeatMap(o.children, type) : [],
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+const funGetTree = async () => {
|
|
|
+ const res = await getProcessTree();
|
|
|
+ treeData.value = funRepeatMap(res.data);
|
|
|
+ excelList.value = [];
|
|
|
+};
|
|
|
+const funCurrentChange = ({ current, currentNode }) => {
|
|
|
+ excelCheckboxShow.value = true;
|
|
|
+ if (current.childs) {
|
|
|
+ excelList.value = current.childs.map((o) => {
|
|
|
+ return {
|
|
|
+ id: o.id,
|
|
|
+ interval: o.interval,
|
|
|
+ path: o.path,
|
|
|
+ prepareid: o.prepareid,
|
|
|
+ station: o.station,
|
|
|
+ time: o.time,
|
|
|
+ type: o.type,
|
|
|
+ windturbine: o.windturbine,
|
|
|
+ name: o.path.substring(
|
|
|
+ o.path.indexOf(o.station + "_") + (o.station + "_").length
|
|
|
+ ),
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ excelList.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+const funTreeCheckChange = ({
|
|
|
+ current,
|
|
|
+ checkedNodes,
|
|
|
+ checkedKeys,
|
|
|
+ halfCheckedNodes,
|
|
|
+ halfCheckedKeys,
|
|
|
+}) => {
|
|
|
+ //tree change -> excel change
|
|
|
+ funCurrentChange({ current, currentNode: "" });
|
|
|
+ const checkIds = [];
|
|
|
+ if (checkedNodes.length) {
|
|
|
+ for (const node of checkedNodes) {
|
|
|
+ if (node.childs && node.childs.length) {
|
|
|
+ for (const child of node.childs) {
|
|
|
+ checkIds.push(child.id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ excelCheckIds.value = checkIds;
|
|
|
+};
|
|
|
+
|
|
|
+/**process tree 开始 */
|
|
|
+const processTreeData = ref([]);
|
|
|
+const funGetProcessTree = async (flag = true) => {
|
|
|
+ //flag控制是否获取tree的第一项 true为可获取
|
|
|
+ actTreeNode.value = null;
|
|
|
+ const res = await getWindFittingTree();
|
|
|
+ excelFitList.value = [];
|
|
|
+ processTreeData.value = funRepeatMap(res.data, flag ? "process" : "prepare"); //flag控制对actTreeNode赋值
|
|
|
+ if (actTreeNode.value) {
|
|
|
+ funProcessCurrentChange({ current: actTreeNode.value, currentNode: null });
|
|
|
+ const child = actTreeNode.value.childs[0];
|
|
|
+ const obj = {
|
|
|
+ id: child.id,
|
|
|
+ interval: child.interval,
|
|
|
+ path: child.path,
|
|
|
+ prepareid: child.prepareid,
|
|
|
+ station: child.station,
|
|
|
+ time: child.time,
|
|
|
+ type: child.type,
|
|
|
+ windturbine: child.windturbine,
|
|
|
+ name: child.path.substring(
|
|
|
+ child.path.indexOf(child.station + "_") + (child.station + "_").length
|
|
|
+ ),
|
|
|
+ };
|
|
|
+ funExcelChange(obj);
|
|
|
+ }
|
|
|
+};
|
|
|
+const funProcessCurrentChange = ({ current, currentNode }) => {
|
|
|
+ if (current.childs) {
|
|
|
+ excelFitList.value = current.childs.map((o) => {
|
|
|
+ return {
|
|
|
+ id: o.id,
|
|
|
+ interval: o.interval,
|
|
|
+ path: o.path,
|
|
|
+ prepareid: o.prepareid,
|
|
|
+ station: o.station,
|
|
|
+ time: o.time,
|
|
|
+ type: o.type,
|
|
|
+ windturbine: o.windturbine,
|
|
|
+ name: o.path.substring(
|
|
|
+ o.path.indexOf(o.station + "_") + (o.station + "_").length
|
|
|
+ ),
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ excelFitList.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/**table 开始 */
|
|
|
+const tableShowId = ref("");
|
|
|
+const tableColumn = ref([]);
|
|
|
+const tableLoading = ref(false);
|
|
|
+const tableName = ref("");
|
|
|
+const tableData = ref([]);
|
|
|
+/**table 结束 */
|
|
|
+/**search 开始 */
|
|
|
+const funSubmit = async (query) => {
|
|
|
+ if (!excelCheckIds.value.length) {
|
|
|
+ ElMessage.error("请勾选要预处理的项");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const params = {
|
|
|
+ ...query,
|
|
|
+ ids: excelCheckIds.value.join(","),
|
|
|
+ };
|
|
|
+ const res = await getWindFittingData(params);
|
|
|
+ if (res.code === 200) {
|
|
|
+ ElMessage.success(res.msg);
|
|
|
+ funGetProcessTree(false); //阻止获取tree第一项数据及图表
|
|
|
+ const excelInfo = res.data;
|
|
|
+
|
|
|
+ /**拟合完成后 显示右侧图表及数据 */
|
|
|
+ funExcelChange({
|
|
|
+ id: excelInfo.id,
|
|
|
+ name: excelInfo.path.substring(
|
|
|
+ excelInfo.path.indexOf(excelInfo.station + "_") +
|
|
|
+ (excelInfo.station + "_").length
|
|
|
+ ),
|
|
|
+ type: "fitting",
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|
|
|
+/**chart Data */
|
|
|
+const avgObj = reactive({
|
|
|
+ //平均cpz等
|
|
|
+ title: "",
|
|
|
+ cpavg: "",
|
|
|
+ frequency: "",
|
|
|
+ pcratio: "",
|
|
|
+});
|
|
|
+const markDot = reactive({
|
|
|
+ //3-5 point点等
|
|
|
+ pcl5: null,
|
|
|
+ pcl10: null,
|
|
|
+ pcl12: null,
|
|
|
+ pcl25: null,
|
|
|
+});
|
|
|
+const xAxisData = ref([]);
|
|
|
+const chartRef = ref(); //chart 的ref
|
|
|
+const seriesData = ref([]);
|
|
|
+const isChartArea = ref(false); // 用来控制图表是否区域划分
|
|
|
+const dataSet = ref("");
|
|
|
+const funChartSelect = async (batch) => {
|
|
|
+ const wDataArr = [];
|
|
|
+ const yDataArr = [];
|
|
|
+ let scatterls = [];
|
|
|
+ let scatterhs = [];
|
|
|
+ let dataSetObj = [];
|
|
|
+ wtData.value = [];
|
|
|
+ if (batch?.length && dataSet.value) {
|
|
|
+ scatterls = batch[0].selected[2].dataIndex;
|
|
|
+ scatterhs = batch[0].selected[3].dataIndex;
|
|
|
+ if (scatterls?.length || scatterhs?.length) {
|
|
|
+ dataSetObj = JSON.parse(dataSet.value);
|
|
|
+ if (scatterls?.length) {
|
|
|
+ for (const scatterIndex of scatterls) {
|
|
|
+ wDataArr.push(dataSetObj[0].source[scatterIndex].k);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (scatterhs?.length) {
|
|
|
+ for (const scatterIndex of scatterhs) {
|
|
|
+ yDataArr.push(dataSetObj[1].source[scatterIndex].k);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const wtRes = await getWindFittingFilter({
|
|
|
+ yk: yDataArr.join(","),
|
|
|
+ wk: wDataArr.join(","),
|
|
|
+ only: dataRadom.value,
|
|
|
+ });
|
|
|
+ if (wtRes.code === 200) {
|
|
|
+ let id = 1;
|
|
|
+ const tempArr = []; //用于以风机id 聚合dataArr
|
|
|
+ if (wtRes.data?.length) {
|
|
|
+ for (const data of wtRes.data) {
|
|
|
+ if (tempArr.length) {
|
|
|
+ const findIndex = tempArr.findIndex((o) => o.wtId === data.wtId);
|
|
|
+ if (findIndex !== -1) {
|
|
|
+ if (!tempArr[findIndex].children) {
|
|
|
+ tempArr[findIndex].children = [];
|
|
|
+ }
|
|
|
+ tempArr[findIndex].children.push({
|
|
|
+ ...data,
|
|
|
+ id: id,
|
|
|
+ filter: data.filter === 0 ? "是" : "否",
|
|
|
+ });
|
|
|
+ id++;
|
|
|
+ } else {
|
|
|
+ tempArr.push({
|
|
|
+ ...data,
|
|
|
+ id: id,
|
|
|
+ filter: data.filter === 0 ? "是" : "否",
|
|
|
+ });
|
|
|
+ id++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ tempArr.push({
|
|
|
+ ...data,
|
|
|
+ id: id,
|
|
|
+ filter: data.filter === 0 ? "是" : "否",
|
|
|
+ });
|
|
|
+ id++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ wtDialog.value = true;
|
|
|
+ nextTick(() => {
|
|
|
+ wtTab.value = "table";
|
|
|
+ wtData.value = tempArr;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+const funChartArea = () => {
|
|
|
+ if (seriesData.value?.length) {
|
|
|
+ if (!isChartArea.value) {
|
|
|
+ // 请求一下
|
|
|
+ seriesData.value[0] = {
|
|
|
+ ...seriesData.value[0],
|
|
|
+ markLine: {
|
|
|
+ symbol: "none",
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ lineStyle: {
|
|
|
+ color: "rgba(96,174,255, 1)",
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ xAxis: 3,
|
|
|
+ valueIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 5,
|
|
|
+ valueIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 10,
|
|
|
+ valueIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 12,
|
|
|
+ valueIndex: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 25,
|
|
|
+ valueIndex: 0,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ markArea: {
|
|
|
+ label: {
|
|
|
+ fontSize: 13,
|
|
|
+ color: "#ccc",
|
|
|
+ fontWeight: "normal",
|
|
|
+ fontFamily: "Arial",
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: "rgba(236,245,255, 0)",
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ itemStyle: {
|
|
|
+ color: "rgba(96,174,255, 0.5)",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data: [
|
|
|
+ [
|
|
|
+ {
|
|
|
+ name: `3~5m 偏差率: ${markDot.pcl5}%`,
|
|
|
+ xAxis: 3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 5,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ {
|
|
|
+ name: `5~10m 偏差率: ${markDot.pcl10}%`,
|
|
|
+ xAxis: 5,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 10,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ {
|
|
|
+ name: `10~12m 偏差率: ${markDot.pcl12}%`,
|
|
|
+ xAxis: 10,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 12,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ {
|
|
|
+ name: `12~25m 偏差率: ${markDot.pcl25}%`,
|
|
|
+ xAxis: 12,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ xAxis: 25,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ };
|
|
|
+ isChartArea.value = true;
|
|
|
+ } else {
|
|
|
+ seriesData.value[0] = {
|
|
|
+ ...seriesData.value[0],
|
|
|
+ markLine: null,
|
|
|
+ markArea: null,
|
|
|
+ };
|
|
|
+ isChartArea.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+const handleClick = (val) => {
|
|
|
+ wtTab.value = val.props.name;
|
|
|
+ if (wtTab.value === "problem") {
|
|
|
+ faultDataFn();
|
|
|
+ } else if (wtTab.value === "warning") {
|
|
|
+ warnDataFn();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//故障数据
|
|
|
+const faultDataFn = async () => {
|
|
|
+ let params = {
|
|
|
+ only: dataRadom.value,
|
|
|
+ table: "alarmWt",
|
|
|
+ };
|
|
|
+ const faultRes = await getWindFittingAlarms(params);
|
|
|
+ faultData.value = faultRes.data;
|
|
|
+};
|
|
|
+//预警数据
|
|
|
+const warnDataFn = async () => {
|
|
|
+ let params = {
|
|
|
+ only: dataRadom.value,
|
|
|
+ table: "alarmCt",
|
|
|
+ };
|
|
|
+ const warnRes = await getWindFittingAlarms(params);
|
|
|
+ warnData.value = warnRes.data;
|
|
|
+};
|
|
|
+
|
|
|
+/**dialog 数据 */
|
|
|
+const wtDialog = ref(false);
|
|
|
+const wtData = ref([]);
|
|
|
+const faultData = ref([]);
|
|
|
+const warnData = ref([]);
|
|
|
+const wtTab = ref("table");
|
|
|
+// 随机数
|
|
|
+const dataRadom = ref(null);
|
|
|
+/**tab */
|
|
|
+const activeTab = ref("1");
|
|
|
+/**created */
|
|
|
+funGetTree();
|
|
|
+funGetProcessTree();
|
|
|
+/**mounted */
|
|
|
+
|
|
|
+/**activated */
|
|
|
+onActivated(() => {
|
|
|
+ funGetTree();
|
|
|
+ funGetProcessTree();
|
|
|
+});
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="container-wrapper">
|
|
|
+ <search-cop @submit="funSubmit"> </search-cop>
|
|
|
+ <el-dialog v-model="wtDialog" draggable>
|
|
|
+ <template #title>
|
|
|
+ <div class="dialog-title">
|
|
|
+ <div class="title">风机功率点位</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-tabs v-model="wtTab" @tab-click="handleClick">
|
|
|
+ <el-tab-pane label="数据" name="table">
|
|
|
+ <el-table :data="wtData" row-key="id" :max-height="550">
|
|
|
+ <el-table-column property="wtId" align="center" label="风机" />
|
|
|
+ <el-table-column
|
|
|
+ property="time"
|
|
|
+ sortable
|
|
|
+ :width="160"
|
|
|
+ align="center"
|
|
|
+ label="时间"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="speed"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="风速(m/s)"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="power"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="功率(kW)"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="rr"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="转速"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="filter"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="是否有用点"
|
|
|
+ />
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="故障" name="problem">
|
|
|
+ <el-table :data="faultData" row-key="id" :max-height="550">
|
|
|
+ <el-table-column property="deviceId" align="center" label="风机" />
|
|
|
+ <el-table-column
|
|
|
+ property="ts"
|
|
|
+ sortable
|
|
|
+ :width="160"
|
|
|
+ align="center"
|
|
|
+ label="时间"
|
|
|
+ >
|
|
|
+ <template v-slot="scope">
|
|
|
+ {{ new Date(scope.row.ts).formatDate("yyyy-MM-dd hh:mm:ss") }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ property="characteristic"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="特性"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="components"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="部件"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="description"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="描述"
|
|
|
+ />
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="预警" name="warning">
|
|
|
+ <el-table :data="warnData" row-key="id" :max-height="550">
|
|
|
+ <el-table-column property="deviceId" align="center" label="风机" />
|
|
|
+ <el-table-column
|
|
|
+ property="ts"
|
|
|
+ sortable
|
|
|
+ :width="160"
|
|
|
+ align="center"
|
|
|
+ label="时间"
|
|
|
+ >
|
|
|
+ <template v-slot="scope">
|
|
|
+ {{ new Date(scope.row.ts).formatDate("yyyy-MM-dd hh:mm:ss") }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ property="characteristic"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="特性"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="components"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="部件"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ property="description"
|
|
|
+ sortable
|
|
|
+ align="center"
|
|
|
+ label="描述"
|
|
|
+ />
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-dialog>
|
|
|
+ <div class="power-data-wrapper card-shadow wrapper">
|
|
|
+ <div class="card-title">数据展示</div>
|
|
|
+ <div class="data-wrapper">
|
|
|
+ <div class="data-left-wrapper">
|
|
|
+ <tree-cop
|
|
|
+ class="tree-height"
|
|
|
+ :data="treeData"
|
|
|
+ @checkChange="funTreeCheckChange"
|
|
|
+ :show-checkbox="true"
|
|
|
+ @currentChange="funCurrentChange"
|
|
|
+ @refresh="funGetTree"
|
|
|
+ />
|
|
|
+ <tree-cop
|
|
|
+ class="tree-height"
|
|
|
+ :dropdownMenu="['export', 'delete', 'save']"
|
|
|
+ :data="processTreeData"
|
|
|
+ @currentChange="funProcessCurrentChange"
|
|
|
+ @refresh="funGetProcessTree"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="data-excel-wrapper">
|
|
|
+ <excel-cop
|
|
|
+ class="excel-height"
|
|
|
+ :checkIds="excelCheckIds"
|
|
|
+ :showCheckbox="excelCheckboxShow"
|
|
|
+ :data="excelList"
|
|
|
+ @excelChange="funExcelChange"
|
|
|
+ @checkChange="funExcelCheckChange"
|
|
|
+ />
|
|
|
+ <excel-cop
|
|
|
+ :currentIds="currentId"
|
|
|
+ class="excel-height"
|
|
|
+ :data="excelFitList"
|
|
|
+ @excelChange="funExcelChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="data-table-wrapper card-shadow">
|
|
|
+ <SubmitBtn
|
|
|
+ class="submit-btn"
|
|
|
+ desc="区域划分"
|
|
|
+ v-if="activeTab === '2' && excelType === 'fitting'"
|
|
|
+ @click="funChartArea"
|
|
|
+ ></SubmitBtn>
|
|
|
+
|
|
|
+ <el-tabs v-model="activeTab" class="data-table-tabs">
|
|
|
+ <el-tab-pane label="表格数据" name="1"> </el-tab-pane>
|
|
|
+ <el-tab-pane
|
|
|
+ label="图表展示"
|
|
|
+ name="2"
|
|
|
+ v-if="excelType === 'fitting'"
|
|
|
+ >
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <table-cop
|
|
|
+ v-show="activeTab === '1'"
|
|
|
+ :showShadow="false"
|
|
|
+ :data="tableData"
|
|
|
+ :loading="tableLoading"
|
|
|
+ :column="tableColumn"
|
|
|
+ :tableId="tableShowId"
|
|
|
+ :tableName="tableName"
|
|
|
+ />
|
|
|
+ <div v-show="activeTab === '2'" class="data-chart-wrapper">
|
|
|
+ <CurrentScatterChart
|
|
|
+ ref="chartRef"
|
|
|
+ width="100%"
|
|
|
+ height="100%"
|
|
|
+ :chartTitle="
|
|
|
+ avgObj.title +
|
|
|
+ ' ' +
|
|
|
+ '平均Cp值:' +
|
|
|
+ avgObj.cpavg +
|
|
|
+ '; 静风频率:' +
|
|
|
+ avgObj.frequency +
|
|
|
+ '%; 曲线偏差率:' +
|
|
|
+ avgObj.pcratio +
|
|
|
+ '%'
|
|
|
+ "
|
|
|
+ :xAxisData="xAxisData"
|
|
|
+ :yAxisData="{ splitLine: { show: false } }"
|
|
|
+ :seriesData="seriesData"
|
|
|
+ :showLegend="true"
|
|
|
+ :brushSelected="!isChartArea"
|
|
|
+ :dataSet="dataSet"
|
|
|
+ @getSelected="funChartSelect"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-tabs>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style lang="less" scoped>
|
|
|
+.el-tabs ::v-deep {
|
|
|
+ height: calc(100% - 22px);
|
|
|
+ .el-tabs__item {
|
|
|
+ color: #b3b3b3;
|
|
|
+ padding: 0 12px;
|
|
|
+ }
|
|
|
+ .el-tabs__nav-wrap::after {
|
|
|
+ background-color: #14221f;
|
|
|
+ }
|
|
|
+ .el-tabs__active-bar {
|
|
|
+ background-color: #05bb4c;
|
|
|
+ }
|
|
|
+ .el-tabs__item.is-active,
|
|
|
+ .el-tabs__item:hover {
|
|
|
+ color: #05bb4c;
|
|
|
+ }
|
|
|
+ .el-tabs__content {
|
|
|
+ height: calc(100% - 45px);
|
|
|
+ .table-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .data-chart-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|