123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810 |
- <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>
|