543 lines
16 KiB
Vue
543 lines
16 KiB
Vue
<template>
|
|
<el-row :gutter="20">
|
|
<el-col :span="24">
|
|
<h2>適合每月用電超過5,300度之住宅及小商店評估選用。</h2>
|
|
</el-col>
|
|
<el-col :span="16" :offset="4">
|
|
<table class="">
|
|
<thead>
|
|
<tr>
|
|
<th colspan="8" class="">
|
|
<div style="display: flex; justify-content: space-between">
|
|
標準型時間電價三段式
|
|
<el-button-group>
|
|
<el-button
|
|
type="warning"
|
|
plain
|
|
:icon="Edit"
|
|
v-if="!stand3isEditing"
|
|
@click.stop.prevent="startEditing()"
|
|
>編輯</el-button
|
|
>
|
|
<template v-else>
|
|
<el-button
|
|
type="warning"
|
|
plain
|
|
:icon="CircleCheck"
|
|
@click.stop.prevent="confirmChanges()"
|
|
>確認</el-button
|
|
>
|
|
<el-button
|
|
type="warning"
|
|
plain
|
|
:icon="CircleClose"
|
|
@click.stop.prevent="onCancel()"
|
|
>取消</el-button
|
|
>
|
|
</template>
|
|
</el-button-group>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td colspan="6" class="">分類</td>
|
|
<td class="">夏月<br />(6/1~9/30)</td>
|
|
<td class="">非夏月<br />(夏月以外的時間)</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="6" class="bg-brown">基本電費</td>
|
|
<td colspan="2" rowspan="2" class="bg-brown">按戶計收</td>
|
|
<td colspan="2" class="bg-brown">單相</td>
|
|
<td rowspan="2" class="bg-brown">每戶每月</td>
|
|
<td colspan="2" class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[0]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2" class="bg-brown">三相</td>
|
|
<td colspan="2" class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[1]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="4" class="bg-brown">經常契約</td>
|
|
<td rowspan="4" class="bg-brown">每瓩每月</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[2]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[3]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="4" class="bg-brown">非夏日契約</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[4]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[5]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="4" class="bg-brown">週六半尖峰契約</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[6]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[7]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="4" class="bg-brown">離峰契約</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[8]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-brown">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[9]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="10">流動電費</td>
|
|
<td rowspan="5">週一~週五</td>
|
|
<td class="bg-red">尖峰時間</td>
|
|
<td class="bg-lightred" width="50">夏月</td>
|
|
<td class="bg-lightred" width="120">16:00 ~ 22:00</td>
|
|
<td rowspan="10">每度</td>
|
|
<td class="bg-lightred">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[10]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightred">-</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="2" class="bg-yellow">半尖峰時間</td>
|
|
<td class="bg-lightyellow">夏月</td>
|
|
<td class="bg-lightyellow">09:00 ~ 16:00<br />22:00 ~ 24:00</td>
|
|
<td class="bg-lightyellow">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[11]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightyellow">-</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="bg-lightyellow">非夏月</td>
|
|
<td class="bg-lightyellow">06:00 ~ 11:00<br />14:00 ~ 24:00</td>
|
|
<td class="bg-lightyellow">-</td>
|
|
<td class="bg-lightyellow">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[12]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="2" class="bg-green">離峰時間</td>
|
|
<td class="bg-lightgreen">夏月</td>
|
|
<td class="bg-lightgreen">00:00 ~ 09:00</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[13]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightgreen">-</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="bg-lightgreen">非夏月</td>
|
|
<td class="bg-lightgreen">
|
|
00:00 ~ 06:00<br />
|
|
11:00 ~ 14:00
|
|
</td>
|
|
<td class="bg-lightgreen">-</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[14]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="4">週六</td>
|
|
<td rowspan="2" class="bg-yellow">半尖峰時間</td>
|
|
<td class="bg-lightyellow">夏月</td>
|
|
<td class="bg-lightyellow">09:00 ~ 24:00</td>
|
|
<td class="bg-lightyellow">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[15]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightyellow">-</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="bg-lightyellow">非夏月</td>
|
|
<td class="bg-lightyellow">
|
|
06:00 ~ 11:00<br />
|
|
14:00 ~ 24:00
|
|
</td>
|
|
<td class="bg-lightyellow">-</td>
|
|
<td class="bg-lightyellow">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[16]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td rowspan="2" class="bg-green">離峰時間</td>
|
|
<td class="bg-lightgreen">夏月</td>
|
|
<td class="bg-lightgreen">00:00 ~ 09:00</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[17]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightgreen">-</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="bg-lightgreen">非夏月</td>
|
|
<td class="bg-lightgreen">00:00 ~ 06:00<br />11:00 ~ 14:00</td>
|
|
<td class="bg-lightgreen">-</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[18]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>週日及離峰日</td>
|
|
<td class="bg-green">離峰時間</td>
|
|
<td colspan="2" class="bg-lightgreen">全日</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[19]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
<td class="bg-lightgreen">
|
|
<el-input
|
|
type="number"
|
|
v-model.number="stand3Value[20]"
|
|
style="width: 140px"
|
|
:disabled="!stand3isEditing"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</el-col>
|
|
</el-row>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, watch } from "vue";
|
|
import { Edit, CircleClose, CircleCheck } from "@element-plus/icons-vue";
|
|
import useElecPriceStore from "../stores/useElecPriceStore";
|
|
import axios from "axios";
|
|
|
|
const storeElecPrice = useElecPriceStore();
|
|
|
|
const stand3isEditing = ref(false);
|
|
|
|
const stand3Value = ref<number[]>(new Array(21).fill(null));
|
|
|
|
const beforeEditValues = ref<number[]>([]);
|
|
|
|
const displayNameToIndex: { [key: string]: number | number[] } = {
|
|
基本半尖峰夏月: 4,
|
|
基本離峰夏月: 8,
|
|
基本離峰非夏月: 9,
|
|
基本半尖峰非夏月: 5,
|
|
流動週日離峰夏月: 19,
|
|
流動週日離峰非夏月: 20,
|
|
流動週六離峰非夏月: 18,
|
|
基本經常夏月: 2,
|
|
基本按戶單相: 0,
|
|
基本經常非夏月: 3,
|
|
基本按戶三相: 1,
|
|
流動平日半尖峰非夏月: 12,
|
|
流動平日半尖峰夏月: 11,
|
|
流動平日尖峰夏月: 10,
|
|
流動週六離峰夏月: 17,
|
|
流動週六半尖峰非夏月: 16,
|
|
流動平日離峰夏月: 13,
|
|
流動週六半尖峰夏月: 15,
|
|
流動平日離峰非夏月: 14,
|
|
基本週六半尖峰非夏月: 7,
|
|
基本週六半尖峰夏月: 6,
|
|
};
|
|
|
|
const initialStand3Values = ref<number[]>([]);
|
|
|
|
const startEditing = () => {
|
|
beforeEditValues.value = [...stand3Value.value];
|
|
stand3isEditing.value = true;
|
|
};
|
|
|
|
const resetStand3Values = () => {
|
|
if (initialStand3Values.value.length > 0) {
|
|
stand3Value.value = [...initialStand3Values.value];
|
|
} else {
|
|
stand3Value.value = new Array(21).fill(null);
|
|
}
|
|
};
|
|
|
|
const updatePrice = async (slotPath: string, out: number) => {
|
|
const domain = window.location.origin;
|
|
try {
|
|
console.log("updatePrice",`${domain}/obix/config/${slotPath}/in2/value`)
|
|
const res = await axios.put(
|
|
`${domain}/obix/config/${slotPath}/in2/value`,
|
|
`<real name="in" val="${out}"/> `,
|
|
{
|
|
headers: { "Content-Type": "text/xml" },
|
|
}
|
|
);
|
|
if (res.status === 200) {
|
|
console.log(`成功更新 ${slotPath} 為 ${out}`);
|
|
return true;
|
|
} else {
|
|
console.error(`更新 ${slotPath} 失敗,狀態碼: ${res.status}`);
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error(`更新 ${slotPath} 出錯:`, error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const confirmChanges = async () => {
|
|
stand3isEditing.value = false;
|
|
|
|
const elecData = storeElecPrice.elecData;
|
|
|
|
const failedUpdates: { slotPath: string; out: number }[] = [];
|
|
|
|
if (!elecData || elecData.length === 0) {
|
|
console.warn("useElecPriceStore.elecData 為空,無法更新 stand3Value");
|
|
return;
|
|
}
|
|
|
|
// 循環遍歷所有值,找出修改過的
|
|
for (let i = 0; i < stand3Value.value.length; i++) {
|
|
if (stand3Value.value[i] !== beforeEditValues.value[i]) {
|
|
// 找到對應的 displayName
|
|
const displayName = Object.keys(displayNameToIndex).find((key) => {
|
|
const index = displayNameToIndex[key];
|
|
if (typeof index === "number") {
|
|
return index === i;
|
|
} else if (Array.isArray(index)) {
|
|
return index.includes(i);
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (displayName) {
|
|
// 查找 elecData 中對應的 item
|
|
const item = elecData.find((item) => item.displayName === displayName);
|
|
if (item) {
|
|
// 移除 "slot:/" 前綴
|
|
const slotPath = item.slotPath.startsWith("slot:/")
|
|
? item.slotPath.slice(6) // 移除 "slot:/"
|
|
: item.slotPath; // 如果没有前綴,則保持不變
|
|
// 更新 Niagara
|
|
const success = await updatePrice(slotPath, stand3Value.value[i]);
|
|
if (!success) {
|
|
failedUpdates.push({
|
|
slotPath: item.slotPath,
|
|
out: stand3Value.value[i],
|
|
});
|
|
}
|
|
} else {
|
|
console.warn(`找不到 displayName 為 ${displayName} 的 elecData`);
|
|
}
|
|
} else {
|
|
console.warn(`找不到 index 為 ${i} 的 displayName`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (failedUpdates.length > 0) {
|
|
console.error("以下更新失敗:", failedUpdates);
|
|
} else {
|
|
console.log("所有更新成功");
|
|
}
|
|
|
|
// 更新 initialStand3Values
|
|
initialStand3Values.value = [...stand3Value.value];
|
|
};
|
|
|
|
const onCancel = () => {
|
|
stand3isEditing.value = false;
|
|
resetStand3Values();
|
|
};
|
|
|
|
const updateStand3Values = () => {
|
|
const elecData = storeElecPrice.elecData;
|
|
|
|
if (!elecData || elecData.length === 0) {
|
|
console.warn("useElecPriceStore.elecData 為空,無法更新 stand3Value");
|
|
return;
|
|
}
|
|
|
|
const tempStand3Value = new Array(21).fill(null); // 儲存新值
|
|
|
|
elecData.forEach((item) => {
|
|
const index = displayNameToIndex[item.displayName];
|
|
|
|
if (typeof index === "number") {
|
|
tempStand3Value[index] = item.out as number;
|
|
} else if (Array.isArray(index)) {
|
|
index.forEach((i) => {
|
|
tempStand3Value[i] = item.out as number;
|
|
});
|
|
}
|
|
});
|
|
|
|
// 更新 stand3Value
|
|
stand3Value.value = [...tempStand3Value];
|
|
initialStand3Values.value = [...tempStand3Value]; //緩存一份
|
|
console.log("成功更新 stand3Value:", stand3Value.value);
|
|
};
|
|
|
|
watch(
|
|
() => storeElecPrice.elecData,
|
|
(newValue) => {
|
|
console.log("費率:", newValue);
|
|
updateStand3Values();
|
|
},
|
|
{
|
|
immediate: true,
|
|
deep: true,
|
|
}
|
|
);
|
|
</script>
|
|
|
|
<style scoped>
|
|
h2 {
|
|
font-size: 1.2em;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
th,
|
|
td {
|
|
border: 1px solid #9c9a97;
|
|
padding: 0.5rem;
|
|
text-align: center;
|
|
font-weight: 600;
|
|
background: #e9e2d1;
|
|
}
|
|
th {
|
|
font-size: 14px;
|
|
line-height: 2;
|
|
background: #f3ac0a;
|
|
color: #fff;
|
|
}
|
|
td {
|
|
font-size: 14px;
|
|
line-height: 1.2;
|
|
}
|
|
.bg-brown {
|
|
background: #d8cdb2;
|
|
}
|
|
.bg-red {
|
|
background: #ce1c45;
|
|
color: #fff;
|
|
}
|
|
.bg-lightred {
|
|
background: #fee5dd;
|
|
}
|
|
.bg-green {
|
|
background: #4da62c;
|
|
color: #fff;
|
|
}
|
|
.bg-lightgreen {
|
|
background: #dae9c9;
|
|
}
|
|
.bg-yellow {
|
|
background: #eeb612;
|
|
color: #fff;
|
|
}
|
|
.bg-lightyellow {
|
|
background: #f3e5a3;
|
|
}
|
|
</style> |