修改生产模块页面,增加顶部标签,新建分包pages-production,将生产页面移动至分包下面。
下一步制作曲线页面,统计页面,继续做好设备,安防等页面。
This commit is contained in:
parent
adcdb86db7
commit
47f2aca7f1
@ -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>
|
||||||
217
src/pages-production/shishishuju/chart/sssjChart.vue
Normal file
217
src/pages-production/shishishuju/chart/sssjChart.vue
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<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" time-field="createTime" :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([{
|
||||||
|
field: 'yl',
|
||||||
|
name: '压力',
|
||||||
|
referenceValue: 0.73
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'wd',
|
||||||
|
name: '温度',
|
||||||
|
color: '#ff6347'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'yc',
|
||||||
|
name: '压力差'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'ssll',
|
||||||
|
name: '瞬时流量'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'jrl',
|
||||||
|
name: '累计流量'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
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>
|
||||||
356
src/pages-production/shishishuju/trqSssj.vue
Normal file
356
src/pages-production/shishishuju/trqSssj.vue
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
<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()
|
||||||
|
})
|
||||||
|
|
||||||
|
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,422 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<!-- ECharts图表容器 -->
|
||||||
|
<view class="chart-container" ref="chartContainer">
|
||||||
|
<l-echart ref="chart" @finished="onChartFinished" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue';
|
||||||
|
|
||||||
|
// 定义数据项接口
|
||||||
|
interface DataItem {
|
||||||
|
[key : string] : string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义字段配置接口
|
||||||
|
interface FieldConfig {
|
||||||
|
field : string; // 数据字段名
|
||||||
|
name : string; // 显示名称
|
||||||
|
color ?: string; // 线条颜色(可选)
|
||||||
|
referenceValue ?: number; // 参考值(可选)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件属性接口
|
||||||
|
interface TrendChartProps {
|
||||||
|
dataList : DataItem[]; // 数据列表
|
||||||
|
timeField : string; // 时间字段名
|
||||||
|
fields : FieldConfig[]; // 需要展示的字段配置
|
||||||
|
title ?: string; // 图表标题
|
||||||
|
height ?: string; // 图表高度
|
||||||
|
showLegend ?: boolean; // 是否显示图例
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件属性定义
|
||||||
|
const props = withDefaults(defineProps<TrendChartProps>(), {
|
||||||
|
timeField: 'createTime',
|
||||||
|
fields: () => [],
|
||||||
|
title: '数据趋势图',
|
||||||
|
height: '30vh',
|
||||||
|
showLegend: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 图表引用和状态
|
||||||
|
const chart = ref<any>(null);
|
||||||
|
const chartContainer = ref<HTMLElement | null>(null);
|
||||||
|
const chartInstance = ref<echarts.ECharts | null>(null);
|
||||||
|
const chartOption = ref<any>({});
|
||||||
|
const isLoading = ref(true);
|
||||||
|
|
||||||
|
// 生成颜色数组 - 为不同线条提供区分色
|
||||||
|
const generateColors = (count : number) : string[] => {
|
||||||
|
const baseColors = [
|
||||||
|
'#337ab7', '#5cb85c', '#5bc0de', '#f0ad4e', '#d9534f',
|
||||||
|
'#7b68ee', '#ff6347', '#00ced1', '#ffd700', '#9370db'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count <= baseColors.length) {
|
||||||
|
return baseColors.slice(0, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = [...baseColors];
|
||||||
|
for (let i = baseColors.length; i < count; i++) {
|
||||||
|
const color = `#${Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')}`;
|
||||||
|
colors.push(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理系列数据 - 增加错误处理
|
||||||
|
const processSeriesData = () => {
|
||||||
|
// 验证数据有效性
|
||||||
|
if (!props.dataList || props.dataList.length === 0) {
|
||||||
|
console.warn('没有可用数据');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!props.fields || props.fields.length === 0) {
|
||||||
|
console.warn('没有配置要显示的字段');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = generateColors(props.fields.length);
|
||||||
|
const series : any[] = [];
|
||||||
|
|
||||||
|
props.fields.forEach((fieldConfig, index) => {
|
||||||
|
try {
|
||||||
|
// 验证字段是否存在于数据中
|
||||||
|
const hasField = props.dataList.some(item => item[fieldConfig.field] !== undefined);
|
||||||
|
if (!hasField) {
|
||||||
|
console.warn(`数据中不存在字段: ${fieldConfig.field}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理当前字段的趋势线数据
|
||||||
|
const fieldData = props.dataList
|
||||||
|
.filter(item => item[props.timeField] && item[fieldConfig.field]) // 过滤无效数据
|
||||||
|
.sort((a, b) => {
|
||||||
|
const timeA = new Date(a[props.timeField] as string).getTime();
|
||||||
|
const timeB = new Date(b[props.timeField] as string).getTime();
|
||||||
|
return timeA - timeB;
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
const timeValue = new Date(item[props.timeField] as string).getTime();
|
||||||
|
const fieldValue = parseFloat(item[fieldConfig.field].toString()) || 0;
|
||||||
|
return [timeValue, fieldValue];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加趋势线系列
|
||||||
|
series.push({
|
||||||
|
name: fieldConfig.name,
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 6,
|
||||||
|
smooth: true,
|
||||||
|
data: fieldData,
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
color: fieldConfig.color || colors[index]
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: fieldConfig.color || colors[index],
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
scale: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果有参考值,添加参考线
|
||||||
|
if (fieldConfig.referenceValue !== undefined) {
|
||||||
|
series.push({
|
||||||
|
type: 'line',
|
||||||
|
name: `${fieldConfig.name}参考值`,
|
||||||
|
markLine: {
|
||||||
|
silent: true,
|
||||||
|
lineStyle: {
|
||||||
|
type: 'dashed',
|
||||||
|
color: fieldConfig.color || colors[index],
|
||||||
|
width: 2
|
||||||
|
},
|
||||||
|
data: [{ yAxis: fieldConfig.referenceValue }],
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'end',
|
||||||
|
formatter: `${fieldConfig.name}参考值: ${fieldConfig.referenceValue}`,
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`处理字段 ${fieldConfig.field} 时出错:`, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return series;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成图表配置
|
||||||
|
const generateOptions = () => ({
|
||||||
|
title: {
|
||||||
|
text: props.title,
|
||||||
|
left: 'center',
|
||||||
|
textStyle: {
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 16
|
||||||
|
},
|
||||||
|
padding: [10, 0, 0, 0]
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||||
|
borderColor: '#eee',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 8,
|
||||||
|
textStyle: {
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
axisPointer: {
|
||||||
|
type: 'line',
|
||||||
|
lineStyle: {
|
||||||
|
color: '#ddd',
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatter: function (params : any[]) {
|
||||||
|
if (!params || params.length === 0) return '';
|
||||||
|
const time = new Date(params[0].value[0]).toLocaleString();
|
||||||
|
let result = `<div style="font-weight:bold;margin-bottom:5px">${time}</div>`;
|
||||||
|
|
||||||
|
params.forEach((item) => {
|
||||||
|
if (item.seriesType === 'line' && item.data) {
|
||||||
|
result += `<div style="display:flex;align-items:center;margin:3px 0">
|
||||||
|
<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${item.color};margin-right:5px;"></span>
|
||||||
|
<span>${item.seriesName}:${item.value[1].toFixed(2)}</span>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
confine: true
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#ddd'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
formatter: (value : number) => {
|
||||||
|
const date = new Date(value);
|
||||||
|
return `${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
},
|
||||||
|
rotate: 30
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#f5f5f5',
|
||||||
|
type: 'dashed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#ddd'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#f5f5f5',
|
||||||
|
type: 'dashed'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666',
|
||||||
|
formatter: (value : number) => `${value.toFixed(2)}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: processSeriesData(),
|
||||||
|
legend: props.showLegend ? {
|
||||||
|
type: 'scroll',
|
||||||
|
bottom: 5,
|
||||||
|
textStyle: {
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 12
|
||||||
|
},
|
||||||
|
pageIconColor: '#666',
|
||||||
|
pageTextStyle: {
|
||||||
|
color: '#999'
|
||||||
|
},
|
||||||
|
selectedMode: 'multiple'
|
||||||
|
} : {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: props.title ? 60 : 30,
|
||||||
|
right: 30,
|
||||||
|
bottom: props.showLegend ? 60 : 30,
|
||||||
|
left: 50,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
start: 0,
|
||||||
|
end: 100,
|
||||||
|
minValueSpan: 3600 * 1000 * 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'slider',
|
||||||
|
bottom: 10,
|
||||||
|
start: 0,
|
||||||
|
end: 100,
|
||||||
|
handleSize: 8
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = async () => {
|
||||||
|
if (!chart.value || chartInstance.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 确保图表容器已正确渲染
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// 初始化图表实例
|
||||||
|
chartInstance.value = await chart.value.init(echarts);
|
||||||
|
|
||||||
|
// 设置图表配置
|
||||||
|
updateChart();
|
||||||
|
|
||||||
|
// 监听窗口大小变化
|
||||||
|
const handleResize = () => {
|
||||||
|
chartInstance.value?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
// 组件卸载时清理
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('图表初始化失败:', error);
|
||||||
|
isLoading.value = false; // 即使失败也隐藏加载状态
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图表组件加载完成回调
|
||||||
|
const onChartFinished = () => {
|
||||||
|
initChart();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新图表
|
||||||
|
const updateChart = () => {
|
||||||
|
if (!chartInstance.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 生成新的图表配置
|
||||||
|
chartOption.value = generateOptions();
|
||||||
|
|
||||||
|
// 设置图表数据
|
||||||
|
chartInstance.value.setOption(chartOption.value, true);
|
||||||
|
|
||||||
|
// 数据加载完成,隐藏加载状态
|
||||||
|
isLoading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新图表失败:', error);
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听数据变化,更新图表
|
||||||
|
watch(
|
||||||
|
() => [props.dataList, props.fields, props.title],
|
||||||
|
() => {
|
||||||
|
if (props.dataList.length > 0 && props.fields.length > 0) {
|
||||||
|
isLoading.value = true;
|
||||||
|
// 延迟更新,确保DOM已更新
|
||||||
|
setTimeout(updateChart, 100);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true } // 立即执行一次
|
||||||
|
);
|
||||||
|
|
||||||
|
// 生命周期钩子
|
||||||
|
onMounted(() => {
|
||||||
|
// 设置图表高度
|
||||||
|
if (chartContainer.value && props.height) {
|
||||||
|
chartContainer.value.style.height = props.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果数据已准备好,初始化图表
|
||||||
|
if (props.dataList.length > 0 && props.fields.length > 0) {
|
||||||
|
nextTick(() => {
|
||||||
|
initChart();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// 销毁图表,释放资源
|
||||||
|
if (chartInstance.value) {
|
||||||
|
chartInstance.value.dispose();
|
||||||
|
chartInstance.value = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 图表容器样式 */
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 16rpx;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载状态样式 - 仅在isLoading为true时显示 */
|
||||||
|
.chart-container::before {
|
||||||
|
content: '数据加载中...';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: #999;
|
||||||
|
font-size: 28rpx;
|
||||||
|
z-index: 1;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
opacity: v-bind(isLoading ? 1 : 0);
|
||||||
|
pointer-events: v-bind(isLoading ? 'auto' : 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端适配 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.chart-container {
|
||||||
|
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