265 lines
7.1 KiB
Vue
265 lines
7.1 KiB
Vue
<script setup>
|
|
import { getAssetList, getAssetSingle, deleteAssetItem } from "@/apis/asset";
|
|
import { onMounted, ref, watch, inject, provide, computed } from "vue";
|
|
import useSearchParam from "@/hooks/useSearchParam";
|
|
import AssetTableAddModal from "./AssetTableAddModal.vue";
|
|
import { getOperationCompanyList } from "@/apis/operation";
|
|
import { postMQTTRefresh } from "@/apis/alert";
|
|
import dayjs from "dayjs";
|
|
import { useI18n } from "vue-i18n";
|
|
const { t } = useI18n();
|
|
const { openToast, cancelToastOpen } = inject("app_toast");
|
|
const { companyOptions, departmentList, floors } = inject("asset_modal_options");
|
|
const FILE_BASEURL = window.env?.VITE_FILE_API_BASEURL;
|
|
const { searchParams, changeParams } = useSearchParam();
|
|
|
|
const totalCoordinates = ref({});
|
|
const tableData = ref([]);
|
|
const getAssetData = async () => {
|
|
totalCoordinates.value = {}; // 在獲取新數據之前清空 totalCoordinates
|
|
const res = await getAssetList(searchParams.value?.subSys_id);
|
|
if (res.isSuccess) {
|
|
// 將 device_coordinate 推入對應樓層的座標陣列
|
|
res.data.forEach((d) => {
|
|
const floorGuid = d.floor_guid;
|
|
if (!totalCoordinates.value[floorGuid]) {
|
|
totalCoordinates.value[floorGuid] = [];
|
|
}
|
|
totalCoordinates.value[floorGuid].push(d.device_coordinate);
|
|
});
|
|
tableData.value = res.data.map((d) => ({
|
|
...d,
|
|
key: d.id,
|
|
floor: floors.value.find(({ floor_guid }) => d.floor_guid === floor_guid)
|
|
?.full_name,
|
|
company: companyOptions.value.find(({ id }) => d.operation_id === id),
|
|
department: departmentList.value.find(({ id }) => d.department_id === id)
|
|
?.name,
|
|
buying_date: d?.buying_date
|
|
? dayjs(d?.buying_date).format("YYYY-MM-DD")
|
|
: "",
|
|
created_at: d?.created_at
|
|
? dayjs(d?.created_at).format("YYYY-MM-DD")
|
|
: "",
|
|
}));
|
|
}
|
|
};
|
|
|
|
const refreshMQTT = async () => {
|
|
const res = await postMQTTRefresh();
|
|
if (res.isSuccess) {
|
|
openToast("success", t("msg.mqtt_refresh"));
|
|
} else {
|
|
openToast("error", res.msg, "#outliers_add_table_item");
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
getAssetData();
|
|
});
|
|
|
|
const columns = computed(() => [
|
|
// {
|
|
// title: t("assetManagement.device_number"),
|
|
// key: "device_number",
|
|
// class: "break-all",
|
|
// },
|
|
{
|
|
title: t("assetManagement.device_name"),
|
|
key: "full_name",
|
|
filter: true,
|
|
class: "break-all",
|
|
},
|
|
{
|
|
title: t("assetManagement.asset_number"),
|
|
key: "asset_number",
|
|
},
|
|
{
|
|
title: t("assetManagement.floor"),
|
|
key: "floor",
|
|
filter: true,
|
|
sort: true,
|
|
},
|
|
{
|
|
title: t("assetManagement.department"),
|
|
key: "department",
|
|
filter: true,
|
|
},
|
|
{
|
|
title: t("assetManagement.device_coordinate"),
|
|
key: "device_coordinate",
|
|
},
|
|
{
|
|
title: t("assetManagement.brand_and_modal"),
|
|
key: "brandAndModal",
|
|
},
|
|
{
|
|
title: t("assetManagement.company_and_contact"),
|
|
key: "companyAndContact",
|
|
},
|
|
{
|
|
title: t("assetManagement.buying_date"),
|
|
key: "buying_date",
|
|
sort: true,
|
|
},
|
|
// {
|
|
// title: t("assetManagement.oriFile"),
|
|
// key: "oriFile",
|
|
// },
|
|
{
|
|
title: t("assetManagement.created_at"),
|
|
key: "created_at",
|
|
sort: true,
|
|
},
|
|
{
|
|
title: t("assetManagement.operation"),
|
|
key: "operation",
|
|
width: 200,
|
|
},
|
|
]);
|
|
|
|
watch(
|
|
() => searchParams,
|
|
(newValue) => {
|
|
if (newValue.value?.subSys_id) {
|
|
getAssetData();
|
|
} else {
|
|
tableData.value = [];
|
|
}
|
|
},
|
|
{
|
|
deep: true,
|
|
}
|
|
);
|
|
|
|
// modal
|
|
const editRecord = ref(null);
|
|
const openModal = () => {
|
|
asset_add_table_item.showModal();
|
|
};
|
|
|
|
const onCancel = () => {
|
|
editRecord.value = null;
|
|
asset_add_table_item.close();
|
|
};
|
|
const edit = async (id) => {
|
|
// changeParams({ ...searchParams.value, main_id: record.id });
|
|
const res = await getAssetSingle(id);
|
|
if (res.isSuccess) {
|
|
res.data.oriFile = res.data.oriFile.map((file, index) => ({
|
|
...file,
|
|
key: index,
|
|
src: file.file_url,
|
|
name: file.orgName,
|
|
ext: file.saveName.split(".")[file.saveName.split(".").length - 1],
|
|
}));
|
|
res.data.sub_device = res.data.sub_device?.map(
|
|
({ device_number, points }) => ({
|
|
device_number,
|
|
points,
|
|
})
|
|
);
|
|
editRecord.value = res.data;
|
|
openModal();
|
|
} else {
|
|
openToast("error", res.msg);
|
|
}
|
|
};
|
|
|
|
const remove = async (id) => {
|
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
|
await cancelToastOpen();
|
|
const res = await deleteAssetItem(id);
|
|
if (res.isSuccess) {
|
|
getAssetData();
|
|
openToast("success", t("msg.delete_success"));
|
|
} else {
|
|
openToast("error", res.msg);
|
|
}
|
|
});
|
|
};
|
|
|
|
provide("asset_table_data", {
|
|
totalCoordinates,
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex justify-between items-center mt-10">
|
|
<div class="flex">
|
|
<h3 class="text-xl mr-5">{{ $t("assetManagement.device_list") }}</h3>
|
|
<AssetTableAddModal
|
|
:openModal="openModal"
|
|
:onCancel="onCancel"
|
|
:editRecord="editRecord"
|
|
:getData="getAssetData"
|
|
/>
|
|
</div>
|
|
<button class="btn btn-sm btn-add" @click.prevent="refreshMQTT">
|
|
<font-awesome-icon :icon="['fas', 'cog']" />{{
|
|
$t("alert.reorganization")
|
|
}}
|
|
</button>
|
|
</div>
|
|
<Table :columns="columns" :dataSource="tableData" class="mt-3">
|
|
<template #bodyCell="{ record, column, index }">
|
|
<template v-if="column.key === 'companyAndContact'">
|
|
{{ record.company?.name }} /
|
|
{{ record.company?.contact_person }}
|
|
</template>
|
|
<template v-else-if="column.key === 'brandAndModal'">
|
|
{{ record.brand }} / {{ record.device_model }}
|
|
</template>
|
|
<template v-else-if="column.key === 'oriFile'">
|
|
<span v-if="record.oriFile.length === 0"></span>
|
|
<template v-else>
|
|
<span class="flex flex-wrap gap-1">
|
|
<a
|
|
v-for="file in record.oriFile"
|
|
:href="`${FILE_BASEURL}/${file?.file_url}`"
|
|
target="_blank"
|
|
class="mx-1"
|
|
>
|
|
<img
|
|
v-if="
|
|
file.saveName
|
|
.split('.')
|
|
[file.saveName.split('.').length - 1]?.match(
|
|
/png|jpg|jpeg|gif|bmp|svg/g
|
|
)
|
|
"
|
|
:src="`${FILE_BASEURL}/${file?.file_url}`"
|
|
class="w-14 h-14"
|
|
/>
|
|
<font-awesome-icon
|
|
v-else
|
|
class="mx-auto mb-2 text-4xl text-white"
|
|
:icon="['fas', 'file-word']"
|
|
/>
|
|
</a>
|
|
</span>
|
|
</template>
|
|
</template>
|
|
<template v-else-if="column.key === 'operation'">
|
|
<button
|
|
class="btn btn-sm btn-success text-white mr-2"
|
|
@click.stop.prevent="() => edit(record.main_id)"
|
|
>
|
|
{{ $t("button.edit") }}
|
|
</button>
|
|
<button
|
|
class="btn btn-sm btn-error text-white"
|
|
@click.stop.prevent="() => remove(record.main_id)"
|
|
>
|
|
{{ $t("button.delete") }}
|
|
</button>
|
|
</template>
|
|
<template v-else>
|
|
{{ record[column.key] }}
|
|
</template>
|
|
</template>
|
|
</Table>
|
|
</template>
|
|
|
|
<style lang="scss" scoped></style>
|