修改生产模块页面,增加顶部标签,新建分包pages-production,将生产页面移动至分包下面。
下一步制作曲线页面,统计页面,继续做好设备,安防等页面。
This commit is contained in:
parent
adcdb86db7
commit
6bac6dc89d
@ -17,8 +17,8 @@ export default defineManifestConfig({
|
|||||||
name: VITE_APP_TITLE,
|
name: VITE_APP_TITLE,
|
||||||
appid: VITE_UNI_APPID,
|
appid: VITE_UNI_APPID,
|
||||||
description: '',
|
description: '',
|
||||||
versionName: '2.2.0',
|
versionName: '2.3.0',
|
||||||
versionCode: '20250903',
|
versionCode: '202509011',
|
||||||
transformPx: false,
|
transformPx: false,
|
||||||
locale: VITE_FALLBACK_LOCALE, // 'zh-Hans'
|
locale: VITE_FALLBACK_LOCALE, // 'zh-Hans'
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
@ -77,7 +77,7 @@ export default defineManifestConfig({
|
|||||||
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
|
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
|
||||||
],
|
],
|
||||||
// app外连接访问 by 闵
|
// app外连接访问 by 闵
|
||||||
schemes : "szcxapp"
|
schemes: "szcxapp"
|
||||||
},
|
},
|
||||||
/* ios打包配置 */
|
/* ios打包配置 */
|
||||||
ios: {},
|
ios: {},
|
||||||
|
@ -49,3 +49,11 @@ export function queryJldDataByZc(params : object) { // 获取站场计量点实
|
|||||||
data: params
|
data: params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function queryJldDataByJldID(params : object) { // 获取计量点五分钟实时采集的历史数据
|
||||||
|
return http({
|
||||||
|
url: 'http://10.75.166.6:9999/Gyk/jldls/cxcSssjLssjJldls/getLssjByJldId',
|
||||||
|
method: 'GET',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
@ -2,8 +2,8 @@
|
|||||||
"name": "数智产销",
|
"name": "数智产销",
|
||||||
"appid": "__UNI__9F097F0",
|
"appid": "__UNI__9F097F0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"versionName": "2.2.0",
|
"versionName": "2.3.0",
|
||||||
"versionCode": "20250903",
|
"versionCode": "202509011",
|
||||||
"transformPx": false,
|
"transformPx": false,
|
||||||
"app-plus": {
|
"app-plus": {
|
||||||
"usingComponents": true,
|
"usingComponents": true,
|
||||||
|
274
src/pages-production/ribaoshuju/rbsjLsxq.vue
Normal file
274
src/pages-production/ribaoshuju/rbsjLsxq.vue
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'default',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '历史数据',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
<template>
|
||||||
|
<PageLayout navTitle="历史数据">
|
||||||
|
<view class="stats-container">
|
||||||
|
<uni-title v-if="type === 'trq'" :title="name.unit + '天然气---单位(万方)'" color="blue" type="h2"></uni-title>
|
||||||
|
<uni-title v-if="type === 'yy'" :title="name.dw + '原油---单位(吨)'" color="blue" type="h2"></uni-title>
|
||||||
|
</view>
|
||||||
|
<view class="dateSelect">
|
||||||
|
<cxc-szcx-dateRangeSelect :mode="'range'" v-model="dateRange"></cxc-szcx-dateRangeSelect>
|
||||||
|
</view>
|
||||||
|
<cxc-szcx-lineChart v-if="type === 'trq'" :dataList="dataList" x-field="rqDate" y-field="rq" legend-field="unit"
|
||||||
|
:reference-value="0"></cxc-szcx-lineChart>
|
||||||
|
|
||||||
|
<cxc-szcx-lineChart v-if="type === 'yy'" :dataList="dataList" x-field="scrq" y-field="rcwy" legend-field="dw"
|
||||||
|
:reference-value="0"></cxc-szcx-lineChart>
|
||||||
|
<view style="margin: 0 15px">
|
||||||
|
<view class="stats-container">
|
||||||
|
<view class="stats-item">最大值: {{ dataStats.max }}</view>
|
||||||
|
<view class="stats-item">最小值: {{ dataStats.min }}</view>
|
||||||
|
<view class="stats-item">平均值: {{ dataStats.average }}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<wd-table :data="dataList" :height="800" v-if="type === 'trq'" :index="true">
|
||||||
|
<wd-table-col prop="unit" label="名称" :width="screenWidth / 3" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="rqDate" label="日期" :width="screenWidth / 4" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="rq" label="日气量" :width="screenWidth / 5" align="center"></wd-table-col>
|
||||||
|
</wd-table>
|
||||||
|
|
||||||
|
<wd-table :data="dataList" :height="800" v-if="type === 'yy'" :index="true">
|
||||||
|
<wd-table-col prop="dw" label="名称" :width="screenWidth / 3" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="scrq" label="日期" :width="screenWidth / 4" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="rcwy" label="日油量" :width="screenWidth / 5" align="center"></wd-table-col>
|
||||||
|
</wd-table>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</PageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
queryJinriShengchansj,
|
||||||
|
queryJinriYuanyouShengchansj
|
||||||
|
} from '@/api/production';
|
||||||
|
import {
|
||||||
|
formatDate,
|
||||||
|
getDateAfterDays,
|
||||||
|
getDateAfterMonths
|
||||||
|
} from '@/utils/dateTime';
|
||||||
|
const name = ref({});
|
||||||
|
const type = ref('');
|
||||||
|
const dateRange = ref([]);
|
||||||
|
const dataList = ref([]);
|
||||||
|
const endDate = ref('');
|
||||||
|
const startDate = ref('');
|
||||||
|
const dataStats = ref({
|
||||||
|
min: 0,
|
||||||
|
max: 0,
|
||||||
|
avg: 0
|
||||||
|
});
|
||||||
|
const screenWidth = ref(0)
|
||||||
|
const calculateTableHeight = () => {
|
||||||
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
screenWidth.value = systemInfo.screenWidth;
|
||||||
|
}
|
||||||
|
const getJinriShengchansj = (tempDateRange) => {
|
||||||
|
// console.log(tempDateRange);
|
||||||
|
// 添加日期有效性检查
|
||||||
|
if (!tempDateRange || tempDateRange.some((date) => !convertToDate(date))) {
|
||||||
|
console.error('收到无效日期范围:', tempDateRange);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let queryParms = {};
|
||||||
|
dataList.value = [];
|
||||||
|
queryParms.gas = name.value.gas;
|
||||||
|
queryParms.unit = name.value.unit;
|
||||||
|
queryParms.rqDate_begin = formatDate(tempDateRange[0]);
|
||||||
|
queryParms.rqDate_end = formatDate(tempDateRange[1]);
|
||||||
|
queryParms.pageSize = 500;
|
||||||
|
|
||||||
|
// 添加参数有效性检查
|
||||||
|
if (!queryParms.rqDate_begin || !queryParms.rqDate_end) {
|
||||||
|
console.error('参数格式化失败:', queryParms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// console.log(queryParms);
|
||||||
|
queryJinriShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
// console.log(res);
|
||||||
|
dataList.value = res.result.records;
|
||||||
|
dataStats.value = calculateStats(dataList.value, 'rq');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getJinriYuanyouShengchansj = (tempDateRange) => {
|
||||||
|
console.log(tempDateRange);
|
||||||
|
// 添加日期有效性检查
|
||||||
|
if (!tempDateRange || tempDateRange.some((date) => !convertToDate(date))) {
|
||||||
|
console.error('收到无效日期范围:', tempDateRange);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let queryParms = {};
|
||||||
|
dataList.value = [];
|
||||||
|
queryParms.dw = name.value.dw;
|
||||||
|
queryParms.scrq_begin = formatDate(tempDateRange[0]);
|
||||||
|
queryParms.scrq_end = formatDate(tempDateRange[1]);
|
||||||
|
queryParms.pageSize = 500;
|
||||||
|
|
||||||
|
// 添加参数有效性检查
|
||||||
|
if (!queryParms.scrq_begin || !queryParms.scrq_end) {
|
||||||
|
console.error('参数格式化失败:', queryParms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(queryParms);
|
||||||
|
queryJinriYuanyouShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
console.log(res);
|
||||||
|
dataList.value = res.result.records;
|
||||||
|
dataStats.value = calculateStats(dataList.value, 'rcwy').reverse();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function calculateStats(data, field) {
|
||||||
|
// 过滤掉 field 字段值为 null 或 undefined 的数据
|
||||||
|
const validData = data.filter((item) => item[field] !== null && item[field] !== undefined);
|
||||||
|
if (validData.length === 0) {
|
||||||
|
return {
|
||||||
|
max: null,
|
||||||
|
min: null,
|
||||||
|
average: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 初始化最大值、最小值和总和
|
||||||
|
let max = validData[0][field];
|
||||||
|
let min = validData[0][field];
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
// 遍历有效数据
|
||||||
|
for (let i = 0; i < validData.length; i++) {
|
||||||
|
const value = validData[i][field];
|
||||||
|
// 更新最大值
|
||||||
|
if (value > max) {
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
// 更新最小值
|
||||||
|
if (value < min) {
|
||||||
|
min = value;
|
||||||
|
}
|
||||||
|
// 累加值到总和
|
||||||
|
sum += value;
|
||||||
|
}
|
||||||
|
// 计算平均值
|
||||||
|
const average = (sum / validData.length).toFixed(4);
|
||||||
|
|
||||||
|
return {
|
||||||
|
max: max,
|
||||||
|
min: min,
|
||||||
|
average: average
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToDate(str) {
|
||||||
|
try {
|
||||||
|
const date = new Date(str);
|
||||||
|
// 判断日期是否有效
|
||||||
|
if (isNaN(date.getTime())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
//TODO handle the exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 修改后(正确)
|
||||||
|
watch(
|
||||||
|
[() => type.value, dateRange], // 监听 type 和 dateRange
|
||||||
|
([newType, newDateRange]) => {
|
||||||
|
if (!newDateRange || !convertToDate(newDateRange[0]) || !convertToDate(newDateRange[1])) {
|
||||||
|
// console.error('无效的日期范围:', newDateRange);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// console.log(newType, newDateRange);
|
||||||
|
|
||||||
|
switch (
|
||||||
|
newType // 直接使用 newType
|
||||||
|
) {
|
||||||
|
case 'trq':
|
||||||
|
getJinriShengchansj(newDateRange);
|
||||||
|
break;
|
||||||
|
case 'yy':
|
||||||
|
getJinriYuanyouShengchansj(newDateRange);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn('未知类型:', newType);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
onMounted(() => {
|
||||||
|
// nextTick();
|
||||||
|
// getJinriShengchansj(dateRange.value);
|
||||||
|
calculateTableHeight();
|
||||||
|
// 监听屏幕旋转变化
|
||||||
|
uni.onWindowResize(() => {
|
||||||
|
calculateTableHeight();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
name.value = JSON.parse(options.data);
|
||||||
|
type.value = options.type;
|
||||||
|
// console.log(name.value, type.value);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
if (now.getHours() < 11) {
|
||||||
|
endDate.value = getDateAfterDays(now, -1); //11点之前 头一天的数据
|
||||||
|
startDate.value = getDateAfterMonths(endDate.value, -1); //11点之前 头一天的数据
|
||||||
|
} else {
|
||||||
|
endDate.value = now;
|
||||||
|
startDate.value = getDateAfterMonths(endDate.value, -1); //11点之前 头一天的数据
|
||||||
|
}
|
||||||
|
dateRange.value = [startDate.value, endDate.value];
|
||||||
|
// console.log(1111, dateRange.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.stats-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 15 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dateSelect {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 5px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-item {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #00aa00;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-item+.stats-item {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
633
src/pages-production/ribaoshuju/trqRbsj.vue
Normal file
633
src/pages-production/ribaoshuju/trqRbsj.vue
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<!-- 标题行 -->
|
||||||
|
<view class="header-row">
|
||||||
|
<view class="title">天然气产量</view>
|
||||||
|
<view class="more" @click="selectMore">更多>></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="container">
|
||||||
|
<view v-for="(item, index) in shishiArrSelect" :key="index" class="card-item"
|
||||||
|
@click="handleCardClick(item.gas)">
|
||||||
|
<view class="card">
|
||||||
|
<text class="title">{{ item.gas }}</text>
|
||||||
|
<view class="content">
|
||||||
|
<text class="label">气量</text>
|
||||||
|
<text class="value">{{ formatNumber(item.dailyVolume) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<text class="label">年累计</text>
|
||||||
|
<text class="value">{{ formatNumber(item.yearVolume) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="progress-bar">
|
||||||
|
<!-- 动态设置宽度和颜色 -->
|
||||||
|
<view class="progress"
|
||||||
|
:style="{ width: `${Math.abs(item.yearPerCent)}%`, 'background-color': item.yearPerCent < 0 ? '#ff4444' : '#007aff' }">
|
||||||
|
</view>
|
||||||
|
<!-- 显示带符号的百分比 -->
|
||||||
|
<text v-if="!(item.yearPlan === '' || item.yearPlan === '0')"
|
||||||
|
class="progress-text">{{ item.yearPerCent }}%</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<wd-popup v-model="popupSelect" position="top" background-color="#fff">
|
||||||
|
<view style="margin-top: 50px">
|
||||||
|
<view class="titlepopup">选择显示更多生产数据</view>
|
||||||
|
|
||||||
|
<view class="popupBtn">
|
||||||
|
<button size="mini" @click="selectDefault" style="padding: 8px 16px;">默认</button>
|
||||||
|
<button size="mini" @click="selectAll" style="padding: 8px 16px;">全选</button>
|
||||||
|
<button size="mini" @click="selectNo" style="padding: 8px 16px;">全不选</button>
|
||||||
|
</view>
|
||||||
|
<view class="popupcheckbox">
|
||||||
|
<uni-data-checkbox style="font-size: 14px" @change="onselectionchange" :localdata="shishiArr"
|
||||||
|
v-model="shishiArrDisplay" multiple :map="{ value: 'gas', text: 'gas' }"></uni-data-checkbox>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
<!-- 数据弹窗 -->
|
||||||
|
<wd-popup v-model="popup" position="bottom" closable custom-style="height: 400px;" @close="handleClose">
|
||||||
|
<wd-cell-group :title="tableTitle">
|
||||||
|
<wd-table :data="filteredData" :height="800">
|
||||||
|
<wd-table-col prop="unit" label="名称" :width="screenWidth * 57 / 140 " align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="rq" label="日气量" :width="screenWidth / 5" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="yearVolume" label="年累计" :width="screenWidth / 4" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="" label="操作" :width="screenWidth / 7" align="center">
|
||||||
|
<template #value="{row}">
|
||||||
|
<text style="color: red;" @click="goHistory(row)">历史</text>
|
||||||
|
</template>
|
||||||
|
</wd-table-col>
|
||||||
|
</wd-table>
|
||||||
|
</wd-cell-group>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
queryJinriShengchansj,
|
||||||
|
queryYearShengchansj,
|
||||||
|
queryJinriTrqShengchansj
|
||||||
|
} from '@/api/production';
|
||||||
|
import {
|
||||||
|
formatDate,
|
||||||
|
getDateAfterDays
|
||||||
|
} from '@/utils/dateTime';
|
||||||
|
|
||||||
|
const shishiArr = ref([]);
|
||||||
|
const shishiArrSelect = ref([]);
|
||||||
|
const shishiArrDisplay = ref(['气井气', '商品量', '站线综合输差']);
|
||||||
|
const dataJinriUnit = ref([]);
|
||||||
|
const tableTitle = ref('')
|
||||||
|
const filteredData = ref([]);
|
||||||
|
const popup = ref(false);
|
||||||
|
const popupSelect = ref(false);
|
||||||
|
const strDate = ref('');
|
||||||
|
|
||||||
|
const dataJinri = ref([]);
|
||||||
|
const dataJinriSum = ref([]);
|
||||||
|
const dataJinriSumUnit = ref([]);
|
||||||
|
|
||||||
|
|
||||||
|
const qjqNdjs = ref(7500);
|
||||||
|
const splNdjs = ref(7220);
|
||||||
|
const zhqNdjs = ref(300);
|
||||||
|
const zhscNdjs = ref(50);
|
||||||
|
const screenWidth = ref(0)
|
||||||
|
const handleClose = () => {
|
||||||
|
popup.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击卡片处理
|
||||||
|
// const handleCardClick = (gas) => {
|
||||||
|
// let queryParms = {};
|
||||||
|
// filteredData.value = [];
|
||||||
|
// queryParms.day = strDate.value;
|
||||||
|
// queryParms.gas = gas;
|
||||||
|
// queryParms.unit = '文23气田,户部寨气田';
|
||||||
|
// console.log(queryParms);
|
||||||
|
// queryJinriTrqShengchansj(queryParms).then((res) => {
|
||||||
|
// if (res.success) {
|
||||||
|
// console.log(res);
|
||||||
|
// filteredData.value = res.result;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// popup.value.open();
|
||||||
|
// };
|
||||||
|
|
||||||
|
function selectMore() {
|
||||||
|
popupSelect.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectAll() {
|
||||||
|
shishiArrDisplay.value = [];
|
||||||
|
// console.log(9, shishiArr.value)
|
||||||
|
shishiArr.value.forEach((item) => {
|
||||||
|
// console.log(10, item)
|
||||||
|
shishiArrDisplay.value.push(item.gas);
|
||||||
|
});
|
||||||
|
onselectionchange()
|
||||||
|
popup.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectNo() {
|
||||||
|
shishiArrDisplay.value = [];
|
||||||
|
onselectionchange()
|
||||||
|
popup.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectDefault() {
|
||||||
|
shishiArrDisplay.value = ['气井气', '商品量', '站线综合输差'];
|
||||||
|
onselectionchange()
|
||||||
|
popup.value = false;
|
||||||
|
}
|
||||||
|
const onselectionchange = () => {
|
||||||
|
shishiArrSelect.value = [];
|
||||||
|
shishiArrDisplay.value.forEach((item) => {
|
||||||
|
shishiArrSelect.value.push(shishiArr.value.filter((item1) => item1.gas === item)[0]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCardClick = (gas) => {
|
||||||
|
tableTitle.value = gas + '数据详情 单位(万立方米)'
|
||||||
|
filteredData.value = dataJinriSumUnit.value.filter((item) => item.gas === gas);
|
||||||
|
filteredData.value = filteredData.value.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
rq: formatNumber(item.rq),
|
||||||
|
yearVolume: formatNumber(item.yearVolume)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
popup.value = true;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closePopup = () => {
|
||||||
|
popup.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateTableHeight = () => {
|
||||||
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
screenWidth.value = systemInfo.screenWidth;
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
getJinriTrqShengchansj();
|
||||||
|
getJinriShengchansj();
|
||||||
|
|
||||||
|
calculateTableHeight();
|
||||||
|
// 监听屏幕旋转变化
|
||||||
|
uni.onWindowResize(() => {
|
||||||
|
calculateTableHeight();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 数字格式化
|
||||||
|
const formatNumber = (num) => {
|
||||||
|
let temp = 0;
|
||||||
|
try {
|
||||||
|
temp = parseFloat(num);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO handle the exception
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp.toFixed(4).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自动计算综合输差
|
||||||
|
function calcZhsc(tempArray) {
|
||||||
|
let totalJinqi = {
|
||||||
|
gas: '总进气',
|
||||||
|
dailyVolume: 0,
|
||||||
|
yearVolume: 0,
|
||||||
|
yearPlan: '100',
|
||||||
|
yearPerCent: 0
|
||||||
|
};
|
||||||
|
let totalChuqi = {
|
||||||
|
gas: '总出气',
|
||||||
|
dailyVolume: 0,
|
||||||
|
yearVolume: 0,
|
||||||
|
yearPlan: '100',
|
||||||
|
yearPerCent: 0
|
||||||
|
};
|
||||||
|
const compositeZx = {
|
||||||
|
gas: '站线综合输差',
|
||||||
|
dailyVolume: 0,
|
||||||
|
yearVolume: 0,
|
||||||
|
yearPlan: '100',
|
||||||
|
yearPerCent: 0
|
||||||
|
}; // 综合输差
|
||||||
|
const compositeJc = {
|
||||||
|
gas: '进出综合输差',
|
||||||
|
dailyVolume: 0,
|
||||||
|
yearVolume: 0,
|
||||||
|
yearPlan: '100',
|
||||||
|
yearPerCent: 0
|
||||||
|
};
|
||||||
|
const trqSpl = {
|
||||||
|
gas: '商品量',
|
||||||
|
dailyVolume: 0,
|
||||||
|
yearVolume: 0,
|
||||||
|
yearPlan: '7220',
|
||||||
|
yearPerCent: 0
|
||||||
|
};
|
||||||
|
// 综合输差
|
||||||
|
tempArray.forEach((item) => {
|
||||||
|
if (item.gas === '站输差' || item.gas === '线输差') {
|
||||||
|
compositeZx.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||||
|
compositeZx.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||||
|
}
|
||||||
|
if (item.gas === '气井气' || item.gas === '外部气' || item.gas === '返回气') {
|
||||||
|
totalJinqi.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||||
|
totalJinqi.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||||
|
}
|
||||||
|
if (item.gas === '自耗气' || item.gas === '用户气' || item.gas === '返采油厂干气') {
|
||||||
|
totalChuqi.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||||
|
totalChuqi.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||||
|
}
|
||||||
|
if (item.gas === '气井气' || item.gas === '站输差' || item.gas === '线输差') {
|
||||||
|
trqSpl.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||||
|
trqSpl.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||||
|
}
|
||||||
|
if (item.gas === '自耗气') {
|
||||||
|
trqSpl.dailyVolume -= parseFloat(item.dailyVolume) || 0;
|
||||||
|
trqSpl.yearVolume -= parseFloat(item.yearVolume) || 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
compositeZx.yearPerCent = calcPercent(compositeZx.yearPlan, compositeZx.yearVolume);
|
||||||
|
|
||||||
|
trqSpl.yearPerCent = calcPercent(trqSpl.yearPlan, trqSpl.yearVolume);
|
||||||
|
|
||||||
|
compositeJc.dailyVolume = (-totalJinqi.dailyVolume + totalChuqi.dailyVolume).toFixed(4);
|
||||||
|
compositeJc.yearVolume = (-totalJinqi.yearVolume + totalChuqi.yearVolume).toFixed(4);
|
||||||
|
compositeJc.yearPerCent = calcPercent(compositeJc.yearPlan, compositeJc.yearVolume);
|
||||||
|
|
||||||
|
tempArray.push(compositeZx);
|
||||||
|
tempArray.push(trqSpl);
|
||||||
|
|
||||||
|
return tempArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getJinriTrqShengchansj = () => {
|
||||||
|
const now = new Date();
|
||||||
|
if (now.getHours() < 11) {
|
||||||
|
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||||
|
} else {
|
||||||
|
strDate.value = formatDate(now).toString();
|
||||||
|
}
|
||||||
|
let queryParms = {};
|
||||||
|
shishiArr.value = [];
|
||||||
|
queryParms.day = strDate.value;
|
||||||
|
queryJinriTrqShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
console.log(1, res);
|
||||||
|
let temp = res.result;
|
||||||
|
|
||||||
|
temp.forEach((item) => {
|
||||||
|
if (item.gas === '气井气') {
|
||||||
|
item.yearPlan = 7500;
|
||||||
|
item.yearPerCent = calcPercent(item.yearPlan, item.yearVolume);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
shishiArr.value = calcZhsc(temp);
|
||||||
|
nextTick();
|
||||||
|
onselectionchange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function goHistory(val) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/production/ribaoshuju/rbsjLsxq?data=' + JSON.stringify(val) + '&type=trq'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcPercent(yearJihua, yearShiji) {
|
||||||
|
// 计算进度百分比,避免除数为 0
|
||||||
|
// 确保进度百分比不超过 100
|
||||||
|
let plan = parseFloat(yearJihua === '' ? 0 : yearJihua);
|
||||||
|
let shiji = parseFloat(yearShiji);
|
||||||
|
let percent = 0;
|
||||||
|
// 修改原始计算代码
|
||||||
|
if (plan > 0) {
|
||||||
|
percent = (shiji / plan) * 100;
|
||||||
|
percent = Math.min(percent, 100); // 限制最大100%
|
||||||
|
}
|
||||||
|
return parseFloat(percent.toFixed(2)); // 转为数值
|
||||||
|
}
|
||||||
|
|
||||||
|
const getJinriShengchansj = () => {
|
||||||
|
const now = new Date();
|
||||||
|
if (now.getHours() < 11) {
|
||||||
|
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||||
|
} else {
|
||||||
|
strDate.value = formatDate(now).toString();
|
||||||
|
}
|
||||||
|
let queryParms = {};
|
||||||
|
dataJinri.value = [];
|
||||||
|
dataJinriSum.value = [];
|
||||||
|
dataJinriSumUnit.value = [];
|
||||||
|
queryParms.rqDate = strDate.value;
|
||||||
|
queryParms.pageSize = 100;
|
||||||
|
queryJinriShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
dataJinri.value = res.result.records;
|
||||||
|
dataJinriSumUnit.value = sumByUnit(dataJinri.value); //包含gas unit rq cq totalGas
|
||||||
|
// // 使用 nextTick 等待 DOM 更新
|
||||||
|
nextTick();
|
||||||
|
getYearShengchansj(); //再获取今年以来的数据
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getYearShengchansj = () => {
|
||||||
|
const now = new Date();
|
||||||
|
let year = formatDate(now).split('-')[0];
|
||||||
|
let queryParms = {};
|
||||||
|
queryParms.yearStart = year;
|
||||||
|
queryParms.yearEnd = year;
|
||||||
|
queryYearShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
try {
|
||||||
|
let yearData = res.result[year];
|
||||||
|
dataJinriSumUnit.value.forEach((item) => {
|
||||||
|
yearData.forEach((itemYear) => {
|
||||||
|
// // console.log(item, itemYear);
|
||||||
|
if (item.setId === itemYear.setId) {
|
||||||
|
item.yearVolume = itemYear.yearSum || 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
dataJinriSum.value = sumByGas(dataJinriSumUnit.value);
|
||||||
|
shishiArr.value.forEach((item) => {
|
||||||
|
dataJinriSum.value.forEach((itemjinri) => {
|
||||||
|
if (item.gas === itemjinri.gas) {
|
||||||
|
item.dailyVolume = itemjinri.rq.toFixed(4);
|
||||||
|
item.yearVolume = itemjinri.yearVolume.toFixed(4);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function sumByGas(records) {
|
||||||
|
const summaryMap = {};
|
||||||
|
try {
|
||||||
|
records.forEach((record) => {
|
||||||
|
const gas = record.gas;
|
||||||
|
if (!summaryMap[gas]) {
|
||||||
|
// 初始化该 gas 类型的汇总对象
|
||||||
|
summaryMap[gas] = {
|
||||||
|
gas: gas,
|
||||||
|
rq: 0,
|
||||||
|
sq: 0,
|
||||||
|
totalGas: 0,
|
||||||
|
yearVolume: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 无论是否是第一次遇到该 gas 类型,都进行累加操作
|
||||||
|
summaryMap[gas].rq += record.rq || 0;
|
||||||
|
summaryMap[gas].sq += record.sq || 0;
|
||||||
|
summaryMap[gas].totalGas += record.totalGas || 0;
|
||||||
|
summaryMap[gas].yearVolume += record.yearVolume || 0;
|
||||||
|
});
|
||||||
|
return Object.values(summaryMap);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO handle the exception
|
||||||
|
// console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sumByUnit(records) {
|
||||||
|
console.log(records);
|
||||||
|
const summaryMap = {};
|
||||||
|
try {
|
||||||
|
records.forEach((record) => {
|
||||||
|
const unit = record.unit;
|
||||||
|
const gas = record.gas;
|
||||||
|
// 添加setId计算
|
||||||
|
const setId = record.setId
|
||||||
|
if (gas != "区输差") {
|
||||||
|
if (!summaryMap[setId]) {
|
||||||
|
// 初始化该 gas 类型的汇总对象
|
||||||
|
summaryMap[setId] = {
|
||||||
|
unit: unit,
|
||||||
|
setId: setId,
|
||||||
|
gas: record.gas,
|
||||||
|
rq: 0,
|
||||||
|
sq: 0,
|
||||||
|
totalGas: 0,
|
||||||
|
yearVolume: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 无论是否是第一次遇到该 unit 类型,都进行累加操作
|
||||||
|
summaryMap[setId].rq += record.rq || 0;
|
||||||
|
summaryMap[setId].sq += record.sq || 0;
|
||||||
|
summaryMap[setId].totalGas += record.totalGas || 0;
|
||||||
|
summaryMap[setId].yearVolume += record.yearVolume || 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.values(summaryMap);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO handle the exception
|
||||||
|
// console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10 10rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlepopup {
|
||||||
|
font-size: 35rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 给包裹按钮的容器设置样式 */
|
||||||
|
.popupBtn {
|
||||||
|
display: grid;
|
||||||
|
/* 创建三个等宽的列 */
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
/* 设置列与列之间的间距 */
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 添加按钮按下效果 */
|
||||||
|
.popupBtn button:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scale(0.98);
|
||||||
|
transition: all 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 给按钮设置通用样式 */
|
||||||
|
.popupBtn button {
|
||||||
|
border: none;
|
||||||
|
padding: 0px 10px;
|
||||||
|
background-color: #007BFF;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 鼠标悬停在按钮上时的样式 */
|
||||||
|
.popupBtn button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more::after {
|
||||||
|
content: '';
|
||||||
|
width: 8rpx;
|
||||||
|
height: 8rpx;
|
||||||
|
border-top: 2rpx solid #666;
|
||||||
|
border-right: 2rpx solid #666;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
margin-left: 8rpx;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 鼠标悬停效果 */
|
||||||
|
.more:hover {
|
||||||
|
color: #007aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popupcheckbox {
|
||||||
|
/* 使用 Flexbox 布局 */
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
/* 允许换行 */
|
||||||
|
gap: 2px;
|
||||||
|
/* 设置复选框之间的间距 */
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.popupcheckbox .uni-data-checkbox__item {
|
||||||
|
flex-basis: calc((100% / var(4)) - 10px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 20rpx;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
padding: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #888;
|
||||||
|
font-size: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-item {
|
||||||
|
flex: 1 1 200rpx; // 基础宽度300rpx,自动伸缩 formatNumber
|
||||||
|
min-width: 240rpx;
|
||||||
|
max-width: calc(50% - 10rpx); // 最大不超过容器一半(考虑间距)
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
max-width: calc(33.33% - 14rpx); // 大屏显示3列
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #ececec;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 15rpx;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(179, 179, 179, 0.1);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #0000ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
position: relative;
|
||||||
|
height: 20px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
// color: red;
|
||||||
|
/* 保持红色 */
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
/* 提升可读性 */
|
||||||
|
}
|
||||||
|
</style>
|
317
src/pages-production/ribaoshuju/yyRbsj.vue
Normal file
317
src/pages-production/ribaoshuju/yyRbsj.vue
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
<template>
|
||||||
|
<!-- <view style="margin-left: 20rpx;"> <uni-title :title="strDate + ':生产数据'" type="h1" color="red" /> -->
|
||||||
|
<!-- </view> -->
|
||||||
|
<view class="content">
|
||||||
|
<!-- 标题行 -->
|
||||||
|
<view class="header-row">
|
||||||
|
<view class="title">原油产量</view>
|
||||||
|
<view class="more"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="container">
|
||||||
|
<view v-for="(item, index) in shishiArr" :key="index" class="card-item" @click="handleCardClick(item.gas)">
|
||||||
|
<view class="card">
|
||||||
|
<!-- <text class="title">{{ item.gas }}</text> -->
|
||||||
|
<view class="content">
|
||||||
|
<text class="label">日油量</text>
|
||||||
|
<text class="value">{{ item.rcwy || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<text class="label">月累计</text>
|
||||||
|
<text class="value">{{ item.yl || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<text class="label">年累计</text>
|
||||||
|
<text class="value">{{ item.nl || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="progress-bar">
|
||||||
|
<!-- 动态设置宽度和颜色 -->
|
||||||
|
<view class="progress" :style="{
|
||||||
|
width: `${Math.abs(item.yearPerCent)}%`,
|
||||||
|
'background-color': item.yearPerCent < 0 ? '#ff4444' : '#007aff'
|
||||||
|
}"></view>
|
||||||
|
<!-- 显示带符号的百分比 -->
|
||||||
|
<text v-if="!(item.yearPlan === '' || item.yearPlan === '0')"
|
||||||
|
class="progress-text">{{ item.yearPerCent }}%</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 数据弹窗 -->
|
||||||
|
<wd-popup v-model="popup" position="bottom" closable custom-style="height: 400px;" @close="handleClose">
|
||||||
|
<wd-cell-group title="原油数据详情 单位(吨)">
|
||||||
|
<wd-table :data="dataJinri" :height="800">
|
||||||
|
<wd-table-col prop="dw" label="名称" :width="screenWidth * 29 / 140" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="rcwy" label="日油量" :width="screenWidth / 5" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="yl" label="月累计" :width="screenWidth / 5" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="nl" label="年累计" :width="screenWidth / 4" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="" label="操作" :width="screenWidth / 7" align="center">
|
||||||
|
<template #value="{row}">
|
||||||
|
<text style="color: red;" @click="goHistory(row)">历史</text>
|
||||||
|
</template>
|
||||||
|
</wd-table-col>
|
||||||
|
</wd-table>
|
||||||
|
</wd-cell-group>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
queryJinriYuanyouShengchansj
|
||||||
|
} from '@/api/production';
|
||||||
|
import {
|
||||||
|
formatDate,
|
||||||
|
getDateAfterDays
|
||||||
|
} from '@/utils/dateTime';
|
||||||
|
const shishiArr = ref([{
|
||||||
|
gas: '原油产量',
|
||||||
|
rcwy: '',
|
||||||
|
yl: '',
|
||||||
|
nl: '',
|
||||||
|
yearPlan: '1500',
|
||||||
|
yearPerCent: ''
|
||||||
|
}]);
|
||||||
|
const screenWidth = ref(0)
|
||||||
|
const dataJinri = ref([]);
|
||||||
|
const dataJinriSum = ref([]);
|
||||||
|
const popup = ref(false);
|
||||||
|
// 点击卡片处理
|
||||||
|
const handleCardClick = () => {
|
||||||
|
popup.value = true
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closePopup = () => {
|
||||||
|
popup.value = false
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
getJinriYuanyouShengchansj();
|
||||||
|
// getYearShengchansj();
|
||||||
|
calculateTableHeight();
|
||||||
|
// 监听屏幕旋转变化
|
||||||
|
uni.onWindowResize(() => {
|
||||||
|
calculateTableHeight();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const strDate = ref('');
|
||||||
|
// 数字格式化
|
||||||
|
const formatNumber = (num) => {
|
||||||
|
if (typeof num !== 'number') return '-';
|
||||||
|
return num.toFixed(4).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
const handleClose = () => {
|
||||||
|
popup.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function goHistory(val) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/production/ribaoshuju/rbsjLsxq?data=' + JSON.stringify(val) + '&type=yy'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const calculateTableHeight = () => {
|
||||||
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
screenWidth.value = systemInfo.screenWidth;
|
||||||
|
}
|
||||||
|
const getJinriYuanyouShengchansj = () => {
|
||||||
|
const now = new Date();
|
||||||
|
if (now.getHours() < 11) {
|
||||||
|
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||||
|
} else {
|
||||||
|
strDate.value = formatDate(now).toString();
|
||||||
|
}
|
||||||
|
let queryParms = {};
|
||||||
|
dataJinri.value = [];
|
||||||
|
dataJinriSum.value = [];
|
||||||
|
queryParms.scrq = strDate.value;
|
||||||
|
queryParms.pageSize = 100;
|
||||||
|
queryJinriYuanyouShengchansj(queryParms).then((res) => {
|
||||||
|
if (res.success) {
|
||||||
|
dataJinri.value = res.result.records;
|
||||||
|
dataJinriSum.value = sumByOil(dataJinri.value); //包含gas unit rq cq totalGas
|
||||||
|
// // console.log(dataJinriSum.value);
|
||||||
|
nextTick();
|
||||||
|
shishiArr.value.forEach((item) => {
|
||||||
|
dataJinriSum.value.forEach((itemjinri) => {
|
||||||
|
item.rcwy = itemjinri.rcwy.toFixed(4);
|
||||||
|
item.nl = itemjinri.nl.toFixed(4);
|
||||||
|
item.yl = itemjinri.yl.toFixed(4);
|
||||||
|
item.yearPerCent = calcPercent(item.yearPlan, item.nl);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dataJinri.value = dataJinri.value.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
rcwy: formatNumber(item.rcwy),
|
||||||
|
yl: formatNumber(item.yl),
|
||||||
|
nl: formatNumber(item.nl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// getYearShengchansj(); //再获取今年以来的数据
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function calcPercent(yearJihua, yearShiji) {
|
||||||
|
// 计算进度百分比,避免除数为 0
|
||||||
|
// 确保进度百分比不超过 100
|
||||||
|
let plan = parseFloat(yearJihua === '' ? 0 : yearJihua);
|
||||||
|
let shiji = parseFloat(yearShiji);
|
||||||
|
let percent = 0;
|
||||||
|
// 修改原始计算代码
|
||||||
|
if (plan > 0) {
|
||||||
|
percent = (shiji / plan) * 100;
|
||||||
|
percent = Math.min(percent, 100); // 限制最大100%
|
||||||
|
}
|
||||||
|
return parseFloat(percent.toFixed(2)); // 转为数值
|
||||||
|
}
|
||||||
|
|
||||||
|
function sumByOil(records) {
|
||||||
|
// console.log(records);
|
||||||
|
const summaryMap = {};
|
||||||
|
try {
|
||||||
|
records.forEach((record) => {
|
||||||
|
const gas = record.gas;
|
||||||
|
if (!summaryMap[gas]) {
|
||||||
|
// 初始化该 gas 类型的汇总对象
|
||||||
|
summaryMap[gas] = {
|
||||||
|
rcwy: 0,
|
||||||
|
yl: 0,
|
||||||
|
nl: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 无论是否是第一次遇到该 gas 类型,都进行累加操作
|
||||||
|
summaryMap[gas].rcwy += record.rcwy || 0;
|
||||||
|
summaryMap[gas].yl += record.yl || 0;
|
||||||
|
summaryMap[gas].nl += record.nl || 0;
|
||||||
|
});
|
||||||
|
return Object.values(summaryMap);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO handle the exception
|
||||||
|
// console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15rpx 0;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more::after {
|
||||||
|
content: '';
|
||||||
|
width: 8rpx;
|
||||||
|
height: 8rpx;
|
||||||
|
border-top: 2rpx solid #666;
|
||||||
|
border-right: 2rpx solid #666;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
margin-left: 8rpx;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 鼠标悬停效果 */
|
||||||
|
.more:hover {
|
||||||
|
color: #007aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 20rpx;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-item {
|
||||||
|
flex: 1 1 200rpx; // 基础宽度300rpx,自动伸缩 selectedGas formatNumber
|
||||||
|
min-width: 200rpx;
|
||||||
|
max-width: calc(50% - 10rpx); // 最大不超过容器一半(考虑间距)
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
max-width: calc(33.33% - 14rpx); // 大屏显示3列
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #ececec;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 15rpx;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(197, 197, 197, 0.1);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #0000ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
position: relative;
|
||||||
|
height: 20px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: red;
|
||||||
|
/* 保持红色 */
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
/* 提升可读性 */
|
||||||
|
}
|
||||||
|
</style>
|
8
src/pages-production/shishishuju/aqbjSssj.vue
Normal file
8
src/pages-production/shishishuju/aqbjSssj.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
507
src/pages-production/shishishuju/chart/lssjChart.vue
Normal file
507
src/pages-production/shishishuju/chart/lssjChart.vue
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'default',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '历史数据图表',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageLayout navTitle="历史数据图表" backRouteName="index" routeMethod="pushTab">
|
||||||
|
<view class="chart-container">
|
||||||
|
<view class="chart-header">
|
||||||
|
<view class="chart-title-container">
|
||||||
|
<text class="chart-title">{{ chartTitle }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="filter-section">
|
||||||
|
<view class="date-picker">
|
||||||
|
<uni-datetime-picker type="datetimerange" v-model="lssjTimeRang" @change="getTime"
|
||||||
|
:placeholder="['开始时间', '结束时间']" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="checkbox-container">
|
||||||
|
<label class="checkbox">
|
||||||
|
<checkbox :checked="tableVisibled" @change="onChangeTable" />
|
||||||
|
<text>{{ checkBoxText }}</text>
|
||||||
|
</label>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图表容器 -->
|
||||||
|
<view id="myCharts" class="chart"></view>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<view v-if="tableVisibled" class="table-container">
|
||||||
|
<uni-table border stripe emptyText="暂无数据" :loading="loading">
|
||||||
|
<uni-tr>
|
||||||
|
<uni-th width="60" align="center">序号</uni-th>
|
||||||
|
<uni-th align="center">日期时间</uni-th>
|
||||||
|
<uni-th align="center">温度(℃)</uni-th>
|
||||||
|
<uni-th align="center">压力(MPa)</uni-th>
|
||||||
|
<uni-th align="center">压差(kPa)</uni-th>
|
||||||
|
<uni-th align="center">瞬时量(Nm³/d)</uni-th>
|
||||||
|
<uni-th align="center">今日量(m³)</uni-th>
|
||||||
|
<uni-th align="center">今日时间(分)</uni-th>
|
||||||
|
<uni-th align="center">仪表状态</uni-th>
|
||||||
|
</uni-tr>
|
||||||
|
<uni-tr v-for="(item, index) in dataSource" :key="index">
|
||||||
|
<uni-td align="center">{{ index + 1 }}</uni-td>
|
||||||
|
<uni-td align="center">{{ formatTableTime(item.createTime) }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.wd }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.yl }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.yc }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.ssll }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.jrl }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.jrsj }}</uni-td>
|
||||||
|
<uni-td align="center">{{ item.zt }}</uni-td>
|
||||||
|
</uni-tr>
|
||||||
|
</uni-table>
|
||||||
|
|
||||||
|
<view class="pagination">
|
||||||
|
<uni-pagination :current="ipagination.current" :pageSize="ipagination.pageSize"
|
||||||
|
:total="ipagination.total" @change="handlePageChange" showTotal />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</PageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
watch,
|
||||||
|
nextTick
|
||||||
|
} from 'vue'
|
||||||
|
import {
|
||||||
|
onLoad
|
||||||
|
} from '@dcloudio/uni-app'
|
||||||
|
import {
|
||||||
|
formatDate
|
||||||
|
} from '@/utils/dateTime.ts'
|
||||||
|
|
||||||
|
// 定义props
|
||||||
|
const props = defineProps({
|
||||||
|
lineData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 数据声明
|
||||||
|
const urljlByJldID = ref('https://szcx.zyyt.sinopec.com/Gyk/jldls/cxcSssjLssjJldls/getLssjByJldId')
|
||||||
|
|
||||||
|
|
||||||
|
const colorData = [{
|
||||||
|
color: '#000000'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#00007f'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#ff0000'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#005500'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#55007f'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#ffff00'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const option = ref({})
|
||||||
|
const legendData = ref([])
|
||||||
|
const xData = ref([])
|
||||||
|
const yaxis = ref({
|
||||||
|
type: 'value',
|
||||||
|
name: '',
|
||||||
|
min: 0,
|
||||||
|
max: 500,
|
||||||
|
position: 'left',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#61A0A8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const yAxis = ref([])
|
||||||
|
const series = ref([])
|
||||||
|
const serie = ref({
|
||||||
|
field: '',
|
||||||
|
name: '',
|
||||||
|
showSymbol: false,
|
||||||
|
type: 'line',
|
||||||
|
data: [],
|
||||||
|
yAxisIndex: 1,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#61A0A8',
|
||||||
|
width: 1
|
||||||
|
},
|
||||||
|
connectNulls: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const tableVisibled = ref(false)
|
||||||
|
const checkBoxText = ref('显示历史报表')
|
||||||
|
const dataSource = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const ipagination = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const jldID = ref('')
|
||||||
|
const jldName = ref('')
|
||||||
|
const chartTitle = ref('')
|
||||||
|
const lineName = ref([])
|
||||||
|
const startTime = ref('')
|
||||||
|
const endTime = ref('')
|
||||||
|
const lssjTimeRang = ref([])
|
||||||
|
const myCharts = ref(null)
|
||||||
|
|
||||||
|
// 获取当前日期时间范围
|
||||||
|
const getDefaultTimeRange = () => {
|
||||||
|
const now = new Date()
|
||||||
|
const start = new Date(now)
|
||||||
|
start.setHours(8, 0, 0, 0)
|
||||||
|
|
||||||
|
const end = new Date(now)
|
||||||
|
end.setDate(end.getDate() + 1)
|
||||||
|
end.setHours(7, 59, 59, 0)
|
||||||
|
|
||||||
|
return [start.getTime(), end.getTime()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = () => {
|
||||||
|
series.value = []
|
||||||
|
yAxis.value = []
|
||||||
|
xData.value = []
|
||||||
|
let positionIndex = 0
|
||||||
|
|
||||||
|
for (let i = 0; i < lineName.value.length; i++) {
|
||||||
|
const yaxisTemp = JSON.parse(JSON.stringify(yaxis.value))
|
||||||
|
legendData.value.push(`${lineName.value[i].name}(${lineName.value[i].unit})`)
|
||||||
|
|
||||||
|
if (lineName.value[i].field === 'ssll') {
|
||||||
|
yaxisTemp.position = 'left'
|
||||||
|
} else {
|
||||||
|
yaxisTemp.position = 'right'
|
||||||
|
yaxisTemp.offset = lineName.value[i].field === 'jrl' ? 60 * positionIndex : 55 * positionIndex
|
||||||
|
positionIndex += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
yaxisTemp.name = `${lineName.value[i].name}(${lineName.value[i].unit})`
|
||||||
|
yaxisTemp.min = lineName.value[i].min
|
||||||
|
yaxisTemp.max = lineName.value[i].max
|
||||||
|
yaxisTemp.axisLine.lineStyle.color = colorData[i].color
|
||||||
|
yAxis.value.push(yaxisTemp)
|
||||||
|
|
||||||
|
const serieTemp = JSON.parse(JSON.stringify(serie.value))
|
||||||
|
serieTemp.name = `${lineName.value[i].name}(${lineName.value[i].unit})`
|
||||||
|
serieTemp.field = lineName.value[i].field
|
||||||
|
serieTemp.lineStyle.color = colorData[i].color
|
||||||
|
serieTemp.yAxisIndex = i
|
||||||
|
series.value.push(serieTemp)
|
||||||
|
}
|
||||||
|
|
||||||
|
option.value = {
|
||||||
|
color: ['#000000', '#00007f', '#ff0000', '#005500', '#55007f', '#ffff00'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataZoom: [{
|
||||||
|
connectNulls: false,
|
||||||
|
id: 'dataZoomX',
|
||||||
|
type: "inside",
|
||||||
|
roam: false,
|
||||||
|
show: true,
|
||||||
|
xAxisIndex: [0],
|
||||||
|
filterMode: 'empty',
|
||||||
|
throttle: 50,
|
||||||
|
zoomOnMouseWheel: true,
|
||||||
|
moveOnMouseMove: true
|
||||||
|
}, {
|
||||||
|
id: 'dataZoomY',
|
||||||
|
type: 'inside',
|
||||||
|
filterMode: 'empty',
|
||||||
|
zoomLock: false,
|
||||||
|
throttle: 50,
|
||||||
|
zoomOnMouseWheel: true,
|
||||||
|
moveOnMouseMove: true
|
||||||
|
}],
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
dataView: {
|
||||||
|
show: false,
|
||||||
|
readOnly: false
|
||||||
|
},
|
||||||
|
restore: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
saveAsImage: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: legendData.value
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: '10%',
|
||||||
|
left: '3%',
|
||||||
|
right: '10%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true
|
||||||
|
},
|
||||||
|
data: xData.value
|
||||||
|
},
|
||||||
|
yAxis: yAxis.value,
|
||||||
|
series: series.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间选择变化
|
||||||
|
const getTime = (e) => {
|
||||||
|
if (e && e.length === 2) {
|
||||||
|
startTime.value = formatDate(e[0], 'yyyy-MM-dd hh:mm:ss')
|
||||||
|
endTime.value = formatDate(e[1], 'yyyy-MM-dd hh:mm:ss')
|
||||||
|
updateChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换表格显示
|
||||||
|
const onChangeTable = (e) => {
|
||||||
|
tableVisibled.value = !tableVisibled.value
|
||||||
|
checkBoxText.value = tableVisibled.value ? '显示历史趋势' : '显示历史报表'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
const handlePageChange = (e) => {
|
||||||
|
ipagination.value.current = e.current
|
||||||
|
ipagination.value.pageSize = e.pageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化表格时间显示
|
||||||
|
const formatTableTime = (time) => {
|
||||||
|
if (!time) return ''
|
||||||
|
return formatDate(time, 'yyyy-MM-dd hh:mm:ss')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数组最大值
|
||||||
|
const maxArrValue = (data) => {
|
||||||
|
if (!data || data.length === 0) return 0
|
||||||
|
|
||||||
|
const list = []
|
||||||
|
for (let i in data) {
|
||||||
|
if (data[i] !== null) {
|
||||||
|
list.push(parseInt(data[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.length === 0) return 0
|
||||||
|
|
||||||
|
list.sort((num1, num2) => num1 - num2)
|
||||||
|
return list[list.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新图表数据
|
||||||
|
const updateChart = () => {
|
||||||
|
dataSource.value = []
|
||||||
|
xData.value = []
|
||||||
|
|
||||||
|
for (let j = 0; j < series.value.length; j++) {
|
||||||
|
series.value[j].data = []
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
getAction(url.list, {
|
||||||
|
jldId: jldID.value,
|
||||||
|
startTime: startTime.value,
|
||||||
|
endTime: endTime.value
|
||||||
|
}).then(res => {
|
||||||
|
loading.value = false
|
||||||
|
|
||||||
|
if (res.success) {
|
||||||
|
const ssData = JSON.parse(res.result)
|
||||||
|
dataSource.value = ssData
|
||||||
|
ipagination.value.total = ssData.length
|
||||||
|
|
||||||
|
for (let i = 0; i < ssData.length; i++) {
|
||||||
|
const ctime = formatDate(ssData[i].createTime, 'yyyy-MM-dd hh:mm:ss')
|
||||||
|
xData.value.push(ctime)
|
||||||
|
|
||||||
|
for (let j = 0; j < series.value.length; j++) {
|
||||||
|
let tempValue = ssData[i][lineName.value[j].field]
|
||||||
|
tempValue = tempValue === 0 ? null : tempValue
|
||||||
|
series.value[j].data.push(tempValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let mm = 0; mm < series.value.length; mm++) {
|
||||||
|
const maxVal = maxArrValue(series.value[mm].data)
|
||||||
|
yAxis.value[mm].max = Math.round(maxVal * 1.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
option.value.xAxis.data = xData.value
|
||||||
|
|
||||||
|
if (myCharts.value) {
|
||||||
|
myCharts.value.setOption(option.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化ECharts
|
||||||
|
const initECharts = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
// 在Uniapp中,需要使用uni.createCanvasContext或使用ucharts等替代方案
|
||||||
|
// 这里简化处理,实际使用时需要根据Uniapp的图表方案调整
|
||||||
|
const canvas = document.getElementById('myCharts')
|
||||||
|
if (canvas) {
|
||||||
|
// 初始化ECharts实例
|
||||||
|
myCharts.value = echarts.init(canvas)
|
||||||
|
myCharts.value.setOption(option.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听lineData变化
|
||||||
|
watch(() => props.lineData, (val) => {
|
||||||
|
jldID.value = val.jldID
|
||||||
|
jldName.value = val.jldName
|
||||||
|
chartTitle.value = `${val.jldName}历史趋势`
|
||||||
|
lineName.value = JSON.parse(JSON.stringify(val.lineName))
|
||||||
|
startTime.value = val.startTime
|
||||||
|
endTime.value = val.endTime
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (val.startTime && val.endTime) {
|
||||||
|
const sDt = new Date(val.startTime)
|
||||||
|
const eDt = new Date(val.endTime)
|
||||||
|
lssjTimeRang.value = [sDt.getTime(), eDt.getTime()]
|
||||||
|
} else {
|
||||||
|
lssjTimeRang.value = getDefaultTimeRange()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('时间格式错误', e)
|
||||||
|
lssjTimeRang.value = getDefaultTimeRange()
|
||||||
|
}
|
||||||
|
|
||||||
|
initChart()
|
||||||
|
updateChart()
|
||||||
|
}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
// 设置默认时间范围
|
||||||
|
lssjTimeRang.value = getDefaultTimeRange()
|
||||||
|
|
||||||
|
// 在Uniapp中需要动态导入echarts或使用其他图表库
|
||||||
|
setTimeout(() => {
|
||||||
|
initECharts()
|
||||||
|
}, 500)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 页面卸载
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (myCharts.value) {
|
||||||
|
myCharts.value.dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-header {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title-container {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-picker {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 600rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
231
src/pages-production/shishishuju/chart/sssjChart.vue
Normal file
231
src/pages-production/shishishuju/chart/sssjChart.vue
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'default',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '历史数据图表',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageLayout :navbarShow="false" class="page-layout">
|
||||||
|
<view style="color: blue;font-size:18px;text-align: center;margin: 10px;width: 100%;">
|
||||||
|
<wd-text :text="jldData.jldname+ '实时趋势'" style="color: blue;font-size:18px;"></wd-text>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<uni-datetime-picker type="datetimerange" v-model="lssjTimeRange" @change="getTime" start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间" />
|
||||||
|
</view>
|
||||||
|
<view style="text-align: center;padding: 5px;">
|
||||||
|
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable @click="handleForward">前一天</wd-button>
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable @click="handleNext">后一天</wd-button>
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable @click="handleQuery">查询数据</wd-button>
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable @click="handleDrawLine">生成曲线</wd-button>
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<scroll-view direction="vertical" style="height: 200px;">
|
||||||
|
<wd-table :data="chartData" height="200px">
|
||||||
|
<wd-table-col prop="createTime" label="日期" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="jldName" label="计量点名称" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="yl" label="压力(MPa)" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="wd" label="温度(℃)" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="yc" label="差压(kPa)" align="center"></wd-table-col>
|
||||||
|
<wd-table-col prop="ssll" label="瞬时流量(m³/d)" align="center">
|
||||||
|
</wd-table-col>
|
||||||
|
<wd-table-col prop="jrl" label="今日流量(m³)" align="center">
|
||||||
|
</wd-table-col>
|
||||||
|
</wd-table>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<view v-if="drawLineFlag">
|
||||||
|
<cxc-szcx-multiLineChart :data-list="chartData" x-field="createTime" :y-fields="lineFields"
|
||||||
|
title="文增伴生气外输数据趋势" height="300"></cxc-szcx-multiLineChart>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</PageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
queryJldDataByJldID
|
||||||
|
} from '@/api/production'
|
||||||
|
import {
|
||||||
|
formatDate
|
||||||
|
} from '@/utils/dateTime.ts';
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
watchEffect,
|
||||||
|
onUnmounted,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
|
||||||
|
const lineFields = ref([{
|
||||||
|
name: '压力',
|
||||||
|
field: 'yl',
|
||||||
|
min: '0',
|
||||||
|
max: '2',
|
||||||
|
unit: 'MPa'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '温度',
|
||||||
|
field: 'wd',
|
||||||
|
min: '-10',
|
||||||
|
max: '40',
|
||||||
|
unit: '℃'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '差压',
|
||||||
|
field: 'yc',
|
||||||
|
min: '0',
|
||||||
|
max: '60',
|
||||||
|
unit: 'kPa'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '瞬时流量',
|
||||||
|
field: 'ssll',
|
||||||
|
min: '0',
|
||||||
|
max: '50000',
|
||||||
|
unit: 'm³/d'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '今日流量',
|
||||||
|
field: 'jrl',
|
||||||
|
min: '0',
|
||||||
|
max: '50000',
|
||||||
|
unit: 'm³'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
jldData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const chartData = ref([])
|
||||||
|
const drawLineFlag = ref(false)
|
||||||
|
|
||||||
|
function handleQuery() {
|
||||||
|
|
||||||
|
const jldid = props.jldData.id;
|
||||||
|
queryJldDataByJldID({
|
||||||
|
jldId: jldid,
|
||||||
|
startTime: startTime.value,
|
||||||
|
endTime: endTime.value
|
||||||
|
}).then(res => {
|
||||||
|
chartData.value = JSON.parse(res.result)
|
||||||
|
|
||||||
|
chartData.value.forEach(item => {
|
||||||
|
item.createTime = formatDate(item.createTime, "YYYY-MM-DD HH:mm ss")
|
||||||
|
})
|
||||||
|
console.log(123, chartData.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrawLine() {
|
||||||
|
drawLineFlag.value = true
|
||||||
|
}
|
||||||
|
// 前一天 - 以当前选择的起始日期为基准计算
|
||||||
|
function handleForward() {
|
||||||
|
// 使用当前选择的开始时间作为基准,而不是系统当前时间
|
||||||
|
lssjTimeRange.value = getDefaultTimeRange(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后一天
|
||||||
|
function handleNext() {
|
||||||
|
// 获取当前选择的开始时间
|
||||||
|
const currentStart = new Date(startTime.value);
|
||||||
|
// 获取今天8点的时间对象
|
||||||
|
const today8AM = new Date();
|
||||||
|
today8AM.setHours(8, 0, 0, 0);
|
||||||
|
|
||||||
|
// 允许切换到今天及之前的日期范围
|
||||||
|
if (currentStart < today8AM || isSameDay(currentStart, today8AM)) {
|
||||||
|
lssjTimeRange.value = getDefaultTimeRange(1);
|
||||||
|
} else {
|
||||||
|
// 可添加提示:已经是最新数据
|
||||||
|
uni.showToast({
|
||||||
|
title: '已是最新数据',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1500
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定日期偏移的时间范围(每天8:00至次日7:59)
|
||||||
|
const getDefaultTimeRange = (days) => {
|
||||||
|
// 防止原日期对象被污染,使用当前选择的开始时间作为基准
|
||||||
|
var baseDate;
|
||||||
|
if (startTime.value && new Date(startTime.value).toString() !== 'Invalid Date') {
|
||||||
|
baseDate = new Date(startTime.value);
|
||||||
|
} else {
|
||||||
|
// 如果选择的时间无效,则使用当前时间作为 fallback
|
||||||
|
baseDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算目标日期(基础日期 + 偏移天数)
|
||||||
|
const targetDate = new Date(baseDate);
|
||||||
|
targetDate.setDate(baseDate.getDate() + days);
|
||||||
|
|
||||||
|
// 构建开始时间:目标日期的8:00:00
|
||||||
|
const start = new Date(targetDate);
|
||||||
|
start.setHours(8, 0, 0, 0);
|
||||||
|
|
||||||
|
// 构建结束时间:目标日期+1天的7:59:59
|
||||||
|
const end = new Date(targetDate);
|
||||||
|
end.setDate(targetDate.getDate() + 1);
|
||||||
|
end.setHours(7, 59, 59, 0);
|
||||||
|
|
||||||
|
// 格式化时间字符串
|
||||||
|
const formattedStart = formatDate(start, 'YYYY-MM-DD HH:mm:ss');
|
||||||
|
const formattedEnd = formatDate(end, 'YYYY-MM-DD HH:mm:ss');
|
||||||
|
|
||||||
|
// 更新响应式变量
|
||||||
|
startTime.value = formattedStart;
|
||||||
|
endTime.value = formattedEnd;
|
||||||
|
|
||||||
|
return [formattedStart, formattedEnd];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 辅助函数:判断两个日期是否是同一天
|
||||||
|
const isSameDay = (date1, date2) => {
|
||||||
|
return date1.getFullYear() === date2.getFullYear() &&
|
||||||
|
date1.getMonth() === date2.getMonth() &&
|
||||||
|
date1.getDate() === date2.getDate();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 设置默认时间范围 需要延时等控件渲染好
|
||||||
|
setTimeout(() => {
|
||||||
|
lssjTimeRange.value = getDefaultTimeRange(0)
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
console.log(lssjTimeRange.value);
|
||||||
|
})
|
||||||
|
const startTime = ref('')
|
||||||
|
const endTime = ref('')
|
||||||
|
const lssjTimeRange = ref([])
|
||||||
|
|
||||||
|
|
||||||
|
// 时间选择变化
|
||||||
|
const getTime = (e) => {
|
||||||
|
if (e && e.length === 2) {
|
||||||
|
startTime.value = formatDate(e[0], 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
endTime.value = formatDate(e[1], 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
// updateChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
8
src/pages-production/shishishuju/gycsSssj.vue
Normal file
8
src/pages-production/shishishuju/gycsSssj.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
7
src/pages-production/shishishuju/index.vue
Normal file
7
src/pages-production/shishishuju/index.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<trqSssjVue></trqSssjVue>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import trqSssjVue from './trqSssj';
|
||||||
|
</script>
|
8
src/pages-production/shishishuju/nyxhSssj.vue
Normal file
8
src/pages-production/shishishuju/nyxhSssj.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
360
src/pages-production/shishishuju/trqSssj.vue
Normal file
360
src/pages-production/shishishuju/trqSssj.vue
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'default',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '生产数据',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
<template>
|
||||||
|
<PageLayout :navbarShow="false" class="page-layout">
|
||||||
|
<!-- 标题行 -->
|
||||||
|
<wd-text :text="stationName ? stationName + '实时数据' : '实时数据'"
|
||||||
|
style="color: blue;font-size:18px;text-align: center;margin: 5px;"></wd-text>
|
||||||
|
<wd-cell :title="'时间:' + nowDateTime " center>
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable
|
||||||
|
@click="handleStop">{{caijiText}}</wd-button>
|
||||||
|
<wd-button custom-class="custom-value" size="small" plain clickable
|
||||||
|
@click="handleRightClick">选择站场</wd-button>
|
||||||
|
|
||||||
|
</wd-cell>
|
||||||
|
|
||||||
|
<scroll-view direction="vertical" class="scroll-container">
|
||||||
|
<view class="container">
|
||||||
|
<view v-for="(item, index) in jlData" :key="index" class="card">
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="titlejl">{{ item.jldname }}</text>
|
||||||
|
<view class="status-circle"
|
||||||
|
:style="{ backgroundColor: item.yxzt==='运行' ? '#4CAF50' : '#F44336' }">
|
||||||
|
{{item.yxzt}}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="field-list">
|
||||||
|
<!-- 压力 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">压力(MPa)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.yl) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 差压 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">差压(kPa)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.yc) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 温度 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">温度(℃)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.wd) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 瞬时流量 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-labelssll" @click="openSssjChart(item)">瞬时流量(m³/d)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.ssll) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 今日流量 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-labelssll" @click="openlssjChart(item)">今日流量(m³)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.jrl) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 昨日流量 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">昨日流量(m³)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.zrl) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 昨日时间 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">昨日时间(min)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.zrsj) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 今日时间 -->
|
||||||
|
<view class="field-item">
|
||||||
|
<text class="field-label">今日时间(min)</text>
|
||||||
|
<text class="field-value">{{ formatNumber(item.jrsj) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<wd-popup v-model="selectZc" position="bottom" custom-style="width:100%;height: 300px;" @close="handleClose">
|
||||||
|
<view style="font-size: 18px;text-align: center;color: blue;margin: 10px;">选择采输气站场</view>
|
||||||
|
<cxc-szcx-stationJl-select v-model="stationID" returnCodeOrID="id" @change="onChange">
|
||||||
|
</cxc-szcx-stationJl-select>
|
||||||
|
</wd-popup>
|
||||||
|
<wd-popup v-model="lssjFlag" position="bottom" custom-style="width:100%;height: 300px;" @close="handleClose">
|
||||||
|
<lssj-chart></lssj-chart>
|
||||||
|
</wd-popup>
|
||||||
|
<wd-popup v-model="sssjFlag" position="bottom" custom-style="width:100%;height: 70vh;" @close="handleClose">
|
||||||
|
<sssj-chart :jldData="jldData"></sssj-chart>
|
||||||
|
</wd-popup>
|
||||||
|
|
||||||
|
</PageLayout>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
queryJldZcList,
|
||||||
|
queryJldDataByZc
|
||||||
|
} from '@/api/production'
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
watchEffect,
|
||||||
|
onUnmounted,
|
||||||
|
} from 'vue';
|
||||||
|
import {
|
||||||
|
onHide,
|
||||||
|
onShow
|
||||||
|
} from '@dcloudio/uni-app'
|
||||||
|
import {
|
||||||
|
formatDate
|
||||||
|
} from '@/utils/dateTime.ts';
|
||||||
|
|
||||||
|
import SssjChart from './chart/sssjChart'
|
||||||
|
import LssjChart from './chart/lssjChart'
|
||||||
|
|
||||||
|
const res = wx.getSystemInfoSync();
|
||||||
|
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||||
|
const cusnavbarheight = (statusHeight + 30) + "px";
|
||||||
|
|
||||||
|
const selectZc = ref(false)
|
||||||
|
const lssjFlag = ref(false)
|
||||||
|
const sssjFlag = ref(false)
|
||||||
|
const nowDateTime = ref("")
|
||||||
|
const caijiText = ref("停止采集")
|
||||||
|
const stationList = ref([])
|
||||||
|
const stationID = ref("")
|
||||||
|
const stationName = ref(" ")
|
||||||
|
const jlData = ref([])
|
||||||
|
const jldData = ref({})
|
||||||
|
const sssjUrl = ref('wss://szcx.zyyt.sinopec.com/Gyk/websocket/')
|
||||||
|
const jlByzc = ref('https://szcx.zyyt.sinopec.com/Gyk/sssj/GetJlByZc')
|
||||||
|
|
||||||
|
function openSssjChart(e) {
|
||||||
|
sssjFlag.value = true;
|
||||||
|
console.log(11, e)
|
||||||
|
jldData.value = e
|
||||||
|
console.log(selectZc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openlssjChart(e) {
|
||||||
|
sssjFlag.value = true;
|
||||||
|
console.log(selectZc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRightClick() {
|
||||||
|
selectZc.value = true;
|
||||||
|
console.log(selectZc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
console.log(selectZc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(e, data) {
|
||||||
|
console.log(2, e, data.value);
|
||||||
|
stationID.value = e
|
||||||
|
stationName.value = data.value.title
|
||||||
|
|
||||||
|
getScData(); //获取生产数据
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleStop() {
|
||||||
|
|
||||||
|
if (caijiText.value === "停止采集") {
|
||||||
|
console.log('清除定时器,停止采集')
|
||||||
|
caijiText.value = "开始采集"
|
||||||
|
clearInterval(timer2.value);
|
||||||
|
timer2.value = null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log('开始采集,打开定时器')
|
||||||
|
caijiText.value = "停止采集"
|
||||||
|
websocketheart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const websock = ref(null);
|
||||||
|
const timer2 = ref(null);
|
||||||
|
// 封装心跳函数
|
||||||
|
const websocketheart = () => {
|
||||||
|
// 先清除之前的定时器
|
||||||
|
if (timer2.value) {
|
||||||
|
clearInterval(timer2.value);
|
||||||
|
timer2.value = null;
|
||||||
|
}
|
||||||
|
timer2.value = setInterval(() => {
|
||||||
|
nowDateTime.value = formatDate(new Date(), "YYYY-MM-DD HH:mm:ss")
|
||||||
|
if (websock.value && websock.value.readyState === 1) {
|
||||||
|
// 如果连接正常,发送心跳消息
|
||||||
|
// connectSocketInit()
|
||||||
|
}
|
||||||
|
if (stationID.value) {
|
||||||
|
getScData();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
websocketheart()
|
||||||
|
stationID.value = "1267633458481725442"
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(timer2.value);
|
||||||
|
})
|
||||||
|
|
||||||
|
onHide(() => {
|
||||||
|
console.log('页面隐藏,清除定时器')
|
||||||
|
clearInterval(timer2.value);
|
||||||
|
timer2.value = null;
|
||||||
|
})
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
// 页面显示时重新启动定时器
|
||||||
|
websocketheart()
|
||||||
|
})
|
||||||
|
const getScData = () => {
|
||||||
|
uni.request({
|
||||||
|
url: jlByzc.value + '?zhanc=' + stationID.value + '&jldLx=0',
|
||||||
|
method: 'GET',
|
||||||
|
success: (res) => {
|
||||||
|
console.log(res)
|
||||||
|
jlData.value = JSON.parse(res.data.result).JlData;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 数字格式化
|
||||||
|
const formatNumber = (num) => {
|
||||||
|
let temp = 0;
|
||||||
|
try {
|
||||||
|
temp = parseFloat(num);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO handle the exception
|
||||||
|
}
|
||||||
|
return temp.toFixed(4).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10 10rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlejl {
|
||||||
|
font-size: 20rpx;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0055ff;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 5px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
/* 允许子元素换行 */
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-item {
|
||||||
|
display: flex;
|
||||||
|
height: 30px;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 5px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex-basis: calc(50% - 10px);
|
||||||
|
/* 每个元素占据约一半宽度,减去间隙 */
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* 包含内边距和边框 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 当屏幕宽度较小时,每个元素占据整行 */
|
||||||
|
@media (max-width: 200px) {
|
||||||
|
.field-item {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-label {
|
||||||
|
color: #666;
|
||||||
|
font-size: 10px;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 2px;
|
||||||
|
width: 80px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-labelssll {
|
||||||
|
color: #0000ff;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-size: 10px;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 2px;
|
||||||
|
width: 80px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-value {
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: right;
|
||||||
|
width: 60px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-circle {
|
||||||
|
width: 70rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
font-size: 12px;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-layout {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-container {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
8
src/pages-production/shishishuju/ysjSssj.vue
Normal file
8
src/pages-production/shishishuju/ysjSssj.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -9,51 +9,35 @@
|
|||||||
</route>
|
</route>
|
||||||
<template>
|
<template>
|
||||||
<PageLayout :navbarShow="false">
|
<PageLayout :navbarShow="false">
|
||||||
<view>
|
<view class="nav">
|
||||||
<view class="placeholder"></view>
|
<view class="nav_box">
|
||||||
<view style="width: 100%; display: grid; place-items: center">
|
<scroll-view direction="horizontal">
|
||||||
<uni-title :title="dateDate + ':生产情况'" type="h1" color="blue" />
|
<uni-segmented-control :current="current" :values="items" styleType="string" mode="segmented"
|
||||||
|
@clickItem="onClickItem"></uni-segmented-control>
|
||||||
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
<view style="margin: 0 10px;">
|
|
||||||
<uni-segmented-control style="margin-top: 10px;margin-bottom: 10px" :current="current" :values="items"
|
|
||||||
@clickItem="onClickItem" styleType="button" activeColor="#0055ff"></uni-segmented-control>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="content">
|
<view class="content">
|
||||||
|
|
||||||
<view v-if="current === 0">
|
<view v-if="current === 0">
|
||||||
<view style="padding: 0 10px">
|
<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
||||||
<view class="progress-bartime">
|
<sssjData></sssjData>
|
||||||
<!-- 动态设置宽度和颜色 -->
|
</scroll-view>
|
||||||
<view class="progressTime"
|
|
||||||
:style="{ width: `${timePercent}%`, 'background-color': '#0055ff' }">
|
|
||||||
</view>
|
|
||||||
<!-- 显示带符号的百分比 -->
|
|
||||||
<text class="progress-text">全年时间进度:{{ timePercent }}%</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
<view v-if="current === 1">
|
||||||
<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
||||||
<trq-data></trq-data>
|
<trq-data></trq-data>
|
||||||
<yy-data></yy-data>
|
<yy-data></yy-data>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="current === 1">
|
|
||||||
<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
|
||||||
<sssjForm></sssjForm>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import trqData from './ribaoshuju/trqRbsj';
|
|
||||||
import yyData from './ribaoshuju/yyRbsj';
|
|
||||||
import sssjForm from './shishishuju/index';
|
|
||||||
import {
|
|
||||||
formatDate,
|
|
||||||
getDateAfterDays,
|
|
||||||
getYearProgress
|
|
||||||
} from '@/utils/dateTime';
|
|
||||||
import {
|
import {
|
||||||
ref,
|
ref,
|
||||||
onMounted,
|
onMounted,
|
||||||
@ -62,14 +46,19 @@
|
|||||||
watchEffect,
|
watchEffect,
|
||||||
onUnmounted
|
onUnmounted
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
const items = ref(['日报数据', '实时数据'])
|
//、、东风风光的
|
||||||
|
import trqData from '@/pages-production/ribaoshuju/trqRbsj';
|
||||||
|
import yyData from '@/pages-production/ribaoshuju/yyRbsj';
|
||||||
|
import sssjData from '@/pages-production/shishishuju/trqSssj';
|
||||||
|
const items = ref(['油气实时', '油气历史', '管线运行', '安防监控', '设备运行'])
|
||||||
const current = ref(0)
|
const current = ref(0)
|
||||||
const res = wx.getSystemInfoSync();
|
const res = wx.getSystemInfoSync();
|
||||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||||
const cusnavbarheight = statusHeight + 44 + 'px';
|
const cusnavbarheight = (statusHeight + 50) + "px";
|
||||||
const scrollViewHeight = ref(0); //状态栏高度
|
const scrollViewHeight = ref(0); //滚动控件的高度
|
||||||
const timePercent = ref(0);
|
|
||||||
const dateDate = ref('');
|
const activeColor = ref("#0000ff")
|
||||||
|
const inActiveColor = ref("#000000")
|
||||||
|
|
||||||
function onClickItem(e) {
|
function onClickItem(e) {
|
||||||
if (current.value != e.currentIndex) {
|
if (current.value != e.currentIndex) {
|
||||||
@ -77,31 +66,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const strDate = () => {
|
|
||||||
const now = new Date();
|
|
||||||
if (now.getHours() < 11) {
|
|
||||||
return formatDate(getDateAfterDays(now, -1)); //11点之前 头一天的数据
|
|
||||||
} else {
|
|
||||||
return formatDate(now);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
dateDate.value = strDate();
|
|
||||||
timePercent.value = getYearProgress();
|
|
||||||
calculateScrollViewHeight();
|
calculateScrollViewHeight();
|
||||||
// 监听窗口大小变化事件,当窗口大小改变时重新计算高度
|
// 使用 Uniapp 提供的窗口大小变化监听方法
|
||||||
window.addEventListener('resize', calculateScrollViewHeight);
|
uni.onWindowResize(calculateScrollViewHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
// 移除窗口大小变化事件监听器
|
// 移除 Uniapp 窗口大小变化监听
|
||||||
window.removeEventListener('resize', calculateScrollViewHeight);
|
uni.offWindowResize(calculateScrollViewHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
onHide(()=>{ //切换首页后,将生产切换为日本数据以清楚定时 by闵
|
|
||||||
current.value = 0;
|
|
||||||
})
|
|
||||||
|
|
||||||
const calculateScrollViewHeight = () => {
|
const calculateScrollViewHeight = () => {
|
||||||
// 获取屏幕的总高度
|
// 获取屏幕的总高度
|
||||||
const screenHeight = uni.getSystemInfoSync().windowHeight;
|
const screenHeight = uni.getSystemInfoSync().windowHeight;
|
||||||
@ -111,18 +85,7 @@
|
|||||||
query
|
query
|
||||||
.select('.nav')
|
.select('.nav')
|
||||||
.boundingClientRect();
|
.boundingClientRect();
|
||||||
query
|
|
||||||
.select('.placeholder')
|
|
||||||
.boundingClientRect();
|
|
||||||
query
|
|
||||||
.select('.uni-title')
|
|
||||||
.boundingClientRect();
|
|
||||||
query
|
|
||||||
.select('.uni-segmented-control')
|
|
||||||
.boundingClientRect();
|
|
||||||
query
|
|
||||||
.select('.progress-bartime')
|
|
||||||
.boundingClientRect();
|
|
||||||
// 执行查询操作
|
// 执行查询操作
|
||||||
query.exec((res) => {
|
query.exec((res) => {
|
||||||
let totalHeight = 0;
|
let totalHeight = 0;
|
||||||
@ -132,62 +95,38 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 计算 scroll-view 的高度
|
// 计算 scroll-view 的高度
|
||||||
scrollViewHeight.value = screenHeight - totalHeight - 80;
|
scrollViewHeight.value = screenHeight - totalHeight;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.nav {
|
.nav {
|
||||||
width: calc(100% - 60rpx);
|
width: calc(100%);
|
||||||
padding: 0 30rpx;
|
|
||||||
height: v-bind(cusnavbarheight);
|
height: v-bind(cusnavbarheight);
|
||||||
|
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #ffffff;
|
//color: #333333;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
background-image: url('../../static/my/navbg.png');
|
background-image: url('@/static/navbg.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 750rpx 458rpx;
|
background-size: 750rpx 458rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.nav_box {
|
||||||
height: v-bind(cusnavbarheight);
|
font-size: 18;
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bartime {
|
|
||||||
position: relative;
|
|
||||||
height: 25px;
|
|
||||||
background: #f0f0f0;
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
height: 100%;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progressTime {
|
|
||||||
height: 100%;
|
|
||||||
transition: all 0.3s;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-text {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
bottom: 6rpx;
|
||||||
top: 50%;
|
width: calc(100% - 60rpx);
|
||||||
transform: translate(-50%, -50%);
|
left: 30rpx;
|
||||||
color: red;
|
right: 30rpx;
|
||||||
/* 保持红色 */
|
}
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
.content {
|
||||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
position: absolute;
|
||||||
/* 提升可读性 */
|
top: v-bind(cusnavbarheight);
|
||||||
|
width: 100%;
|
||||||
|
min-height: calc(100vh - v-bind(cusnavbarheight));
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -0,0 +1,373 @@
|
|||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'default',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '历史数据图表',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
<template>
|
||||||
|
<PageLayout :navbarShow="false">
|
||||||
|
<view>
|
||||||
|
<!-- ECharts图表 -->
|
||||||
|
<view class="chart-container">
|
||||||
|
<l-echart ref="chart" @finished="initChart" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</PageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted
|
||||||
|
} from 'vue'; // 补充导入ref等API
|
||||||
|
import {
|
||||||
|
formatDate,
|
||||||
|
getDateAfterDays,
|
||||||
|
getDateAfterMonths
|
||||||
|
} from '@/utils/dateTime';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
xField: {
|
||||||
|
type: String,
|
||||||
|
default: 'createTime' // 原xField默认值是'rqDate',与数据中的createTime匹配,修正为createTime
|
||||||
|
},
|
||||||
|
yFields: {
|
||||||
|
type: Object, // 注意:yFields应是数组(存储多条线配置),原代码写的是String,这里修正为Array
|
||||||
|
default: () => [],
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 响应式数据定义
|
||||||
|
const colorData = ref([{
|
||||||
|
color: '#000000'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#00007f'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#ff0000'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#005500'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#55007f'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#ffff00'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const chart = ref(null);
|
||||||
|
const chartOption = ref({}); // 初始化为空对象,避免undefined
|
||||||
|
const chartTitle = ref('历史趋势'); // 直接初始化标题,无需在watch中重复赋值
|
||||||
|
|
||||||
|
// 1. 修复:生成图表配置(返回配置对象,供赋值给chartOption.value)
|
||||||
|
const generateOptions = () => {
|
||||||
|
console.log(23)
|
||||||
|
const serie = []; // 局部变量:存储系列配置
|
||||||
|
const yData = []; // 局部变量:存储Y轴配置
|
||||||
|
const xData = []; // 局部变量:存储X轴数据
|
||||||
|
const legendData = []; // 局部变量:存储图例数据
|
||||||
|
let positionIndex = 0;
|
||||||
|
const yDataNum = props.yFields.length; // Y轴数量 = 线条数量
|
||||||
|
|
||||||
|
// 初始化X轴(若需默认占位,可保留;建议后续用真实数据覆盖)
|
||||||
|
for (let i = 0; i < yDataNum; i++) {
|
||||||
|
xData.push('');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环处理每条线的Y轴和系列配置
|
||||||
|
for (let i = 0; i < props.yFields.length; i++) {
|
||||||
|
const yFieldItem = props.yFields[i]; // 简化变量引用
|
||||||
|
// Y轴配置模板
|
||||||
|
const yaxisTemp = {
|
||||||
|
type: 'value',
|
||||||
|
nameRotate: 270,
|
||||||
|
nameLocation: 'middle',
|
||||||
|
nameGap: 20,
|
||||||
|
name: '',
|
||||||
|
position: 'left',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#61A0A8',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图例名称(拼接名称+单位)
|
||||||
|
const legendName = `${yFieldItem.name}(${yFieldItem.unit})`;
|
||||||
|
legendData.push(legendName);
|
||||||
|
|
||||||
|
console.log(1, legendData)
|
||||||
|
|
||||||
|
// 调整Y轴位置(ssll放左侧,其他放右侧)
|
||||||
|
if (yFieldItem.field === 'ssll') {
|
||||||
|
yaxisTemp.position = 'left';
|
||||||
|
yaxisTemp.nameGap = -15;
|
||||||
|
} else {
|
||||||
|
yaxisTemp.position = 'right';
|
||||||
|
yaxisTemp.offset = 40 * positionIndex;
|
||||||
|
positionIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充Y轴配置(修复v[i].max错误,改为yFieldItem.max)
|
||||||
|
yaxisTemp.name = legendName;
|
||||||
|
yaxisTemp.min = yFieldItem.min ?? 0; // 兜底:无min时设为0
|
||||||
|
yaxisTemp.max = yFieldItem.max ?? 100; // 兜底:无max时设为100
|
||||||
|
yaxisTemp.axisLine.lineStyle.color = colorData.value[i]?.color || '#61A0A8'; // 颜色兜底
|
||||||
|
|
||||||
|
yData.push(yaxisTemp);
|
||||||
|
|
||||||
|
// 系列配置模板
|
||||||
|
const serieTemp = {
|
||||||
|
field: yFieldItem.field,
|
||||||
|
name: legendName,
|
||||||
|
showSymbol: false,
|
||||||
|
type: 'line',
|
||||||
|
lineStyle: {
|
||||||
|
width: 2
|
||||||
|
},
|
||||||
|
data: [],
|
||||||
|
yAxisIndex: i // 对应第i个Y轴
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修复this.serie.push错误:向局部变量seriepush
|
||||||
|
serie.push(serieTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复:返回完整配置对象
|
||||||
|
return {
|
||||||
|
color: ['#000000', '#00007f', '#ff0000', '#005500', '#55007f', '#ffff00'],
|
||||||
|
title: {
|
||||||
|
textAlign: 'auto',
|
||||||
|
text: chartTitle.value
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
alwaysShowContent: true,
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
showTitle: true,
|
||||||
|
orient: 'vertical',
|
||||||
|
feature: {
|
||||||
|
dataView: {
|
||||||
|
show: true,
|
||||||
|
readOnly: false
|
||||||
|
},
|
||||||
|
restore: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
saveAsImage: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
left: '0%',
|
||||||
|
top: '10%'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: legendData,
|
||||||
|
itemGap: 5,
|
||||||
|
padding: [35, 5, 25, 5],
|
||||||
|
type: 'scroll'
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: '15%',
|
||||||
|
left: '5%',
|
||||||
|
right: `${10 + positionIndex * 10}%`, // 动态调整右侧间距(避免Y轴标签被截断)
|
||||||
|
bottom: 20,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true
|
||||||
|
},
|
||||||
|
data: xData
|
||||||
|
},
|
||||||
|
yAxis: yData,
|
||||||
|
series: serie
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. 修复:数据处理(正确访问响应式变量)
|
||||||
|
const processSeriesData = () => {
|
||||||
|
const ssData = props.dataList;
|
||||||
|
// 修复:访问chartOption.value的属性
|
||||||
|
const xData = [...chartOption.value.xAxis.data]; // 拷贝原X轴数据(避免直接修改) series
|
||||||
|
const serie = [...chartOption.value.series]; // 拷贝原系列数据
|
||||||
|
const yData = [...chartOption.value.yAxis]; // 拷贝原Y轴数据
|
||||||
|
|
||||||
|
// 清空历史数据(避免重复添加)
|
||||||
|
xData.length = 0;
|
||||||
|
serie.forEach(item => (item.data.length = 0));
|
||||||
|
|
||||||
|
// 处理每条数据
|
||||||
|
ssData.forEach(item => {
|
||||||
|
// 格式化X轴时间(用props.xField获取字段名,避免硬编码createTime)
|
||||||
|
const ctime = item[props.xField];
|
||||||
|
xData.push(ctime);
|
||||||
|
|
||||||
|
// 填充每条线的数值
|
||||||
|
serie.forEach((serieItem, j) => {
|
||||||
|
const field = props.yFields[j].field;
|
||||||
|
const tempValue = item[field];
|
||||||
|
// 兜底:空值设为0(避免图表断层)
|
||||||
|
serieItem.data.push(tempValue ?? 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 动态调整Y轴最大值(修复this.serie和this.maxArrValue错误)
|
||||||
|
serie.forEach((serieItem, mm) => {
|
||||||
|
const maxValue = maxArrValue(serieItem.data);
|
||||||
|
yData[mm].max = Math.round(maxValue * 1.2) || 100; // 兜底:最大值为0时设为100
|
||||||
|
});
|
||||||
|
|
||||||
|
// 修复:更新响应式数据(必须通过.value)
|
||||||
|
chartOption.value = {
|
||||||
|
...chartOption.value, // 保留原有配置
|
||||||
|
xAxis: {
|
||||||
|
...chartOption.value.xAxis,
|
||||||
|
data: xData
|
||||||
|
},
|
||||||
|
series: serie,
|
||||||
|
yAxis: yData
|
||||||
|
};
|
||||||
|
console.log(22, chartOption.value)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. 修复:计算数组最大值(过滤NaN,避免排序错误)
|
||||||
|
const maxArrValue = (data) => {
|
||||||
|
// 过滤非数字项,转为Number后取最大值
|
||||||
|
const validNumbers = data
|
||||||
|
.map(item => Number(item))
|
||||||
|
.filter(item => !isNaN(item));
|
||||||
|
|
||||||
|
// 兜底:无有效数字时返回0
|
||||||
|
return validNumbers.length > 0 ?
|
||||||
|
Math.max(...validNumbers) :
|
||||||
|
0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 4. 修复:监听数据变化(直接使用初始化后的标题)
|
||||||
|
watch(
|
||||||
|
() => props.dataList,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal.length === 0) return; // 空数据不处理
|
||||||
|
console.log(33, props.dataList)
|
||||||
|
console.log(44, props.yFields)
|
||||||
|
initChart()
|
||||||
|
updateChart();
|
||||||
|
}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
} // 立即执行:初始数据加载时触发
|
||||||
|
);
|
||||||
|
|
||||||
|
// 5. 修复:初始化图表(正确赋值chartOption.value)
|
||||||
|
const initChart = async () => {
|
||||||
|
// 生成配置并赋值给响应式变量
|
||||||
|
chartOption.value = generateOptions();
|
||||||
|
if (!chart.value) return;
|
||||||
|
|
||||||
|
// 初始化ECharts实例(去掉setTimeout,用async/await更可靠)
|
||||||
|
const myChart = await chart.value.init(echarts);
|
||||||
|
myChart.setOption(chartOption.value);
|
||||||
|
|
||||||
|
// 窗口resize时重绘(优化体验)
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
myChart.resize();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 6. 修复:更新图表(正确访问chartOption.value)
|
||||||
|
const updateChart = () => {
|
||||||
|
if (!myChart.value || !chartOption.value) {
|
||||||
|
console.warn('ECharts实例未初始化!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processSeriesData();
|
||||||
|
myChart.value.setOption(chartOption.value, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生命周期:挂载时初始化
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
initChart();
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生命周期:卸载时销毁图表(避免内存泄漏)
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (chart.value) {
|
||||||
|
const myChart = chart.value.getInstance();
|
||||||
|
myChart.dispose();
|
||||||
|
chart.value = null;
|
||||||
|
}
|
||||||
|
window.removeEventListener('resize', () => {}); // 移除监听
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 30vh;
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 20rpx;
|
||||||
|
background: linear-gradient(145deg, #f8f9fa 0%, #ffffff 100%);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载占位符(数据为空时显示) */
|
||||||
|
.chart-container::before {
|
||||||
|
content: '数据加载中...';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: #666;
|
||||||
|
font-size: 28rpx;
|
||||||
|
z-index: 1;
|
||||||
|
/* 数据加载完成后隐藏 */
|
||||||
|
opacity: v-bind('chartOption.value.series?.length > 0 ? 0 : 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端优化:调整右侧间距(避免Y轴标签被截断) */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.chart-container {
|
||||||
|
height: 30vh;
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 10rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
97
src/uni_modules/cxc-szcx-multiLineChart/package.json
Normal file
97
src/uni_modules/cxc-szcx-multiLineChart/package.json
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"id": "cxc-szcx-multiLineChart",
|
||||||
|
"displayName": "cxc-szcx-multiLineChart",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "cxc-szcx-multiLineChart",
|
||||||
|
"keywords": [
|
||||||
|
"cxc-szcx-multiLineChart"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0",
|
||||||
|
"uni-app": "^3.1.0",
|
||||||
|
"uni-app-x": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "",
|
||||||
|
"data": "",
|
||||||
|
"permissions": ""
|
||||||
|
},
|
||||||
|
"npmurl": "",
|
||||||
|
"darkmode": "-",
|
||||||
|
"i18n": "-",
|
||||||
|
"widescreen": "-"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "-",
|
||||||
|
"aliyun": "-",
|
||||||
|
"alipay": "-"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"uni-app": {
|
||||||
|
"vue": {
|
||||||
|
"vue2": "-",
|
||||||
|
"vue3": "-"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"safari": "-",
|
||||||
|
"chrome": "-"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"vue": "-",
|
||||||
|
"nvue": "-",
|
||||||
|
"android": "-",
|
||||||
|
"ios": "-",
|
||||||
|
"harmony": "-"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "-",
|
||||||
|
"alipay": "-",
|
||||||
|
"toutiao": "-",
|
||||||
|
"baidu": "-",
|
||||||
|
"kuaishou": "-",
|
||||||
|
"jd": "-",
|
||||||
|
"harmony": "-",
|
||||||
|
"qq": "-",
|
||||||
|
"lark": "-"
|
||||||
|
},
|
||||||
|
"quickapp": {
|
||||||
|
"huawei": "-",
|
||||||
|
"union": "-"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uni-app-x": {
|
||||||
|
"web": {
|
||||||
|
"safari": "-",
|
||||||
|
"chrome": "-"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"android": "-",
|
||||||
|
"ios": "-",
|
||||||
|
"harmony": "-"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/uni_modules/cxc-szcx-multiLineChart/readme.md
Normal file
34
src/uni_modules/cxc-szcx-multiLineChart/readme.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# cxc-szcx-multiLineChart
|
||||||
|
# 这个多字段趋势图组件具有以下特点和功能:
|
||||||
|
类型安全:使用 TypeScript 定义了清晰的接口,确保数据类型正确
|
||||||
|
灵活配置:通过 props 参数可以配置需要展示的字段、时间字段、标题等
|
||||||
|
多字段展示:支持同时展示多个数据字段的趋势线(如 yl, wd, yc 等)
|
||||||
|
参考线功能:每个字段都可以设置参考值,自动生成对应的参考线
|
||||||
|
交互功能:
|
||||||
|
支持图例筛选,可单独显示 / 隐藏某个字段
|
||||||
|
提供数据缩放功能,可查看局部数据
|
||||||
|
悬停时显示详细数据信息
|
||||||
|
窗口大小变化时自动调整图表
|
||||||
|
使用示例:
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<multi-field-trend-chart
|
||||||
|
:data-list="dataList"
|
||||||
|
time-field="createTime"
|
||||||
|
:fields="[
|
||||||
|
{ field: 'yl', name: '压力', referenceValue: 0.73 },
|
||||||
|
{ field: 'wd', name: '温度', color: '#ff6347' },
|
||||||
|
{ field: 'yc', name: '压力差' },
|
||||||
|
{ field: 'ssll', name: '瞬时流量' },
|
||||||
|
{ field: 'jrl', name: '累计流量' }
|
||||||
|
]"
|
||||||
|
title="文增伴生气外输数据趋势"
|
||||||
|
height="600rpx"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MultiFieldTrendChart from '@/components/MultiFieldTrendChart.vue';
|
||||||
|
import { dataList } from '@/data/trendData'; // 导入您的数据
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user