|
@@ -5,6 +5,9 @@ import dayjs from 'dayjs'
|
|
|
|
|
|
|
|
type CardKey =
|
|
type CardKey =
|
|
|
| 'device'
|
|
| 'device'
|
|
|
|
|
+ | 'utilizationRate'
|
|
|
|
|
+ | 'todayGas'
|
|
|
|
|
+ | 'yearGas'
|
|
|
| 'maintain'
|
|
| 'maintain'
|
|
|
| 'unfilledCount'
|
|
| 'unfilledCount'
|
|
|
| 'filledCount'
|
|
| 'filledCount'
|
|
@@ -23,6 +26,27 @@ const cardConfigs: CardConfig[] = [
|
|
|
accent: THEME.color.blue.strong,
|
|
accent: THEME.color.blue.strong,
|
|
|
glow: THEME.color.blue.glow
|
|
glow: THEME.color.blue.glow
|
|
|
},
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ key: 'utilizationRate',
|
|
|
|
|
+ title: '设备利用率(%)',
|
|
|
|
|
+ icon: 'i-solar:chart-2-linear',
|
|
|
|
|
+ accent: THEME.color.green.strong,
|
|
|
|
|
+ glow: THEME.color.green.glow
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ key: 'todayGas',
|
|
|
|
|
+ title: '当日注气量(万方)',
|
|
|
|
|
+ icon: 'i-solar:gas-station-linear',
|
|
|
|
|
+ accent: THEME.color.blue.strong,
|
|
|
|
|
+ glow: THEME.color.blue.glow
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ key: 'yearGas',
|
|
|
|
|
+ title: '累计注气量(万方)',
|
|
|
|
|
+ icon: 'i-solar:database-linear',
|
|
|
|
|
+ accent: THEME.color.green.strong,
|
|
|
|
|
+ glow: THEME.color.green.glow
|
|
|
|
|
+ },
|
|
|
// {
|
|
// {
|
|
|
// key: 'maintain',
|
|
// key: 'maintain',
|
|
|
// title: '维修工单',
|
|
// title: '维修工单',
|
|
@@ -77,6 +101,9 @@ const cardConfigs: CardConfig[] = [
|
|
|
function createDefaultCardState(): Record<CardKey, CardStateItem> {
|
|
function createDefaultCardState(): Record<CardKey, CardStateItem> {
|
|
|
return {
|
|
return {
|
|
|
device: { value: 0, loading: true },
|
|
device: { value: 0, loading: true },
|
|
|
|
|
+ utilizationRate: { value: 0, loading: true },
|
|
|
|
|
+ todayGas: { value: 0, loading: true },
|
|
|
|
|
+ yearGas: { value: 0, loading: true },
|
|
|
maintain: { value: 0, loading: true },
|
|
maintain: { value: 0, loading: true },
|
|
|
unfilledCount: { value: 0, loading: true },
|
|
unfilledCount: { value: 0, loading: true },
|
|
|
filledCount: { value: 0, loading: true },
|
|
filledCount: { value: 0, loading: true },
|
|
@@ -93,7 +120,8 @@ const summaryCards = computed(() =>
|
|
|
cardConfigs.map((card) => ({
|
|
cardConfigs.map((card) => ({
|
|
|
...card,
|
|
...card,
|
|
|
value: cardState[card.key].value,
|
|
value: cardState[card.key].value,
|
|
|
- loading: cardState[card.key].loading
|
|
|
|
|
|
|
+ loading: cardState[card.key].loading,
|
|
|
|
|
+ decimals: ['utilizationRate', 'todayGas', 'yearGas'].includes(card.key) ? 2 : 0
|
|
|
}))
|
|
}))
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -102,7 +130,51 @@ function toNumber(value: unknown) {
|
|
|
return Number.isFinite(num) ? num : 0
|
|
return Number.isFinite(num) ? num : 0
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function getCreateTimeRange(start: dayjs.Dayjs, end: dayjs.Dayjs) {
|
|
|
|
|
+ return [start.format('YYYY-MM-DD HH:mm:ss'), end.format('YYYY-MM-DD HH:mm:ss')]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function getFirstNumber(data: unknown): number {
|
|
|
|
|
+ if (typeof data === 'number' || typeof data === 'string') return toNumber(data)
|
|
|
|
|
+ if (!data || typeof data !== 'object') return 0
|
|
|
|
|
+
|
|
|
|
|
+ const record = data as Record<string, unknown>
|
|
|
|
|
+ const preferredKeys = [
|
|
|
|
|
+ 'total',
|
|
|
|
|
+ 'value',
|
|
|
|
|
+ 'rate',
|
|
|
|
|
+ 'utilizationRate',
|
|
|
|
|
+ 'totalUtilizationRate',
|
|
|
|
|
+ 'gas',
|
|
|
|
|
+ 'zql',
|
|
|
|
|
+ 'gasInjection',
|
|
|
|
|
+ 'totalGasInjection',
|
|
|
|
|
+ 'totalNaturalGasInjection',
|
|
|
|
|
+ 'totalN2GasInjection'
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ for (const key of preferredKeys) {
|
|
|
|
|
+ if (record[key] !== undefined) return getFirstNumber(record[key])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (Array.isArray(data)) {
|
|
|
|
|
+ return getFirstNumber(data[0])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const firstNumber = Object.values(record).find(
|
|
|
|
|
+ (value) => Number.isFinite(Number(value)) && value !== ''
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return toNumber(firstNumber)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function normalizePercent(value: unknown) {
|
|
|
|
|
+ const num = getFirstNumber(value)
|
|
|
|
|
+ return Math.abs(num) <= 1 ? num * 100 : num
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function setCardValue(key: CardKey, value: unknown) {
|
|
function setCardValue(key: CardKey, value: unknown) {
|
|
|
|
|
+ console.log(key, value)
|
|
|
cardState[key].value = toNumber(value)
|
|
cardState[key].value = toNumber(value)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -127,6 +199,50 @@ async function loadDeviceCard() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+async function loadUtilizationRateCard() {
|
|
|
|
|
+ const keys: CardKey[] = ['utilizationRate']
|
|
|
|
|
+ setCardLoading(keys, true)
|
|
|
|
|
+
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ createTime: getCreateTimeRange(dayjs().startOf('year'), dayjs().endOf('day'))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await IotStatApi.getRhTotalUtilizationRate(params)
|
|
|
|
|
+ setCardValue('utilizationRate', normalizePercent(res))
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取设备利用率失败:', error)
|
|
|
|
|
+ setCardValue('utilizationRate', 0)
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setCardLoading(keys, false)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function loadGasCards() {
|
|
|
|
|
+ const keys: CardKey[] = ['todayGas', 'yearGas']
|
|
|
|
|
+ setCardLoading(keys, true)
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const [todayRes, yearRes] = await Promise.all([
|
|
|
|
|
+ IotStatApi.getRhZqlTotal({
|
|
|
|
|
+ createTime: getCreateTimeRange(dayjs().startOf('day'), dayjs().endOf('day'))
|
|
|
|
|
+ }),
|
|
|
|
|
+ IotStatApi.getRhZqlTotal({
|
|
|
|
|
+ createTime: getCreateTimeRange(dayjs().startOf('year'), dayjs().endOf('day'))
|
|
|
|
|
+ })
|
|
|
|
|
+ ])
|
|
|
|
|
+
|
|
|
|
|
+ setCardValue('todayGas', todayRes)
|
|
|
|
|
+ setCardValue('yearGas', yearRes)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取注气量失败:', error)
|
|
|
|
|
+ setCardValue('todayGas', 0)
|
|
|
|
|
+ setCardValue('yearGas', 0)
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setCardLoading(keys, false)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function loadMaintainCard() {
|
|
async function loadMaintainCard() {
|
|
|
const keys: CardKey[] = ['maintain']
|
|
const keys: CardKey[] = ['maintain']
|
|
|
setCardLoading(keys, true)
|
|
setCardLoading(keys, true)
|
|
@@ -212,6 +328,8 @@ async function loadInspectCards() {
|
|
|
|
|
|
|
|
function loadAllCards() {
|
|
function loadAllCards() {
|
|
|
loadDeviceCard()
|
|
loadDeviceCard()
|
|
|
|
|
+ loadUtilizationRateCard()
|
|
|
|
|
+ loadGasCards()
|
|
|
loadMaintainCard()
|
|
loadMaintainCard()
|
|
|
loadFillCards()
|
|
loadFillCards()
|
|
|
loadMaintainStatusCards()
|
|
loadMaintainStatusCards()
|
|
@@ -233,7 +351,7 @@ onMounted(() => {
|
|
|
工单情况
|
|
工单情况
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="summary-panel__grid grid grid-cols-8 flex-1">
|
|
|
|
|
|
|
+ <div class="summary-panel__grid grid grid-cols-7 flex-1">
|
|
|
<article
|
|
<article
|
|
|
v-for="card in summaryCards"
|
|
v-for="card in summaryCards"
|
|
|
:key="card.key"
|
|
:key="card.key"
|
|
@@ -256,6 +374,7 @@ onMounted(() => {
|
|
|
style="color: #1f5bb8"
|
|
style="color: #1f5bb8"
|
|
|
:start-val="0"
|
|
:start-val="0"
|
|
|
:end-val="card.value"
|
|
:end-val="card.value"
|
|
|
|
|
+ :decimals="card.decimals"
|
|
|
:duration="1200" />
|
|
:duration="1200" />
|
|
|
<span v-else class="summary-card__placeholder">--</span>
|
|
<span v-else class="summary-card__placeholder">--</span>
|
|
|
</div>
|
|
</div>
|