首頁:小卡串資料、今日生產目標串api | 即時告警:預設全選並搜尋

This commit is contained in:
koko 2025-08-08 14:32:29 +08:00
parent 49560b3dd5
commit f4d26271a4
14 changed files with 336 additions and 246 deletions

View File

@ -7,4 +7,5 @@ export const GET_DASHBOARD_ROOM_TEMP_API = `/SituationRoom/GetFormulaRoomStatusD
export const GET_DASHBOARD_ENERGY_API = `/SituationRoom/GetEnergeData`;
export const POST_DASHBOARD_PRODUCT_TARGET_SETTING_API = `/SituationRoom/SetTargetSetting`;
export const GET_DASHBOARD_PRODUCT_TARGET_SETTING_API = `/SituationRoom/GetTargetSetting`
export const GET_DASHBOARD_PRODUCT_HISTORY_API = `/SituationRoom/GetProductionHistory`
export const GET_DASHBOARD_PRODUCT_HISTORY_API = `/SituationRoom/GetProductionHistory`;
export const GET_DASHBOARD_PRODUCT_TASK_API = `/SituationRoom/GetProductionTask`;

View File

@ -9,6 +9,7 @@ import {
POST_DASHBOARD_PRODUCT_TARGET_SETTING_API,
GET_DASHBOARD_PRODUCT_TARGET_SETTING_API,
GET_DASHBOARD_PRODUCT_HISTORY_API,
GET_DASHBOARD_PRODUCT_TASK_API
} from "./api";
import instance from "@/util/request";
import apihandler from "@/util/apihandler";
@ -147,3 +148,12 @@ export const getDashboardProductRecord = async ({ start_time, end_time }) => {
});
};
export const getDashboardProductTask = async () => {
const res = await instance.get(GET_DASHBOARD_PRODUCT_TASK_API);
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
}

View File

@ -151,11 +151,28 @@ const openModal = async (record) => {
}
};
watch(searchParams, (newValue) => {
if (newValue.system_tag) {
watch(
() => ({
isAck: searchParams.value.isAck,
isRecover: searchParams.value.isRecover,
Start_date: searchParams.value.start_created_at,
End_date: searchParams.value.end_created_at,
system_tag: searchParams.value.system_tag,
}),
(val) => {
//
if (
val.isAck !== undefined &&
val.isRecover !== undefined &&
val.Start_date &&
val.End_date &&
val.system_tag
) {
search();
}
});
},
{ immediate: true, deep: true }
);
provide("alert_modal", { model_data, search, updateEditRecord });
provide("alert_table", { openModal, updateEditRecord, dataSource, search, tableLoading });

View File

@ -11,7 +11,7 @@ const changeCheckedItem = () => {
if (checkedItem.value.length === store.subSys.length) {
changeParams({
...searchParams.value,
system_tag: [],
system_tag: [store.subSys[0]?.main_system_tag+`_`+store.subSys[0]?.sub_system_tag],
});
} else {
changeParams({
@ -53,7 +53,7 @@ watch(searchParams, (newValue) => {
if (!newValue.system_tag) {
changeParams({
...newValue,
system_tag: [store.subSys[0]?.main_system_tag+`_`+store.subSys[0]?.sub_system_tag],
system_tag: store.subSys.map(({ main_system_tag, sub_system_tag }) => main_system_tag+`_`+sub_system_tag),
});
}
});

View File

@ -53,18 +53,6 @@ const vesselsData = computed(() => {
return data.map((vessel) => ({
...vessel,
activeTab: getDeviceActiveTab(vessel.name),
SIP: [
{
count: "1",
startTime: "08:00",
endTime: "08:30",
},
{
count: "2",
startTime: "14:00",
endTime: "14:30",
},
],
}));
});
@ -84,12 +72,12 @@ const cookingPotData = computed(() => {
//
const refrigerationData = computed(() => {
return props.realTimeData?.refrigerationData[0] || {};
return props.realTimeData?.refrigerationData || [];
});
//
const meterData = computed(() => {
const data = props.realTimeData?.refrigerationData || [];
const data = props.realTimeData?.meterData || [];
return data.sort((a, b) => a.name.localeCompare(b.name));
});
@ -117,7 +105,7 @@ const valveData = computed(() => {
v-for="(vessel, index) in vesselsData"
:key="index"
:vessel="vessel"
:tabs="tabs"
:tabs="tabs.filter(tab => tab.label !== '品檢')"
/>
</div>
</template>

View File

@ -1,92 +1,35 @@
<script setup>
import { ref, onMounted, computed } from "vue";
import { ref, onMounted, onUnmounted, computed } from "vue";
import { getDashboardProductTask } from "@/apis/dashboard";
import useActiveBtn from "@/hooks/useActiveBtn";
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
//
const recipe_data = ref([]);
recipe_data.value = [
{
id: 1,
productName: "蘋果醋",
status: "調理中",
completionRate: 0.7, // 70%
details: [
{ pot: "第1鍋", location: "包裝室", status: "生產中" },
{ pot: "第2鍋", location: "充填室", status: "生產中" },
{ pot: "第3鍋", location: "調理桶甲", status: "生產中" },
{ pot: "第4鍋", location: "調理桶乙", status: "生產中" },
{ pot: "第5鍋", location: "調理桶丙", status: "生產中" },
{ pot: "第6鍋", location: "調理桶丁", status: "生產中" },
{
pot: "第7鍋",
location: "二重釜大-梅精醋\n二重釜小-加熱",
status: "生產中",
},
{ pot: "第8鍋", location: "", status: "備料" },
],
},
{
id: 2,
productName: "梅子醋",
status: "尚未生產",
completionRate: 0,
details: [],
},
{
id: 3,
productName: "桑葚醋",
status: "尚未生產",
completionRate: 0,
details: [],
},
];
const formulaData = ref([]);
const productData = ref([]);
const loading = ref(false);
//
const finished_data = ref([]);
finished_data.value = [
{
id: 1,
productName: "111018",
status: "已完成",
completionRate: 1, // 100%
details: [
{ pot: "第1鍋", location: "包裝室", status: "生產中" },
{ pot: "第2鍋", location: "充填室", status: "生產中" },
// { pot: "3", location: "調", status: "" },
// { pot: "4", location: "調", status: "" },
// { pot: "5", location: "調", status: "" },
// { pot: "6", location: "調", status: "" },
// {
// pot: "7",
// location: "-\n-",
// status: "",
// },
// { pot: "8", location: "", status: "" },
],
},
{
id: 2,
productName: "121062N",
status: "尚未生產",
completionRate: 0,
details: [],
},
{
id: 3,
productName: "113579",
status: "尚未生產",
completionRate: 0,
details: [],
},
];
let timer = null;
const fetchProductTask = async () => {
loading.value = true;
try {
const res = await getDashboardProductTask();
formulaData.value = res?.data?.formula || [];
productData.value = res?.data?.product || [];
} catch (e) {
formulaData.value = [];
productData.value = [];
} finally {
loading.value = false;
}
};
const production_data = computed(() => {
if (selectedBtn.value?.key === 1) {
return recipe_data.value; //
return formulaData.value;
} else if (selectedBtn.value?.key === 2) {
return finished_data.value; //
return productData.value;
}
return [];
});
@ -116,6 +59,17 @@ onMounted(() => {
active: false,
},
]);
fetchProductTask();
timer = setInterval(() => {
fetchProductTask();
}, 60 * 1000);
});
onUnmounted(() => {
if (timer) {
clearInterval(timer);
timer = null;
}
});
</script>
@ -144,7 +98,7 @@ onMounted(() => {
/>
</template>
<template v-else>
<span class="text-base ">{{ selectedProduct.productName }}</span>
<p class="text-base my-4">{{ selectedProduct.name }}</p>
</template>
</div>
<div className="h-60 overflow-x-auto">
@ -154,27 +108,35 @@ onMounted(() => {
<th>品名</th>
<th>狀態</th>
<th>生產進度</th>
<th>功能</th>
<th v-if="selectedBtn?.key === 1">功能</th>
</tr>
</thead>
<thead v-else>
<tr>
<th>鍋次</th>
<th>位置</th>
<th
v-if="
selectedProduct.details &&
selectedProduct.details.length &&
selectedBtn?.key === 1
"
>
鍋次
</th>
<th>狀態</th>
</tr>
</thead>
<tbody>
<!-- 產品列表 -->
<template v-if="!selectedProduct">
<tr v-for="item in production_data" :key="item.id">
<td>{{ item.productName }}</td>
<tr v-for="item in production_data" :key="item.name">
<td>{{ item.name }}</td>
<td>{{ item.status }}</td>
<td>{{ (item.completionRate * 100).toFixed(0) }}%</td>
<td>
<td>{{ item.progress }}</td>
<td v-if="item.details && item.details.length">
<button
class="btn btn-xs btn-outline-info"
@click="showDetails(item)"
:disabled="!item.details || item.details.length === 0"
>
詳細
</button>
@ -183,14 +145,21 @@ onMounted(() => {
</template>
<!-- 詳細資料 -->
<template v-else>
<tr v-for="(detail, index) in selectedProduct.details" :key="index">
<td>{{ detail.pot }}</td>
<td>{{ detail.location }}</td>
<tr
v-if="selectedProduct.details && selectedProduct.details.length"
v-for="(detail, index) in selectedProduct.details"
:key="index"
>
<td v-if="selectedBtn?.key === 1">{{ detail.batch }}</td>
<td>{{ detail.status }}</td>
</tr>
<tr v-else>
<td colspan="3" class="text-center">無詳細資料</td>
</tr>
</template>
</tbody>
</table>
<div v-if="loading" class="text-center mt-2">載入中...</div>
</div>
</div>
</template>

View File

@ -1,5 +1,6 @@
<script setup>
defineProps({ data: Array });
import { twMerge } from "tailwind-merge";
</script>
<template>
<div class="flex flex-col gap-3">
@ -8,50 +9,62 @@ defineProps({ data: Array });
:key="index"
class="stats shadow bg-slate-200"
>
<div class="stat p-2">
<div class="w-24 stat p-2">
<div class="bg-green-600 rounded-lg p-2 shadow-lg shadow-slate-400">
<div class="text-sm text-slate-100">{{ item.batch }}</div>
<div class="text-sm font-bold text-slate-100">{{ item.product }}</div>
<div class="text-sm text-slate-100">{{ item.batch || "__" }}</div>
<div class="text-sm font-bold text-slate-100">
{{ item.product || "&nbsp;" }}
</div>
</div>
<div class="stat p-2">
<div class="text-sm font-bold text-slate-800">{{ item.equipment }}</div>
</div>
<div class="w-26 stat items-center p-2">
<div class="text-base font-bold text-slate-800">{{ item.name }}</div>
<div class="text-sm text-slate-800">{{ item.status }}</div>
</div>
<div class="stat text-center p-2">
<div class="text-2xl text-slate-800">
<FontAwesomeIcon :icon="['fas', 'temperature-high']" />
</div>
<div class="w-15 stat items-center text-center p-2">
<FontAwesomeIcon
class="text-2xl text-slate-800 mx-auto"
:icon="['fas', 'temperature-high']"
/>
<div class="text-sm text-slate-800">{{ item.temperature }}</div>
</div>
<div class="stat text-center p-2">
<div :class="['text-2xl',
item.sterilization == '殺菌NG' ? 'text-red-700' : 'text-slate-800',
]">
<FontAwesomeIcon :icon="['far', 'clock']" />
</div>
<div :class="['text-sm',
item.sterilization == '殺菌NG' ? 'text-red-700' : 'text-slate-800',
]">{{ item.sterilization }}</div>
</div>
<div class="stat text-center p-2">
<div
:class="[
'text-2xl',
item.sugarStatus == 'warning' ? 'text-red-700' : 'text-slate-800',
'w-15 stat items-center text-center p-2',
item.sterilization == '殺菌完成'
? 'text-green-700'
: 'text-slate-800',
]"
>
<FontAwesomeIcon :icon="['fas', 'tint']" />
<FontAwesomeIcon :icon="['far', 'clock']" class="text-2xl mx-auto" />
<div class="text-sm">
{{ item.sterilization }}
</div>
<div :class="['text-sm',
item.sugarStatus == 'warning' ? 'text-red-700' : 'text-slate-800',
]">{{ item.sugar }}</div>
</div>
<div class="stat text-center p-2">
<div :class="`text-2xl ${item.materialColor}`">
<FontAwesomeIcon :icon="['fas', 'circle']" class="border-2 border-slate-400 rounded-full"/>
<div
:class="[
'w-15 stat items-center text-center p-2',
typeof item.sugar !== 'number' ? 'text-red-700' : 'text-slate-800',
]"
>
<FontAwesomeIcon class="text-2xl mx-auto" :icon="['fas', 'tint']" />
<div class="text-sm">
{{ item.sugar }}
</div>
<div class="text-sm text-slate-800">{{ item.material }}</div>
</div>
<div class="w-15 stat items-center text-center p-2">
<div>
<FontAwesomeIcon
:icon="['fas', 'circle']"
:class="
twMerge(
'text-2xl border-2 border-slate-400 rounded-full',
item.qcResult ? item.qcResult.trim() : 'text-slate-400'
)
"
/>
</div>
<div class="text-sm text-slate-800">{{ item.qcName }}</div>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
<script setup>
const props = defineProps({
pot: Object,
tabs: Array
tabs: Array,
});
</script>
<template>
@ -29,41 +29,105 @@ const props = defineProps({
<div class="p-0">
<div v-if="pot.activeTab2.value === '生產資訊'">
<ul class="leading-7 tracking-wider text-slate-700 px-2">
<li><b>品名:</b> {{ pot.product }}</li>
<li><b>鍋次:</b> {{ pot.batch }}</li>
<li><b>溫度:</b> {{ pot.temperature }}</li>
<li><b>糖度:</b> {{ pot.sugar }}</li>
<li><b>狀態:</b> {{ pot.status }}</li>
<li><b>品名:</b> {{ pot.productInfo?.product }}</li>
<li><b>鍋次:</b> {{ pot.productInfo?.batch || "__" }}</li>
<li><b>溫度:</b> {{ pot.productInfo?.temperature }}</li>
<li><b>糖度:</b> {{ pot.productInfo?.sugar }}</li>
<li><b>狀態:</b> {{ pot.productInfo?.status }}</li>
</ul>
</div>
<div v-else-if="pot.activeTab2.value === '投料進度'">
<div class="h-40 overflow-x-auto">
<table class="table table-sm table-pin-rows">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th class="w-10">順序</th>
<th>動作</th>
<th>原料</th>
<th class="w-20">狀態</th>
</tr>
</thead>
<tbody>
<tr
v-for="(feed, index) in pot.feedProgress"
:key="index"
class="border-0"
>
<th>{{ feed.order }}</th>
<td>{{ feed.action }}</td>
<td>{{ feed.material }}</td>
<td>{{ feed.state }}</td>
</tr>
<tr
v-if="!pot.feedProgress || !pot.feedProgress.length"
class="h-28 border-0"
>
<td colspan="4" class="text-center">無投料進度資料</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="pot.activeTab2.value === '品檢'">
<ul class="leading-7 tracking-wider text-slate-700 px-2">
<li><b>品檢時間:</b> {{ pot.inspectionTime }}</li>
<li><b>風味:</b> {{ pot.flavor }}</li>
<li><b>鹽度:</b> {{ pot.salinity }}</li>
<li><b>酸度:</b> {{ pot.acidity }}</li>
</ul>
<div class="h-40 overflow-x-auto">
<table class="table table-sm table-pin-rows whitespace-nowrap">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th>狀態</th>
<th>品檢時間</th>
<th>風味</th>
<th>色澤</th>
<th>雜異物</th>
<th>鹽度</th>
<th>酸度</th>
<th>糖度</th>
</tr>
</thead>
<tbody>
<tr
v-for="(flow, index) in pot.qcResult"
:key="index"
class="border-0"
>
<th>{{ flow.state }}</th>
<td>{{ flow.time }}</td>
<td>{{ flow.flavor }}</td>
<td>{{ flow.color }}</td>
<td>{{ flow.impurities }}</td>
<td>{{ flow.actual_Salinity }}</td>
<td>{{ flow.actual_PH }}</td>
<td>{{ flow.actual_Brix }}</td>
</tr>
<tr v-if="!pot.qcResult || !pot.qcResult.length" class="h-28 border-0">
<td colspan="8" class="text-center">無品檢資料</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="pot.activeTab2.value === '流量計'">
<div class="">
<table class="table table-sm whitespace-nowrap">
<div class="h-40 overflow-x-auto">
<table class="table table-sm">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th></th>
<th>當前使用量</th>
<th>今日累積量</th>
</tr>
</thead>
<tbody>
<tr class="border-0">
<th class="">補水</th>
<td>{{ pot.waterConsumption }}</td>
<td>100L</td>
<tr
v-for="(flow, index) in pot.flowMeterData"
:key="index"
class="border-0"
>
<th class="">{{ flow.material }}</th>
<td>{{ flow.total }}</td>
</tr>
<tr class="border-0">
<th>補醋</th>
<td>{{ pot.aceticAcidConsumption }}</td>
<td>100L</td>
<tr
v-if="!pot.flowMeterData || !pot.flowMeterData.length"
class="h-28 border-0"
>
<td colspan="2" class="text-center">無流量計資料</td>
</tr>
</tbody>
</table>
@ -80,26 +144,19 @@ const props = defineProps({
</tr>
</thead>
<tbody>
<tr class="border-0">
<th>
第一次
</th>
<td>2025-06-01T08:00:00</td>
<td>2025-06-01T08:30:00</td>
<tr
v-for="(value, index) in pot.sip"
:key="index"
class="border-0">
<th>{{ value.count }}</th>
<td>{{ value.startTime }}</td>
<td>{{ value.endTime }}</td>
</tr>
<tr class="border-0">
<th>
第二次
</th>
<td>2025-06-01T09:00:00</td>
<td>2025-06-01T09:30:00</td>
</tr>
<tr class="border-0">
<th>
第二次
</th>
<td>2025-06-01T10:00:00</td>
<td>2025-06-01T10:30:00</td>
<tr
v-if="!pot.sip || !pot.sip.length"
class="h-28 border-0"
>
<td colspan="3" class="text-center">無SIP資料</td>
</tr>
</tbody>
</table>

View File

@ -1,5 +1,5 @@
<script setup>
defineProps({ data: Array })
defineProps({ data: Array });
</script>
<template>
<div class="flex flex-col gap-3">
@ -8,14 +8,15 @@ defineProps({ data: Array })
:key="index"
class="stats shadow bg-slate-200"
>
<div class="stat p-2">
<div class="text-sm font-bold text-slate-800">{{ item.equipment }}</div>
<div class="text-sm text-slate-800"></div>
</div>
<div class="stat text-center p-2">
<div class="text-sm text-slate-800">
<FontAwesomeIcon :icon="['fas', 'temperature-high']" class="fa-2x" />
<div class="w-26 stat items-center p-2">
<div class="text-sm font-bold text-slate-800">{{ item.name }}</div>
<div class="text-sm text-slate-800">&nbsp;</div>
</div>
<div class="w-15 stat items-center text-center p-2">
<FontAwesomeIcon
:icon="['fas', 'temperature-high']"
class="text-2xl text-slate-800 mx-auto"
/>
<div class="text-sm text-slate-800">{{ item.temperature }}</div>
</div>
</div>

View File

@ -8,20 +8,21 @@ defineProps({ data: Array });
:key="index"
class="stats shadow bg-slate-200"
>
<div class="stat p-2">
<div class="w-24 stat p-2">
<div class="bg-green-600 rounded-lg p-2 shadow-lg shadow-slate-400">
<div class="text-sm text-slate-100">{{ item.batch }}</div>
<div class="text-sm font-bold text-slate-100">{{ item.product }}</div>
</div>
</div>
<div class="stat p-2">
<div class="text-sm font-bold text-slate-800">{{ item.equipment }}</div>
<div class="w-26 stat items-center p-2">
<div class="text-base font-bold text-slate-800">{{ item.name }}</div>
<div class="text-sm text-slate-800">{{ item.status }}</div>
</div>
<div class="stat p-2">
<div class="text-2xl text-slate-800">
<FontAwesomeIcon :icon="['fas', 'temperature-high']" />
</div>
<div class="w-15 stat items-center p-2">
<FontAwesomeIcon
:icon="['fas', 'temperature-high']"
class="text-2xl text-slate-800 mx-auto"
/>
<div class="text-sm text-slate-800">{{ item.temperature }}</div>
</div>
</div>

View File

@ -1,11 +1,17 @@
<script setup>
defineProps({ data: Object });
const props = defineProps({ data: { type: Array, default: () => [] } });
</script>
<template>
<div class="stats shadow bg-slate-200">
<div class="flex flex-col gap-3">
<template v-if="props.data.length">
<div
v-for="(item, index) in props.data"
:key="index"
class="stats shadow bg-slate-200"
>
<div class="stat p-2">
<div class="text-sm font-bold text-slate-800">
{{ data.name }}
{{ item.name }}
</div>
</div>
<div class="stat text-center p-2">
@ -13,8 +19,13 @@ defineProps({ data: Object });
<FontAwesomeIcon :icon="['fas', 'temperature-high']" />
</div>
<div class="text-sm text-slate-800">
{{ data.temperature }}
{{ item.temperature }}
</div>
</div>
</div>
</template>
<template v-else>
<div class="text-center text-slate-400 py-4">無冷藏室資料</div>
</template>
</div>
</template>

View File

@ -10,17 +10,15 @@ import { twMerge } from "tailwind-merge";
</div>
</div>
<div v-for="item in card.groups" :key="item.code" class="stat p-2">
<div class="text-2xl">
<FontAwesomeIcon
:icon="['fas', 'circle']"
:class="
twMerge(
'border-2 border-slate-400 rounded-full',
item.status == 'ON' ? 'text-green-500' : 'text-gray-400'
'text-2xl border-2 border-slate-400 rounded-full',
item.status ? item.status.trim() : 'text-slate-400'
)
"
/>
</div>
<span class="text-sm text-slate-800">{{ item.code }}</span>
</div>
</div>

View File

@ -7,7 +7,7 @@ const props = defineProps({
<template>
<div class="card bg-slate-200 text-accent-content rounded-md w-[25rem]">
<div class="card-body p-3">
<h2 class="card-title">{{ vessel.name }}</h2>
<h2 class="card-title">{{ vessel?.name }}</h2>
<div
role="tablist"
class="tabs tabs-boxed tabs-sm bg-opacity-50 shadow-inner shadow-slate-600"
@ -29,20 +29,21 @@ const props = defineProps({
<div class="p-0">
<div v-if="vessel.activeTab.value === '生產資訊'">
<ul class="leading-7 tracking-wider text-slate-700 px-2">
<li><b>品名:</b> {{ vessel.product }}</li>
<li><b>鍋次:</b> {{ vessel.batch }}</li>
<li><b>狀態:</b> {{ vessel.status }}</li>
<li><b>品名:</b> {{ vessel.productInfo?.product }}</li>
<li><b>鍋次:</b> {{ vessel.productInfo?.batch || "__" }}</li>
<li><b>溫度:</b> {{ vessel.productInfo?.temperature }}</li>
<li><b>狀態:</b> {{ vessel.productInfo?.status }}</li>
</ul>
</div>
<div v-else-if="vessel.activeTab.value === '投料進度'">
<div class="overflow-x-auto">
<table class="table table-sm">
<div class="h-40 overflow-x-auto">
<table class="table table-sm table-pin-rows">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th>順序</th>
<th class="w-10">順序</th>
<th>動作</th>
<th>原料</th>
<th>狀態</th>
<th class="w-20">狀態</th>
</tr>
</thead>
<tbody>
@ -56,17 +57,22 @@ const props = defineProps({
<td>{{ feed.material }}</td>
<td>{{ feed.state }}</td>
</tr>
<tr
v-if="!vessel.feedProgress || !vessel.feedProgress.length"
class="h-28 border-0"
>
<td colspan="4" class="text-center">無投料進度資料</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="vessel.activeTab.value === '流量計'">
<div class="overflow-x-auto">
<table class="table table-sm">
<div class="h-40 overflow-x-auto">
<table class="table table-sm table-pin-rows ">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th></th>
<th>當前使用量</th>
<th>今日累積量</th>
</tr>
</thead>
@ -76,17 +82,22 @@ const props = defineProps({
:key="index"
class="border-0"
>
<th>{{ flow.material }}</th>
<td>{{ flow.current }}</td>
<th class="w-26">{{ flow.material }}</th>
<td>{{ flow.total }}</td>
</tr>
<tr
v-if="!vessel.flowMeterData || !vessel.flowMeterData.length"
class="h-28 border-0"
>
<td colspan="2" class="text-center">無流量計資料</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="vessel.activeTab.value === 'SIP'">
<div class="overflow-x-auto">
<table class="table table-sm">
<div class="h-40 overflow-x-auto">
<table class="table table-sm table-pin-rows">
<thead>
<tr class="border-0 bg-slate-300 text-slate-800">
<th>次數</th>
@ -96,14 +107,20 @@ const props = defineProps({
</thead>
<tbody>
<tr
v-for="(value, index) in vessel.SIP"
v-for="(value, index) in vessel.sip"
:key="index"
class="border-0"
>
<th >{{ value.count }}</th>
<th>{{ value.count }}</th>
<td>{{ value.startTime }}</td>
<td>{{ value.endTime }}</td>
</tr>
<tr
v-if="!vessel.sip || !vessel.sip.length"
class="h-28 border-0"
>
<td colspan="3" class="text-center">無SIP資料</td>
</tr>
</tbody>
</table>
</div>

View File

@ -4,6 +4,13 @@ module.exports = {
"./node_modules/vue-tailwind-datepicker/**/*.js",
],
purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
safelist: [
'text-white',
'text-green-600',
'text-yellow-300',
'text-red-700',
'text-slate-400'
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {