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