設備管理:部門與樓層管理移至設定、小類新稱icon | 能源管理:能匯出excel、報表日期設置 | 運維管理: 廠商管理移至設定
This commit is contained in:
parent
a91c4397a4
commit
80fcfda16c
@ -26,3 +26,5 @@ export const POST_ASSET_DEPARTMENT_API = `/AssetManage/SaveDepartment`;
|
|||||||
export const DELETE_ASSET_DEPARTMENT_API = `/AssetManage/DeleteDepartment`;
|
export const DELETE_ASSET_DEPARTMENT_API = `/AssetManage/DeleteDepartment`;
|
||||||
|
|
||||||
export const GET_ASSET_ELECTYPE_API = `/AssetManage/GetElecType`;
|
export const GET_ASSET_ELECTYPE_API = `/AssetManage/GetElecType`;
|
||||||
|
export const POST_ASSET_ELECTYPE_API = `/AssetManage/SaveElecType`;
|
||||||
|
export const DELETE_ASSET_ELECTYPE_API = `/AssetManage/DeleteElecType`;
|
||||||
|
@ -19,6 +19,8 @@ import {
|
|||||||
POST_ASSET_DEPARTMENT_API,
|
POST_ASSET_DEPARTMENT_API,
|
||||||
DELETE_ASSET_DEPARTMENT_API,
|
DELETE_ASSET_DEPARTMENT_API,
|
||||||
GET_ASSET_ELECTYPE_API,
|
GET_ASSET_ELECTYPE_API,
|
||||||
|
POST_ASSET_ELECTYPE_API,
|
||||||
|
DELETE_ASSET_ELECTYPE_API
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import instance from "@/util/request";
|
import instance from "@/util/request";
|
||||||
import apihandler from "@/util/apihandler";
|
import apihandler from "@/util/apihandler";
|
||||||
@ -246,6 +248,27 @@ export const deleteDepartmentItem = async (id) => {
|
|||||||
export const getElecTypeList = async () => {
|
export const getElecTypeList = async () => {
|
||||||
const res = await instance.post(GET_ASSET_ELECTYPE_API, {});
|
const res = await instance.post(GET_ASSET_ELECTYPE_API, {});
|
||||||
|
|
||||||
|
return apihandler(res.code, res.data, {
|
||||||
|
msg: res.msg,
|
||||||
|
code: res.code,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const postElecTypeList = async ({ name, id }) => {
|
||||||
|
const res = await instance.post(POST_ASSET_ELECTYPE_API, {
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return apihandler(res.code, res.data, {
|
||||||
|
msg: res.msg,
|
||||||
|
code: res.code,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteElecTypeItem = async (id) => {
|
||||||
|
const res = await instance.post(DELETE_ASSET_ELECTYPE_API, { id });
|
||||||
|
|
||||||
return apihandler(res.code, res.data, {
|
return apihandler(res.code, res.data, {
|
||||||
msg: res.msg,
|
msg: res.msg,
|
||||||
code: res.code,
|
code: res.code,
|
||||||
|
@ -2,8 +2,9 @@ export const GET_REALTIME_DIST_API = `/api/Energe/GetRealTimeDistribution`;
|
|||||||
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
|
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
|
||||||
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;
|
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;
|
||||||
|
|
||||||
export const GET_SIDEBAR_API = `/api/Energe/GetEnergySideBar`;
|
export const GET_SIDEBAR_API = `/api/GetSideBar`;
|
||||||
export const GET_SEARCH_API = `/api/Energe/GetFilter`;
|
export const GET_SEARCH_API = `/api/Energe/GetFilter`;
|
||||||
|
|
||||||
export const GET_REPORT_API = `/api/Energe/GetReport`;
|
export const GET_REPORT_API = `/api/Energe/GetReport`;
|
||||||
|
export const GET_Excel_API = `/api/Energe/GetReportExcel`;
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@ import {
|
|||||||
GET_SIDEBAR_API,
|
GET_SIDEBAR_API,
|
||||||
GET_SEARCH_API,
|
GET_SEARCH_API,
|
||||||
GET_REPORT_API,
|
GET_REPORT_API,
|
||||||
|
GET_Excel_API,
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import instance from "@/util/request";
|
import instance, { fileInstance } from "@/util/request";
|
||||||
import apihandler from "@/util/apihandler";
|
import apihandler from "@/util/apihandler";
|
||||||
|
import downloadExcel from "@/util/downloadExcel";
|
||||||
|
|
||||||
export const getRealTimeDist = async () => {
|
export const getRealTimeDist = async () => {
|
||||||
const res = await instance.post(GET_REALTIME_DIST_API);
|
const res = await instance.post(GET_REALTIME_DIST_API);
|
||||||
@ -36,8 +38,8 @@ export const getTaipower = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getEnergySideBar = async () => {
|
export const getSideBar = async (system_type) => {
|
||||||
const res = await instance.post(GET_SIDEBAR_API);
|
const res = await instance.post(GET_SIDEBAR_API, { system_type });
|
||||||
|
|
||||||
return apihandler(res.code, res.data, {
|
return apihandler(res.code, res.data, {
|
||||||
msg: res.msg,
|
msg: res.msg,
|
||||||
@ -76,3 +78,35 @@ export const getReport = async ({
|
|||||||
code: res.code,
|
code: res.code,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getExcel = async ({
|
||||||
|
department,
|
||||||
|
elecType,
|
||||||
|
floor,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
type,
|
||||||
|
}) => {
|
||||||
|
const res = await fileInstance.post(
|
||||||
|
GET_Excel_API,
|
||||||
|
{
|
||||||
|
department,
|
||||||
|
elecType,
|
||||||
|
floor,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
{ responseType: "blob" }
|
||||||
|
);
|
||||||
|
|
||||||
|
return apihandler(
|
||||||
|
res.code,
|
||||||
|
res,
|
||||||
|
{
|
||||||
|
msg: res.msg,
|
||||||
|
code: res.code,
|
||||||
|
},
|
||||||
|
downloadExcel
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { onMounted, ref, watch, computed } from "vue";
|
import { onMounted, ref, watch, computed } from "vue";
|
||||||
import { AUTHPAGES } from "@/constant";
|
import { AUTHPAGES } from "@/constant";
|
||||||
import { getAuth, getAllSysSidebar } from "@/apis/building";
|
import { getAuth, getAllSysSidebar } from "@/apis/building";
|
||||||
import { getEnergySideBar } from "@/apis/energy";
|
import { getSideBar } from "@/apis/energy";
|
||||||
import useBuildingStore from "@/stores/useBuildingStore";
|
import useBuildingStore from "@/stores/useBuildingStore";
|
||||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
@ -42,15 +42,15 @@ const getSubMonitorPage = async (building) => {
|
|||||||
buildingStore.mainSubSys = res.data.history_Main_Systems;
|
buildingStore.mainSubSys = res.data.history_Main_Systems;
|
||||||
menu_array.value = res.data.history_Main_Systems;
|
menu_array.value = res.data.history_Main_Systems;
|
||||||
};
|
};
|
||||||
const getSubEnergyPage = async () => {
|
const getSubPage = async (system_type) => {
|
||||||
const res = await getEnergySideBar();
|
const res = await getSideBar(system_type);
|
||||||
menu_array.value = res.data;
|
menu_array.value = res.data;
|
||||||
};
|
};
|
||||||
const showDrawer = (authCode) => {
|
const showDrawer = (authCode) => {
|
||||||
if (authCode === "PF1") {
|
if (authCode === "PF1") {
|
||||||
getSubMonitorPage();
|
getSubMonitorPage();
|
||||||
} else if (authCode === "PF2") {
|
} else if (authCode === "PF2" || authCode === "PF11") {
|
||||||
getSubEnergyPage();
|
getSubPage(authCode === "PF2" ? "Energy" : "Setting");
|
||||||
}
|
}
|
||||||
currentAuthCode.value = authCode;
|
currentAuthCode.value = authCode;
|
||||||
open.value = true;
|
open.value = true;
|
||||||
@ -105,7 +105,11 @@ onMounted(() => {
|
|||||||
:key="page.authCode"
|
:key="page.authCode"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
v-if="page.authCode === 'PF1' || page.authCode === 'PF2'"
|
v-if="
|
||||||
|
page.authCode === 'PF1' ||
|
||||||
|
page.authCode === 'PF2' ||
|
||||||
|
page.authCode === 'PF11'
|
||||||
|
"
|
||||||
@click="showDrawer(page.authCode)"
|
@click="showDrawer(page.authCode)"
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
@ -115,6 +119,9 @@ onMounted(() => {
|
|||||||
: '',
|
: '',
|
||||||
page.authCode === 'PF2' &&
|
page.authCode === 'PF2' &&
|
||||||
route.fullPath.includes('/energyManagement')
|
route.fullPath.includes('/energyManagement')
|
||||||
|
? 'router-link-active router-link-exact-active'
|
||||||
|
: '',
|
||||||
|
page.authCode === 'PF11' && route.fullPath.includes('/setting')
|
||||||
? 'router-link-active router-link-exact-active'
|
? 'router-link-active router-link-exact-active'
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
@ -168,18 +175,26 @@ onMounted(() => {
|
|||||||
<a-menu-item
|
<a-menu-item
|
||||||
v-for="sub in currentAuthCode === 'PF1'
|
v-for="sub in currentAuthCode === 'PF1'
|
||||||
? main.history_Sub_systems
|
? main.history_Sub_systems
|
||||||
|
: currentAuthCode === 'PF2'
|
||||||
|
? main.sub
|
||||||
: main.sub"
|
: main.sub"
|
||||||
:key="sub.sub_system_tag+`_`+sub.type"
|
:key="sub.sub_system_tag + `_` + sub.type"
|
||||||
@click="() => onClose()"
|
@click="() => onClose()"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{
|
:to="{
|
||||||
name:
|
name:
|
||||||
currentAuthCode === 'PF2' ? 'energyManagement' : 'sub_system',
|
currentAuthCode === 'PF2'
|
||||||
|
? 'energyManagement'
|
||||||
|
: currentAuthCode === 'PF11'
|
||||||
|
? 'setting'
|
||||||
|
: 'sub_system',
|
||||||
params: {
|
params: {
|
||||||
main_system_id: main.main_system_tag,
|
main_system_id: main.main_system_tag,
|
||||||
sub_system_id: sub.sub_system_tag,
|
sub_system_id: sub.sub_system_tag,
|
||||||
...(currentAuthCode === 'PF2' ? { type: sub.type } : { floor_id: 'main' }),
|
...(currentAuthCode === 'PF2' || currentAuthCode === 'PF11'
|
||||||
|
? { type: sub.type }
|
||||||
|
: { floor_id: 'main' }),
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@ -61,4 +61,10 @@ export const AUTHPAGES = [
|
|||||||
pageName: "ProductSetting",
|
pageName: "ProductSetting",
|
||||||
navigate: "/productSetting",
|
navigate: "/productSetting",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
authCode: "PF11",
|
||||||
|
icon: "cog",
|
||||||
|
pageName: "Setting",
|
||||||
|
navigate: "/Setting",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -8,6 +8,7 @@ import AssetManagement from "@/views/AssetManagement/AssetManagement.vue";
|
|||||||
import AlertManagement from "@/views/alert/AlertManagement.vue";
|
import AlertManagement from "@/views/alert/AlertManagement.vue";
|
||||||
import ProductSetting from "@/views/productSetting/ProductSetting.vue";
|
import ProductSetting from "@/views/productSetting/ProductSetting.vue";
|
||||||
import EnergyManagement from "@/views/energyManagement/EnergyManagement.vue";
|
import EnergyManagement from "@/views/energyManagement/EnergyManagement.vue";
|
||||||
|
import SettingManagement from "@/views/setting/SettingManagement.vue";
|
||||||
import Login from "@/views/login/Login.vue";
|
import Login from "@/views/login/Login.vue";
|
||||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||||
import useGetCookie from "@/hooks/useGetCookie";
|
import useGetCookie from "@/hooks/useGetCookie";
|
||||||
@ -84,6 +85,11 @@ const router = createRouter({
|
|||||||
name: "energyManagement",
|
name: "energyManagement",
|
||||||
component: EnergyManagement,
|
component: EnergyManagement,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/setting/:main_system_id/:sub_system_id/:type",
|
||||||
|
name: "setting",
|
||||||
|
component: SettingManagement,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/mytestfile/mjm",
|
path: "/mytestfile/mjm",
|
||||||
name: "mytestfile",
|
name: "mytestfile",
|
||||||
|
@ -4,12 +4,14 @@ import AssetMainList from "./components/AssetMainList.vue";
|
|||||||
import AssetSubList from "./components/AssetSubList.vue";
|
import AssetSubList from "./components/AssetSubList.vue";
|
||||||
import AssetTable from "./components/AssetTable.vue";
|
import AssetTable from "./components/AssetTable.vue";
|
||||||
import { getOperationCompanyList } from "@/apis/operation";
|
import { getOperationCompanyList } from "@/apis/operation";
|
||||||
import { getIOTSchema, getElecTypeList } from "@/apis/asset";
|
import { getDepartmentList, getIOTSchema, getElecTypeList, getAssetFloorList } from "@/apis/asset";
|
||||||
import useSearchParam from "@/hooks/useSearchParam";
|
import useSearchParam from "@/hooks/useSearchParam";
|
||||||
const { searchParams, changeParams } = useSearchParam();
|
const { searchParams, changeParams } = useSearchParam();
|
||||||
const companyOptions = ref([]);
|
const companyOptions = ref([]);
|
||||||
const iotSchemaOptions = ref([]);
|
const iotSchemaOptions = ref([]);
|
||||||
const elecTypeOptions = ref([]);
|
const elecTypeOptions = ref([]);
|
||||||
|
const departmentList = ref([]);
|
||||||
|
const floors = ref([]);
|
||||||
const getCompany = async () => {
|
const getCompany = async () => {
|
||||||
const res = await getOperationCompanyList();
|
const res = await getOperationCompanyList();
|
||||||
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
@ -22,10 +24,20 @@ const getElecType = async () => {
|
|||||||
const res = await getElecTypeList();
|
const res = await getElecTypeList();
|
||||||
elecTypeOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
elecTypeOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
};
|
};
|
||||||
|
const getDepartment = async () => {
|
||||||
|
const res = await getDepartmentList();
|
||||||
|
departmentList.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
|
};
|
||||||
|
const getFloors = async () => {
|
||||||
|
const res = await getAssetFloorList();
|
||||||
|
floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCompany();
|
getCompany();
|
||||||
getElecType();
|
getElecType();
|
||||||
|
getDepartment();
|
||||||
|
getFloors();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -44,6 +56,8 @@ provide("asset_modal_options", {
|
|||||||
companyOptions,
|
companyOptions,
|
||||||
iotSchemaOptions,
|
iotSchemaOptions,
|
||||||
elecTypeOptions,
|
elecTypeOptions,
|
||||||
|
departmentList,
|
||||||
|
floors,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mainSystem = ref([]);
|
const mainSystem = ref([]);
|
||||||
|
const updateFileList = (files) => {
|
||||||
|
formState.value.icon = files;
|
||||||
|
};
|
||||||
const getMainSystems = async () => {
|
const getMainSystems = async () => {
|
||||||
const res = await getAssetMainList();
|
const res = await getAssetMainList();
|
||||||
mainSystem.value = res.data.map((d) => ({ ...d, key: d.id }));
|
mainSystem.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
@ -33,6 +36,7 @@ const formState = ref({
|
|||||||
system_key: "",
|
system_key: "",
|
||||||
system_value: "",
|
system_value: "",
|
||||||
system_parent_id: 0,
|
system_parent_id: 0,
|
||||||
|
icon: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
@ -40,6 +44,7 @@ const resetForm = () => {
|
|||||||
system_key: "",
|
system_key: "",
|
||||||
system_value: "",
|
system_value: "",
|
||||||
system_parent_id: 0,
|
system_parent_id: 0,
|
||||||
|
icon: [],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,6 +125,15 @@ const onOk = async () => {
|
|||||||
</span></template
|
</span></template
|
||||||
>
|
>
|
||||||
</Select>
|
</Select>
|
||||||
|
<Upload
|
||||||
|
name="icon"
|
||||||
|
:fileList="formState.icon"
|
||||||
|
:getFileList="updateFileList"
|
||||||
|
:multiple="false"
|
||||||
|
:baseUrl="`${BASEURL}/upload/graph_manage`"
|
||||||
|
>
|
||||||
|
<template #topLeft>{{ $t("operation.upload_file") }}</template>
|
||||||
|
</Upload>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
<template #modalAction>
|
<template #modalAction>
|
||||||
|
@ -4,7 +4,6 @@ import * as yup from "yup";
|
|||||||
import "yup-phone-lite";
|
import "yup-phone-lite";
|
||||||
import useSearchParam from "@/hooks/useSearchParam";
|
import useSearchParam from "@/hooks/useSearchParam";
|
||||||
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
import AssetTableModalLeftInfoIoT from "./AssetTableModalLeftInfoIoT.vue";
|
||||||
import AssetTableModalLeftInfoDept from "./AssetTableModalLeftInfoDept.vue";
|
|
||||||
import AssetTableModalLeftInfoGraph from "./AssetTableModalLeftInfoGraph.vue";
|
import AssetTableModalLeftInfoGraph from "./AssetTableModalLeftInfoGraph.vue";
|
||||||
import AssetTableModalLeftInfoMQTT from "./AssetTableModalLeftInfoMQTT.vue";
|
import AssetTableModalLeftInfoMQTT from "./AssetTableModalLeftInfoMQTT.vue";
|
||||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||||
@ -16,7 +15,7 @@ const { searchParams, changeParams } = useSearchParam();
|
|||||||
const { updateLeftFields, formErrorMsg, formState } = inject(
|
const { updateLeftFields, formErrorMsg, formState } = inject(
|
||||||
"asset_table_modal_form"
|
"asset_table_modal_form"
|
||||||
);
|
);
|
||||||
const { companyOptions, iotSchemaOptions, elecTypeOptions } = inject("asset_modal_options");
|
const { companyOptions, iotSchemaOptions, elecTypeOptions, departmentList } = inject("asset_modal_options");
|
||||||
const store = useUserInfoStore();
|
const store = useUserInfoStore();
|
||||||
let schema = {
|
let schema = {
|
||||||
full_name: yup.string().nullable(true),
|
full_name: yup.string().nullable(true),
|
||||||
@ -53,7 +52,7 @@ onBeforeMount(() => {
|
|||||||
operation_id: 0,
|
operation_id: 0,
|
||||||
response_schema_id: 0,
|
response_schema_id: 0,
|
||||||
department_id: 0,
|
department_id: 0,
|
||||||
elec_id: null,
|
elec_type_id: null,
|
||||||
asset_number: "",
|
asset_number: "",
|
||||||
topic: "",
|
topic: "",
|
||||||
sub_device: [],
|
sub_device: [],
|
||||||
@ -115,7 +114,17 @@ watch(
|
|||||||
</span></template
|
</span></template
|
||||||
></Input
|
></Input
|
||||||
>
|
>
|
||||||
<AssetTableModalLeftInfoDept />
|
<div class="flex items-center w-72">
|
||||||
|
<Select
|
||||||
|
:value="formState"
|
||||||
|
selectClass="border-info focus-within:border-info"
|
||||||
|
name="department_id"
|
||||||
|
Attribute="name"
|
||||||
|
:options="departmentList"
|
||||||
|
>
|
||||||
|
<template #topLeft>{{ $t("assetManagement.department") }}</template>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<Input
|
<Input
|
||||||
:value="formState"
|
:value="formState"
|
||||||
width="290"
|
width="290"
|
||||||
@ -147,7 +156,7 @@ watch(
|
|||||||
<Select
|
<Select
|
||||||
:value="formState"
|
:value="formState"
|
||||||
selectClass="border-info focus-within:border-info"
|
selectClass="border-info focus-within:border-info"
|
||||||
name="elec_id"
|
name="elec_type_id"
|
||||||
Attribute="name"
|
Attribute="name"
|
||||||
:options="elecTypeOptions"
|
:options="elecTypeOptions"
|
||||||
:required="true"
|
:required="true"
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
import { onMounted, ref, inject, onBeforeMount, watch, computed } from "vue";
|
||||||
import EffectScatter from "@/components/chart/EffectScatter.vue";
|
import EffectScatter from "@/components/chart/EffectScatter.vue";
|
||||||
import {
|
|
||||||
getAssetFloorList,
|
|
||||||
postAssetFloor,
|
|
||||||
deleteAssetFloor,
|
|
||||||
} from "@/apis/asset";
|
|
||||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
|
||||||
import useBuildingStore from "@/stores/useBuildingStore";
|
import useBuildingStore from "@/stores/useBuildingStore";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
|
||||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||||
const { totalCoordinates } = inject("asset_table_data");
|
const { totalCoordinates } = inject("asset_table_data");
|
||||||
|
const { floors } = inject("asset_modal_options");
|
||||||
const { updateRightFields, formErrorMsg, formState } = inject(
|
const { updateRightFields, formErrorMsg, formState } = inject(
|
||||||
"asset_table_modal_form"
|
"asset_table_modal_form"
|
||||||
);
|
);
|
||||||
@ -34,7 +28,6 @@ onBeforeMount(() => {
|
|||||||
|
|
||||||
const asset_floor_chart = ref(null);
|
const asset_floor_chart = ref(null);
|
||||||
const currentFloor = ref(null);
|
const currentFloor = ref(null);
|
||||||
const selectedOption = ref("add");
|
|
||||||
const parsedCoordinates = ref(null);
|
const parsedCoordinates = ref(null);
|
||||||
|
|
||||||
const defaultOption = (map, data = []) => {
|
const defaultOption = (map, data = []) => {
|
||||||
@ -45,7 +38,10 @@ const defaultOption = (map, data = []) => {
|
|||||||
name: coordString,
|
name: coordString,
|
||||||
value: coordinate,
|
value: coordinate,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: coordString === formState.value.device_coordinate ? "#0000FF" : "#b02a02",
|
color:
|
||||||
|
coordString === formState.value.device_coordinate
|
||||||
|
? "#0000FF"
|
||||||
|
: "#b02a02",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -75,13 +71,14 @@ const defaultOption = (map, data = []) => {
|
|||||||
watch(currentFloor, (newValue) => {
|
watch(currentFloor, (newValue) => {
|
||||||
if (newValue?.floor_map_name) {
|
if (newValue?.floor_map_name) {
|
||||||
const coordinates =
|
const coordinates =
|
||||||
(totalCoordinates.value?.[newValue.floor_guid]?.filter(
|
totalCoordinates.value?.[newValue.floor_guid]?.filter(
|
||||||
(coord) => coord !== ""
|
(coord) => coord !== ""
|
||||||
) || []);
|
) || [];
|
||||||
|
|
||||||
parsedCoordinates.value = coordinates.length > 0
|
parsedCoordinates.value =
|
||||||
? coordinates.map((coord) => JSON.parse(coord))
|
coordinates.length > 0
|
||||||
: [];
|
? coordinates.map((coord) => JSON.parse(coord))
|
||||||
|
: [];
|
||||||
|
|
||||||
asset_floor_chart.value.updateSvg(
|
asset_floor_chart.value.updateSvg(
|
||||||
{
|
{
|
||||||
@ -92,12 +89,6 @@ watch(currentFloor, (newValue) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const floors = ref([]);
|
|
||||||
|
|
||||||
const getFloors = async () => {
|
|
||||||
const res = await getAssetFloorList();
|
|
||||||
floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
formState,
|
formState,
|
||||||
@ -120,136 +111,31 @@ const getCoordinate = (position) => {
|
|||||||
formState.value.device_coordinate = JSON.stringify(position);
|
formState.value.device_coordinate = JSON.stringify(position);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getFloors();
|
|
||||||
});
|
|
||||||
|
|
||||||
// modal
|
|
||||||
const openModal = () => {
|
|
||||||
if (selectedOption.value === "add") {
|
|
||||||
FloorFormState.value = {
|
|
||||||
full_name: "",
|
|
||||||
floorFile: [],
|
|
||||||
};
|
|
||||||
} else if (selectedOption.value === "edit") {
|
|
||||||
const floor = floors.value.find(
|
|
||||||
(f) => f.floor_guid === formState.value.floor_guid
|
|
||||||
);
|
|
||||||
if (floor) {
|
|
||||||
console.log("floor", floor);
|
|
||||||
FloorFormState.value = {
|
|
||||||
full_name: floor.full_name,
|
|
||||||
floorFile: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asset_add_floor.showModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
const form = ref(null);
|
|
||||||
const FloorFormState = ref({
|
|
||||||
full_name: "",
|
|
||||||
floorFile: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const floorScheme = yup.object({
|
|
||||||
full_name: yup.string().required(t("button.required")),
|
|
||||||
floorFile: yup.array(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateFileList = (files) => {
|
|
||||||
console.log("file", files);
|
|
||||||
FloorFormState.value.floorFile = files;
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
|
||||||
formErrorMsg: floorFormErrorMsg,
|
|
||||||
handleSubmit,
|
|
||||||
handleErrorReset,
|
|
||||||
updateScheme,
|
|
||||||
} = useFormErrorMessage(floorScheme);
|
|
||||||
const onOk = async () => {
|
|
||||||
const value = handleSubmit(floorScheme, FloorFormState.value);
|
|
||||||
const formData = new FormData(form.value);
|
|
||||||
formData.append("floor_guid", selectedOption.value === "add" ? null :currentFloor.value.floor_guid);
|
|
||||||
formData.append("building_tag", store.selectedBuilding.building_tag);
|
|
||||||
formData.append("initMapName", FloorFormState.value.floorFile[0]?.name);
|
|
||||||
formData.append("mapFile", FloorFormState.value.floorFile[0]);
|
|
||||||
formData.delete("floorFile");
|
|
||||||
for (let [key, value] of formData) {
|
|
||||||
console.log(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await postAssetFloor(formData);
|
|
||||||
if (res.isSuccess) {
|
|
||||||
getFloors();
|
|
||||||
onCancel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const onDelete = async () => {
|
|
||||||
openToast("warning", t("msg.sure_to_delete"), "#asset_add_table_item", async () => {
|
|
||||||
await cancelToastOpen();
|
|
||||||
const res = await deleteAssetFloor({
|
|
||||||
floor_guid: formState.value.floor_guid,
|
|
||||||
});
|
|
||||||
if (res.isSuccess) {
|
|
||||||
getFloors();
|
|
||||||
openToast("success", t("msg.delete_success"), "#asset_add_table_item");
|
|
||||||
} else {
|
|
||||||
openToast("error", res.msg, "#asset_add_table_item");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onCancel = () => {
|
|
||||||
FloorFormState.value = {
|
|
||||||
full_name: "",
|
|
||||||
floorFile: [],
|
|
||||||
};
|
|
||||||
asset_add_floor.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- 平面圖 -->
|
<!-- 平面圖 -->
|
||||||
|
|
||||||
<div class="flex gap-4 mb-5">
|
<div class="flex gap-4 mb-5">
|
||||||
<div className="join w-80 mb-4">
|
<Select
|
||||||
<Select
|
:value="formState"
|
||||||
:value="formState"
|
selectClass="border-info focus-within:border-info"
|
||||||
selectClass="border-info focus-within:border-info rounded-r-none"
|
name="floor_guid"
|
||||||
name="floor_guid"
|
Attribute="full_name"
|
||||||
Attribute="full_name"
|
:options="floors"
|
||||||
:options="floors"
|
:isBottomLabelExist="false"
|
||||||
:isBottomLabelExist="false"
|
>
|
||||||
>
|
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
||||||
<template #topLeft>{{ $t("assetManagement.floor") }}</template>
|
</Select>
|
||||||
</Select>
|
|
||||||
<select
|
|
||||||
v-model="selectedOption"
|
|
||||||
className="select border-info focus-within:border-info join-item mt-11"
|
|
||||||
>
|
|
||||||
<option value="add" selected>{{ $t("button.add") }}</option>
|
|
||||||
<option value="edit">{{ $t("button.edit") }}</option>
|
|
||||||
<option value="delete">{{ $t("button.delete") }}</option>
|
|
||||||
</select>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-success join-item mt-11"
|
|
||||||
@click="selectedOption === 'delete' ? onDelete() : openModal()"
|
|
||||||
:aria-label="$t('button.submit')"
|
|
||||||
>
|
|
||||||
{{ $t("button.submit") }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<Input
|
<Input
|
||||||
:value="formState"
|
:value="formState"
|
||||||
width="270"
|
width="270"
|
||||||
name="device_coordinate"
|
name="device_coordinate"
|
||||||
:disabled="true"
|
:disabled="true"
|
||||||
>
|
>
|
||||||
<template #topLeft>{{ $t("assetManagement.device_coordinate") }}</template>
|
<template #topLeft>{{
|
||||||
|
$t("assetManagement.device_coordinate")
|
||||||
|
}}</template>
|
||||||
<template #bottomLeft
|
<template #bottomLeft
|
||||||
><span class="text-error text-base">
|
><span class="text-error text-base">
|
||||||
{{ formErrorMsg.device_coordinate }}
|
{{ formErrorMsg.device_coordinate }}
|
||||||
@ -276,47 +162,6 @@ const onCancel = () => {
|
|||||||
<p class="text-2xl">{{ $t("assetManagement.add_floor_text") }}</p>
|
<p class="text-2xl">{{ $t("assetManagement.add_floor_text") }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal
|
|
||||||
id="asset_add_floor"
|
|
||||||
:title="t('assetManagement.floor_plan')"
|
|
||||||
:onCancel="onCancel"
|
|
||||||
width="400"
|
|
||||||
>
|
|
||||||
<template #modalContent>
|
|
||||||
<form ref="form">
|
|
||||||
<Input :value="FloorFormState" width="270" name="full_name">
|
|
||||||
<template #topLeft>{{ $t("assetManagement.system_name") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ floorFormErrorMsg.full_name }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Upload
|
|
||||||
name="floorFile"
|
|
||||||
:fileList="FloorFormState.floorFile"
|
|
||||||
:getFileList="updateFileList"
|
|
||||||
:multiple="false"
|
|
||||||
class="col-span-2"
|
|
||||||
formats="svg"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
|
||||||
</Upload>
|
|
||||||
</form>
|
|
||||||
</template>
|
|
||||||
<template #modalAction>
|
|
||||||
<button
|
|
||||||
type="reset"
|
|
||||||
class="btn btn-outline-success mr-2"
|
|
||||||
@click.prevent="onCancel"
|
|
||||||
>
|
|
||||||
{{ $t("button.cancel") }}
|
|
||||||
</button>
|
|
||||||
<button type="submit" class="btn btn-outline-success" @click="onOk">
|
|
||||||
{{ $t("button.submit") }}
|
|
||||||
</button>
|
|
||||||
</template></Modal
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
getAssetFloorList,
|
getAssetFloorList,
|
||||||
getElecTypeList,
|
getElecTypeList,
|
||||||
} from "@/apis/asset";
|
} from "@/apis/asset";
|
||||||
import { getReport } from "@/apis/energy";
|
import { getReport, getExcel } from "@/apis/energy";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -83,6 +83,10 @@ const onSearch = async () => {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onExcel = async () => {
|
||||||
|
const res = await getExcel(formState.value);
|
||||||
|
};
|
||||||
|
|
||||||
// 監聽部門選取
|
// 監聽部門選取
|
||||||
watch(
|
watch(
|
||||||
selectedDeptItems,
|
selectedDeptItems,
|
||||||
@ -176,7 +180,7 @@ onMounted(() => {
|
|||||||
<font-awesome-icon :icon="['fas', 'search']" class="text-lg" />
|
<font-awesome-icon :icon="['fas', 'search']" class="text-lg" />
|
||||||
{{ $t("button.search") }}
|
{{ $t("button.search") }}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-export" @click.stop.prevent="search">
|
<button class="btn btn-export" @click.stop.prevent="onExcel">
|
||||||
<font-awesome-icon :icon="['fas', 'download']" class="text-lg" />
|
<font-awesome-icon :icon="['fas', 'download']" class="text-lg" />
|
||||||
{{ $t("button.export") }}
|
{{ $t("button.export") }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import Table from "@/components/customUI/Table.vue";
|
import Table from "@/components/customUI/Table.vue";
|
||||||
import { inject, computed, ref } from "vue";
|
import { inject, computed, ref } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { tableData, loading } = inject("energy_table_data");
|
const { tableData, loading } = inject("energy_table_data");
|
||||||
|
const route = useRoute();
|
||||||
// 預設的欄位
|
// 預設的欄位
|
||||||
const defaultColumns = ref([
|
const defaultColumns = ref([
|
||||||
{
|
{
|
||||||
@ -29,63 +30,68 @@ const defaultColumns = ref([
|
|||||||
|
|
||||||
// 動態計算欄位
|
// 動態計算欄位
|
||||||
const columns = computed(() => {
|
const columns = computed(() => {
|
||||||
if (!tableData.value || tableData.value.length === 0) {
|
|
||||||
return [...defaultColumns.value, {
|
|
||||||
title: t("energy.subtotal"),
|
|
||||||
key: "subtotal",
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
// 複製預設欄位
|
|
||||||
const dynamicColumns = [...defaultColumns.value];
|
const dynamicColumns = [...defaultColumns.value];
|
||||||
|
|
||||||
// 取得第一個資料的 data 屬性,以此為準
|
if (tableData.value && tableData.value.length > 0) {
|
||||||
const firstDataItem = tableData.value[0];
|
const firstDataItem = tableData.value[0];
|
||||||
if (firstDataItem && firstDataItem.data) {
|
if (firstDataItem && firstDataItem.data) {
|
||||||
// 根據 data 屬性動態生成欄位
|
firstDataItem.data.forEach((item, index) => {
|
||||||
firstDataItem.data.forEach((item, index) => {
|
let formatString = "MM/DD"; // 預設格式
|
||||||
// 使用 dayjs 和 format 格式化日期
|
switch (route.params.type) {
|
||||||
const formattedTime = dayjs(item.time).format("MM-DD");
|
case "3":
|
||||||
dynamicColumns.push({
|
formatString = "YYYY/MM";
|
||||||
title: formattedTime,
|
break;
|
||||||
key: `data[${index}].value`,
|
case "4":
|
||||||
|
formatString = "YYYY";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
formatString = "MM/DD"; // case 1 和 case 2 都是 "MM-DD"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const formattedTime = dayjs(item.time).format(formatString);
|
||||||
|
// 為每個 data 欄位創建一個唯一的 key,例如 "data_0", "data_1" 等
|
||||||
|
dynamicColumns.push({
|
||||||
|
title: formattedTime,
|
||||||
|
key: `data_${index}`,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicColumns.push({
|
dynamicColumns.push({
|
||||||
title: t("energy.subtotal"),
|
title: t("energy.subtotal"),
|
||||||
key: "subtotal",
|
key: "subtotal",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return dynamicColumns;
|
return dynamicColumns;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 動態調整 subtotal 值和新增 data 屬性
|
||||||
// 動態調整 subtotal 值
|
|
||||||
const dataSource = computed(() => {
|
const dataSource = computed(() => {
|
||||||
|
if (!tableData.value || tableData.value.length === 0) return [];
|
||||||
|
|
||||||
if(!tableData.value || tableData.value.length === 0) return [];
|
return tableData.value.map((item) => {
|
||||||
|
let subtotalValue = 0;
|
||||||
return tableData.value.map(item => {
|
const newData = {}; // 用於儲存 data 的值,方便 Table 組件讀取
|
||||||
let subtotalValue = 0;
|
if (item.data && item.data.length > 0) {
|
||||||
if(item.data && item.data.length > 0) {
|
item.data.forEach((dataItem, index) => {
|
||||||
item.data.forEach((dataItem) => {
|
const value = parseFloat(dataItem.value || 0);
|
||||||
subtotalValue += parseFloat(dataItem.value || 0);
|
subtotalValue += value;
|
||||||
});
|
// 將值儲存在 newData 中,key 與 columns 中的 key 對應
|
||||||
}
|
newData[`data_${index}`] = dataItem.value;
|
||||||
return {
|
});
|
||||||
...item,
|
}
|
||||||
subtotal: subtotalValue.toFixed(2)
|
return {
|
||||||
}
|
...item,
|
||||||
})
|
...newData, // 將 data 的值合併到 item 中
|
||||||
})
|
subtotal: subtotalValue.toFixed(2),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Table :columns="columns" :dataSource="dataSource" :loading="loading"></Table>
|
<Table :columns="columns" :dataSource="dataSource" :loading="loading"></Table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
@ -26,9 +26,7 @@ const updateDataSource = (data) => {
|
|||||||
finish_time: d?.finish_time
|
finish_time: d?.finish_time
|
||||||
? dayjs(d?.finish_time).format("YYYY-MM-DD")
|
? dayjs(d?.finish_time).format("YYYY-MM-DD")
|
||||||
: "",
|
: "",
|
||||||
updated_at: d?.updated_at
|
updated_at: d?.updated_at ? dayjs(d?.updated_at).format("YYYY-MM-DD") : "",
|
||||||
? dayjs(d?.updated_at).format("YYYY-MM-DD")
|
|
||||||
: "",
|
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,7 +103,7 @@ const getAllOptions = async (id = "") => {
|
|||||||
|
|
||||||
const openModal = async (id = "") => {
|
const openModal = async (id = "") => {
|
||||||
console.log("open modal", id);
|
console.log("open modal", id);
|
||||||
if(searchParams.value?.work_type < 3){
|
if (searchParams.value?.work_type < 3) {
|
||||||
getAllOptions(id);
|
getAllOptions(id);
|
||||||
}
|
}
|
||||||
operation_action_item.showModal();
|
operation_action_item.showModal();
|
||||||
@ -115,11 +113,7 @@ const tableLoading = ref(false);
|
|||||||
const search = async () => {
|
const search = async () => {
|
||||||
tableLoading.value = true;
|
tableLoading.value = true;
|
||||||
let res;
|
let res;
|
||||||
if (searchParams.value?.work_type < 3) {
|
res = await getOperationRecord(searchParams.value);
|
||||||
res = await getOperationRecord(searchParams.value);
|
|
||||||
} else {
|
|
||||||
res = await getOperationCompanyList();
|
|
||||||
}
|
|
||||||
updateDataSource(res.data);
|
updateDataSource(res.data);
|
||||||
tableLoading.value = false;
|
tableLoading.value = false;
|
||||||
};
|
};
|
||||||
|
@ -61,10 +61,7 @@ watch(
|
|||||||
([newValue, newSelected]) => {
|
([newValue, newSelected]) => {
|
||||||
const keys = Object.keys(newValue).filter((v) => v !== "search_type");
|
const keys = Object.keys(newValue).filter((v) => v !== "search_type");
|
||||||
|
|
||||||
if (newValue.work_type === "3") {
|
if (newSelected) {
|
||||||
isSearchDisabled.value = false;
|
|
||||||
initSubmit(true);
|
|
||||||
} else if (newSelected) {
|
|
||||||
isSearchDisabled.value = !searchParams.value.sub_system_tag;
|
isSearchDisabled.value = !searchParams.value.sub_system_tag;
|
||||||
initSubmit(searchParams.value.sub_system_tag);
|
initSubmit(searchParams.value.sub_system_tag);
|
||||||
}
|
}
|
||||||
@ -81,7 +78,6 @@ watch(
|
|||||||
:items="submitBtns"
|
:items="submitBtns"
|
||||||
:withLine="false"
|
:withLine="false"
|
||||||
:withBtnClass="true"
|
:withBtnClass="true"
|
||||||
v-if="selectedWorkType?.work_type !== 3"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button class="btn btn-add" @click.stop.prevent="() => openModal()">
|
<button class="btn btn-add" @click.stop.prevent="() => openModal()">
|
||||||
|
@ -42,17 +42,7 @@ const setButtonItems = () => {
|
|||||||
active: searchParams.value.work_type === "1",
|
active: searchParams.value.work_type === "1",
|
||||||
work_type: 1,
|
work_type: 1,
|
||||||
params: ["work_type", "sub_system_tag"],
|
params: ["work_type", "sub_system_tag"],
|
||||||
},
|
}
|
||||||
{
|
|
||||||
title: t("operation.company_info"),
|
|
||||||
key: "company_info",
|
|
||||||
active: false,
|
|
||||||
active:
|
|
||||||
searchParams.value.work_type === null ||
|
|
||||||
searchParams.value.work_type === "3",
|
|
||||||
work_type: 3,
|
|
||||||
params: [],
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setSearchTypesItems([
|
setSearchTypesItems([
|
||||||
@ -85,21 +75,17 @@ watch(
|
|||||||
[selectedWorkType, selectedSearchType],
|
[selectedWorkType, selectedSearchType],
|
||||||
([newWorkType, newSearchType]) => {
|
([newWorkType, newSearchType]) => {
|
||||||
if (newWorkType && newSearchType) {
|
if (newWorkType && newSearchType) {
|
||||||
if (newWorkType.work_type === 3) {
|
const oldSearchParams = Object.fromEntries(
|
||||||
changeParams({ work_type: newWorkType?.work_type });
|
[...newWorkType?.params, ...newSearchType?.params].map((key) => [
|
||||||
} else {
|
key,
|
||||||
const oldSearchParams = Object.fromEntries(
|
searchParams.value[key] ?? null,
|
||||||
[...newWorkType?.params, ...newSearchType?.params].map((key) => [
|
])
|
||||||
key,
|
);
|
||||||
searchParams.value[key] ?? null,
|
changeParams({
|
||||||
])
|
...oldSearchParams,
|
||||||
);
|
work_type: newWorkType?.work_type,
|
||||||
changeParams({
|
search_type: newSearchType?.key,
|
||||||
...oldSearchParams,
|
});
|
||||||
work_type: newWorkType?.work_type,
|
|
||||||
search_type: newSearchType?.key,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -119,12 +105,9 @@ watch(
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<OperationSearchSubSys
|
<OperationSearchSubSys />
|
||||||
:class="twMerge(selectedWorkType?.work_type === 3 ? 'hidden' : 'block')"
|
|
||||||
/>
|
|
||||||
<div class="w-full flex flex-wrap items-center justify-start">
|
<div class="w-full flex flex-wrap items-center justify-start">
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
v-if="selectedWorkType?.work_type !== 3"
|
|
||||||
:class="twMerge('mr-3')"
|
:class="twMerge('mr-3')"
|
||||||
:items="searchTypesItems"
|
:items="searchTypesItems"
|
||||||
:withLine="true"
|
:withLine="true"
|
||||||
@ -135,8 +118,7 @@ watch(
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<OperationSearchType :selected="selectedSearchType"
|
<OperationSearchType :selected="selectedSearchType" />
|
||||||
v-if="selectedWorkType?.work_type !== 3" />
|
|
||||||
<OperationActionButton :selectedWorkType="selectedWorkType" />
|
<OperationActionButton :selectedWorkType="selectedWorkType" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -128,7 +128,7 @@ watch(
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
v-if="selected?.key === 'date' && searchParams?.work_type !== '3'"
|
v-if="selected?.key === 'date' "
|
||||||
:items="DateItems"
|
:items="DateItems"
|
||||||
:withLine="true"
|
:withLine="true"
|
||||||
:onclick="
|
:onclick="
|
||||||
@ -140,7 +140,7 @@ watch(
|
|||||||
<DateGroup
|
<DateGroup
|
||||||
:isTopLabelExist="false"
|
:isTopLabelExist="false"
|
||||||
:isBottomLabelExist="false"
|
:isBottomLabelExist="false"
|
||||||
v-if="selected?.key === 'date' && searchParams?.work_type !== '3'"
|
v-if="selected?.key === 'date' "
|
||||||
:items="searchDateItems"
|
:items="searchDateItems"
|
||||||
:withLine="true"
|
:withLine="true"
|
||||||
/>
|
/>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { getFIX_COL, getCOM_COL } from "../constant/OperationTableColumns";
|
import { getFIX_COL } from "../constant/OperationTableColumns";
|
||||||
import { defineProps, computed, inject, watch } from "vue";
|
import { defineProps, computed, inject, watch } from "vue";
|
||||||
import {
|
import {
|
||||||
deleteOperationRecord,
|
deleteOperationRecord
|
||||||
deleteOperationCompany,
|
|
||||||
} from "@/apis/operation";
|
} from "@/apis/operation";
|
||||||
import useSearchParam from "@/hooks/useSearchParam";
|
import useSearchParam from "@/hooks/useSearchParam";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
@ -16,7 +15,7 @@ const { dataSource, openModal, updateEditRecord, search, tableLoading } =
|
|||||||
inject("operation_table");
|
inject("operation_table");
|
||||||
|
|
||||||
const columns = computed(() =>
|
const columns = computed(() =>
|
||||||
searchParams.value?.work_type < 3 ? getFIX_COL(t) : getCOM_COL(t)
|
getFIX_COL(t)
|
||||||
);
|
);
|
||||||
|
|
||||||
const changeData = (record) => {
|
const changeData = (record) => {
|
||||||
@ -29,11 +28,7 @@ const deleteItem = async (id) => {
|
|||||||
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||||
await cancelToastOpen();
|
await cancelToastOpen();
|
||||||
let res;
|
let res;
|
||||||
if (searchParams.value?.work_type < 3) {
|
res = await deleteOperationRecord(id);
|
||||||
res = await deleteOperationRecord(id);
|
|
||||||
} else {
|
|
||||||
res = await deleteOperationCompany(id);
|
|
||||||
}
|
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
search();
|
search();
|
||||||
openToast("success", t("msg.delete_success"));
|
openToast("success", t("msg.delete_success"));
|
||||||
|
@ -4,8 +4,6 @@ import useSearchParam from "@/hooks/useSearchParam";
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {
|
import {
|
||||||
postOperationRecord,
|
postOperationRecord,
|
||||||
postOperationCompany,
|
|
||||||
updateOperationCompany,
|
|
||||||
} from "@/apis/operation";
|
} from "@/apis/operation";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import "yup-phone-lite";
|
import "yup-phone-lite";
|
||||||
@ -71,17 +69,6 @@ const formState = ref([
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let companySchema = yup.object({
|
|
||||||
name: yup.string().required(t("button.required")),
|
|
||||||
contact_person: yup.string().nullable(true),
|
|
||||||
email: yup.string().email().nullable(true),
|
|
||||||
phone: yup.string().nullable(true),
|
|
||||||
city: yup.string().nullable(true),
|
|
||||||
address: yup.string().nullable(true),
|
|
||||||
tax_id_number: yup.string().nullable(true),
|
|
||||||
remark: yup.string().nullable(true),
|
|
||||||
});
|
|
||||||
|
|
||||||
let maintainSchema = yup.object({
|
let maintainSchema = yup.object({
|
||||||
formId: yup.string().required(t("button.required")),
|
formId: yup.string().required(t("button.required")),
|
||||||
work_type: yup.string().required(t("button.required")),
|
work_type: yup.string().required(t("button.required")),
|
||||||
@ -168,36 +155,9 @@ const saveMaintain = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
|
||||||
formErrorMsg: companyFormErrorMsg,
|
|
||||||
handleSubmit: handleCompanySubmit,
|
|
||||||
handleErrorReset: handleCompanyErrorReset,
|
|
||||||
} = useFormErrorMessage(companySchema);
|
|
||||||
const saveCompany = async () => {
|
|
||||||
const value = await handleCompanySubmit(
|
|
||||||
companySchema,
|
|
||||||
formState.value[searchParams.value?.work_type - 1]
|
|
||||||
);
|
|
||||||
let res;
|
|
||||||
if (props.editRecord) {
|
|
||||||
res = await updateOperationCompany(value);
|
|
||||||
} else {
|
|
||||||
res = await postOperationCompany(value);
|
|
||||||
}
|
|
||||||
if (res.isSuccess) {
|
|
||||||
search();
|
|
||||||
onCancel();
|
|
||||||
} else {
|
|
||||||
openToast("error", res.msg, "#operation_action_item");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onOk = async () => {
|
const onOk = async () => {
|
||||||
if (searchParams.value.work_type < 3) {
|
|
||||||
saveMaintain();
|
saveMaintain();
|
||||||
} else {
|
|
||||||
saveCompany();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
@ -221,7 +181,6 @@ const onCancel = () => {
|
|||||||
updateEditRecord?.(null);
|
updateEditRecord?.(null);
|
||||||
reset();
|
reset();
|
||||||
handleMaintainErrorReset();
|
handleMaintainErrorReset();
|
||||||
handleCompanyErrorReset();
|
|
||||||
operation_action_item.close();
|
operation_action_item.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -469,139 +428,6 @@ watch(
|
|||||||
<template #topLeft>{{ $t("operation.upload_file") }}</template>
|
<template #topLeft>{{ $t("operation.upload_file") }}</template>
|
||||||
</Upload>
|
</Upload>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'name')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="name"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.name") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.name }}
|
|
||||||
</span></template
|
|
||||||
>
|
|
||||||
</Input>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(
|
|
||||||
formState[searchParams?.work_type - 1],
|
|
||||||
'contact_person'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="contact_person"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.contact_person") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.contact_person }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'phone')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="phone"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.phone") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.phone }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'email')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="email"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.email") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.email }}
|
|
||||||
</span></template
|
|
||||||
>
|
|
||||||
</Input>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'city')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2 w-[250px]"
|
|
||||||
name="city"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.city") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.city }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'address')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2 w-4/5"
|
|
||||||
name="address"
|
|
||||||
>
|
|
||||||
<template #topLeft>{{ $t("operation.address") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.address }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(
|
|
||||||
formState[searchParams?.work_type - 1],
|
|
||||||
'tax_id_number'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="tax_id_number"
|
|
||||||
>
|
|
||||||
<template #topLeft> {{ $t("operation.tax_id_number") }}</template>
|
|
||||||
<template #bottomLeft
|
|
||||||
><span class="text-error text-base">
|
|
||||||
{{ companyFormErrorMsg.tax_id_number }}
|
|
||||||
</span></template
|
|
||||||
></Input
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
v-if="
|
|
||||||
searchParams?.work_type &&
|
|
||||||
Object.hasOwn(formState[searchParams?.work_type - 1], 'remark')
|
|
||||||
"
|
|
||||||
:value="formState[searchParams?.work_type - 1]"
|
|
||||||
class="my-2"
|
|
||||||
name="remark"
|
|
||||||
>
|
|
||||||
<template #topLeft>
|
|
||||||
{{ $t("operation.remark") }}
|
|
||||||
</template></Input
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
<template #modalAction>
|
<template #modalAction>
|
||||||
|
@ -55,31 +55,3 @@ export const getFIX_COL = (t) => [
|
|||||||
width: 250,
|
width: 250,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getCOM_COL = (t) => [
|
|
||||||
{
|
|
||||||
title: t("operation.vendor"),
|
|
||||||
key: "name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("operation.contact_person"),
|
|
||||||
key: "contact_person",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("operation.phone"),
|
|
||||||
key: "phone",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("operation.email"),
|
|
||||||
key: "email",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("operation.created_at"),
|
|
||||||
key: "created_at",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("operation.operation"),
|
|
||||||
key: "operation",
|
|
||||||
width: 250,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
47
src/views/setting/SettingManagement.vue
Normal file
47
src/views/setting/SettingManagement.vue
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, watch } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
|
import Dept from "./components/Dept.vue";
|
||||||
|
import ElecType from "./components/ElecType.vue";
|
||||||
|
import Vendor from "./components/Vendor.vue";
|
||||||
|
import Floors from "./components/Floors.vue";
|
||||||
|
import MITTList from "./components/MITTList.vue";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const currentComponent = ref(null);
|
||||||
|
|
||||||
|
const updateComponent = () => {
|
||||||
|
const { main_system_id, sub_system_id } = route.params;
|
||||||
|
|
||||||
|
if (main_system_id === "Setting") {
|
||||||
|
if (sub_system_id === "Department") {
|
||||||
|
currentComponent.value = Dept;
|
||||||
|
} else if(sub_system_id === "ElecType") {
|
||||||
|
currentComponent.value = ElecType;
|
||||||
|
} else if(sub_system_id === "Vendor") {
|
||||||
|
currentComponent.value = Vendor;
|
||||||
|
} else if(sub_system_id === "Floor") {
|
||||||
|
currentComponent.value = Floors;
|
||||||
|
}else{
|
||||||
|
currentComponent.value = MITTList;
|
||||||
|
}
|
||||||
|
} else if (main_system_id === "MQTT") {
|
||||||
|
currentComponent.value = MITTList;
|
||||||
|
} else {
|
||||||
|
currentComponent.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(updateComponent);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.params,
|
||||||
|
() => {
|
||||||
|
updateComponent();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<component :is="currentComponent" />
|
||||||
|
</template>
|
104
src/views/setting/components/Dept.vue
Normal file
104
src/views/setting/components/Dept.vue
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<script setup>
|
||||||
|
import Table from "@/components/customUI/Table.vue";
|
||||||
|
import DeptModal from "./DeptModal.vue";
|
||||||
|
import { getDepartmentList, deleteDepartmentItem } from "@/apis/asset";
|
||||||
|
import { onMounted, ref, inject, computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: t("accountManagement.index"),
|
||||||
|
key: "index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("assetManagement.department_name"),
|
||||||
|
key: "name",
|
||||||
|
filter: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("accountManagement.operation"),
|
||||||
|
key: "operation",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dataSource = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const getDataSource = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getDepartmentList();
|
||||||
|
dataSource.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataSource();
|
||||||
|
});
|
||||||
|
|
||||||
|
const formState = ref({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const openModal = (record) => {
|
||||||
|
if (record.id) {
|
||||||
|
formState.value = { ...record };
|
||||||
|
} else {
|
||||||
|
formState.value = {
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
dept_modal.showModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = async (id) => {
|
||||||
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||||
|
await cancelToastOpen();
|
||||||
|
const res = await deleteDepartmentItem(id);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
getDataSource();
|
||||||
|
openToast("success", t("msg.delete_success"));
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex justify-start items-center mt-10 mb-5">
|
||||||
|
<h3 class="text-xl mr-5">{{ $t("assetManagement.department") }}</h3>
|
||||||
|
<DeptModal
|
||||||
|
:formState="formState"
|
||||||
|
:getData="getDataSource"
|
||||||
|
:openModal="openModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table :columns="columns" :dataSource="dataSource" :loading="loading">
|
||||||
|
<template #bodyCell="{ record, column, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
<template v-else-if="column.key === 'operation'">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success text-white mr-2"
|
||||||
|
@click.stop.prevent="() => openModal(record)"
|
||||||
|
>
|
||||||
|
{{ $t("button.edit") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-error text-white"
|
||||||
|
@click.stop.prevent="() => remove(record.id)"
|
||||||
|
>
|
||||||
|
{{ $t("button.delete") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record[column.key] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
84
src/views/setting/components/DeptModal.vue
Normal file
84
src/views/setting/components/DeptModal.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, defineProps, inject, watch } from "vue";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import "yup-phone-lite";
|
||||||
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
|
import { postDepartmentList } from "@/apis/asset";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast } = inject("app_toast");
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formState: Object,
|
||||||
|
getData: Function,
|
||||||
|
openModal: Function
|
||||||
|
});
|
||||||
|
|
||||||
|
const deptScheme = yup.object({
|
||||||
|
name: yup.string().required(t("button.required")),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||||
|
useFormErrorMessage(deptScheme);
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
handleErrorReset();
|
||||||
|
dept_modal.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOk = async () => {
|
||||||
|
const value = await handleSubmit(deptScheme, props.formState);
|
||||||
|
const res = await postDepartmentList(value);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
props.getData();
|
||||||
|
onCancel();
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg, "#dept_modal");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button class="btn btn-sm btn-add " @click.stop.prevent="props.openModal">
|
||||||
|
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||||
|
</button>
|
||||||
|
<Modal
|
||||||
|
id="dept_modal"
|
||||||
|
:title="props.formState?.id ? t('button.edit') : t('button.add')"
|
||||||
|
:onCancel="onCancel"
|
||||||
|
width="400"
|
||||||
|
>
|
||||||
|
<template #modalContent>
|
||||||
|
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
|
||||||
|
<Input :value="formState" class="my-2" name="name">
|
||||||
|
<template #topLeft>{{
|
||||||
|
$t("assetManagement.department_name")
|
||||||
|
}}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.name }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<template #modalAction>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="btn btn-outline-success mr-2"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
>
|
||||||
|
{{ $t("button.cancel") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
@click.stop.prevent="onOk"
|
||||||
|
>
|
||||||
|
{{ $t("button.submit") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
104
src/views/setting/components/ElecType.vue
Normal file
104
src/views/setting/components/ElecType.vue
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<script setup>
|
||||||
|
import Table from "@/components/customUI/Table.vue";
|
||||||
|
import ElecTypeModal from "./ElecTypeModal.vue";
|
||||||
|
import { getElecTypeList, deleteElecTypeItem } from "@/apis/asset";
|
||||||
|
import { onMounted, ref, inject, computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: t("accountManagement.index"),
|
||||||
|
key: "index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("energy.electricity_classification"),
|
||||||
|
key: "name",
|
||||||
|
filter: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("accountManagement.operation"),
|
||||||
|
key: "operation",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dataSource = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const getDataSource = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getElecTypeList();
|
||||||
|
dataSource.value = res.data.map((d) => ({ ...d, key: d.id }));
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataSource();
|
||||||
|
});
|
||||||
|
|
||||||
|
const formState = ref({
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const openModal = (record) => {
|
||||||
|
if (record.id) {
|
||||||
|
formState.value = { ...record };
|
||||||
|
} else {
|
||||||
|
formState.value = {
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
elec_modal.showModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = async (id) => {
|
||||||
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||||
|
await cancelToastOpen();
|
||||||
|
const res = await deleteElecTypeItem(id);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
getDataSource();
|
||||||
|
openToast("success", t("msg.delete_success"));
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex justify-start items-center mt-10 mb-5">
|
||||||
|
<h3 class="text-xl mr-5">{{ $t("energy.electricity_classification") }}</h3>
|
||||||
|
<ElecTypeModal
|
||||||
|
:formState="formState"
|
||||||
|
:getData="getDataSource"
|
||||||
|
:openModal="openModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table :columns="columns" :dataSource="dataSource" :loading="loading">
|
||||||
|
<template #bodyCell="{ record, column, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
<template v-else-if="column.key === 'operation'">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success text-white mr-2"
|
||||||
|
@click.stop.prevent="() => openModal(record)"
|
||||||
|
>
|
||||||
|
{{ $t("button.edit") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-error text-white"
|
||||||
|
@click.stop.prevent="() => remove(record.id)"
|
||||||
|
>
|
||||||
|
{{ $t("button.delete") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record[column.key] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
84
src/views/setting/components/ElecTypeModal.vue
Normal file
84
src/views/setting/components/ElecTypeModal.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, defineProps, inject, watch } from "vue";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import "yup-phone-lite";
|
||||||
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
|
import { postElecTypeList } from "@/apis/asset";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast } = inject("app_toast");
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formState: Object,
|
||||||
|
getData: Function,
|
||||||
|
openModal: Function
|
||||||
|
});
|
||||||
|
|
||||||
|
const deptScheme = yup.object({
|
||||||
|
name: yup.string().required(t("button.required")),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||||
|
useFormErrorMessage(deptScheme);
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
handleErrorReset();
|
||||||
|
elec_modal.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOk = async () => {
|
||||||
|
const value = await handleSubmit(deptScheme, props.formState);
|
||||||
|
const res = await postElecTypeList(value);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
props.getData();
|
||||||
|
onCancel();
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg, "#elec_modal");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button class="btn btn-sm btn-add " @click.stop.prevent="props.openModal">
|
||||||
|
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||||
|
</button>
|
||||||
|
<Modal
|
||||||
|
id="elec_modal"
|
||||||
|
:title="props.formState?.id ? t('button.edit') : t('button.add')"
|
||||||
|
:onCancel="onCancel"
|
||||||
|
width="400"
|
||||||
|
>
|
||||||
|
<template #modalContent>
|
||||||
|
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
|
||||||
|
<Input :value="formState" class="my-2" name="name">
|
||||||
|
<template #topLeft>{{
|
||||||
|
$t("energy.electricity_classification")
|
||||||
|
}}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.name }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<template #modalAction>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="btn btn-outline-success mr-2"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
>
|
||||||
|
{{ $t("button.cancel") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
@click.stop.prevent="onOk"
|
||||||
|
>
|
||||||
|
{{ $t("button.submit") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
114
src/views/setting/components/Floors.vue
Normal file
114
src/views/setting/components/Floors.vue
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<script setup>
|
||||||
|
import Table from "@/components/customUI/Table.vue";
|
||||||
|
import FloorsModal from "./FloorsModal.vue";
|
||||||
|
import { getAssetFloorList, deleteAssetFloor } from "@/apis/asset";
|
||||||
|
import { onMounted, ref, inject, computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: t("accountManagement.index"),
|
||||||
|
key: "index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("energy.floor"),
|
||||||
|
key: "full_name",
|
||||||
|
filter: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("assetManagement.floor_plan"),
|
||||||
|
key: "floor_plan",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("accountManagement.operation"),
|
||||||
|
key: "operation",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dataSource = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const getDataSource = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getAssetFloorList();
|
||||||
|
dataSource.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataSource();
|
||||||
|
});
|
||||||
|
|
||||||
|
const formState = ref({
|
||||||
|
full_name: "",
|
||||||
|
floorFile: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const openModal = (record) => {
|
||||||
|
if (record.floor_guid) {
|
||||||
|
formState.value = { ...record };
|
||||||
|
} else {
|
||||||
|
formState.value = {
|
||||||
|
full_name: "",
|
||||||
|
floorFile: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
floor_modal.showModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = async () => {
|
||||||
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||||
|
await cancelToastOpen();
|
||||||
|
const res = await deleteAssetFloor({
|
||||||
|
floor_guid: formState.value.floor_guid,
|
||||||
|
});
|
||||||
|
if (res.isSuccess) {
|
||||||
|
getDataSource();
|
||||||
|
openToast("success", t("msg.delete_success"));
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex justify-start items-center mt-10 mb-5">
|
||||||
|
<h3 class="text-xl mr-5">{{ $t("energy.floor") }}</h3>
|
||||||
|
<FloorsModal
|
||||||
|
:formState="formState"
|
||||||
|
:getData="getDataSource"
|
||||||
|
:openModal="openModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table :columns="columns" :dataSource="dataSource" :loading="loading">
|
||||||
|
<template #bodyCell="{ record, column, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
<template v-else-if="column.key === 'operation'">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success text-white mr-2"
|
||||||
|
@click.stop.prevent="() => openModal(record)"
|
||||||
|
>
|
||||||
|
{{ $t("button.edit") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-error text-white"
|
||||||
|
@click.stop.prevent="() => remove()"
|
||||||
|
>
|
||||||
|
{{ $t("button.delete") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'floor_plan'">
|
||||||
|
<img :src="`${FILE_BASEURL}/${record.floor_map_url}.svg`" class="w-[200px] bg-white mx-auto" />
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record[column.key] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
108
src/views/setting/components/FloorsModal.vue
Normal file
108
src/views/setting/components/FloorsModal.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, defineProps, inject, watch } from "vue";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import "yup-phone-lite";
|
||||||
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
|
import { postAssetFloor } from "@/apis/asset";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast } = inject("app_toast");
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formState: Object,
|
||||||
|
getData: Function,
|
||||||
|
openModal: Function,
|
||||||
|
});
|
||||||
|
const form = ref(null);
|
||||||
|
|
||||||
|
const floorScheme = yup.object({
|
||||||
|
full_name: yup.string().required(t("button.required")),
|
||||||
|
floorFile: yup.array(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateFileList = (files) => {
|
||||||
|
console.log("file", files);
|
||||||
|
FloorFormState.value.floorFile = files;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||||
|
useFormErrorMessage(floorScheme);
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
handleErrorReset();
|
||||||
|
floor_modal.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOk = async () => {
|
||||||
|
const value = await handleSubmit(floorScheme, props.formState);
|
||||||
|
const formData = new FormData(form.value);
|
||||||
|
formData.append(
|
||||||
|
"floor_guid",
|
||||||
|
selectedOption.value === "add" ? null : currentFloor.value.floor_guid
|
||||||
|
);
|
||||||
|
formData.append("building_tag", store.selectedBuilding.building_tag);
|
||||||
|
formData.append("initMapName", FloorFormState.value.floorFile[0]?.name);
|
||||||
|
formData.append("mapFile", FloorFormState.value.floorFile[0]);
|
||||||
|
formData.delete("floorFile");
|
||||||
|
const res = await postAssetFloor(formData);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
props.getData();
|
||||||
|
onCancel();
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg, "#floor_modal");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button class="btn btn-sm btn-add" @click.stop.prevent="props.openModal">
|
||||||
|
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||||
|
</button>
|
||||||
|
<Modal
|
||||||
|
id="floor_modal"
|
||||||
|
:title="props.formState?.floor_guid ? t('button.edit') : t('button.add')"
|
||||||
|
:onCancel="onCancel"
|
||||||
|
width="400"
|
||||||
|
>
|
||||||
|
<template #modalContent>
|
||||||
|
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
|
||||||
|
<Input :value="formState" class="my-2" name="full_name">
|
||||||
|
<template #topLeft>{{ $t("assetManagement.system_name") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.name }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
name="floorFile"
|
||||||
|
:fileList="formState.floorFile"
|
||||||
|
:getFileList="updateFileList"
|
||||||
|
:multiple="false"
|
||||||
|
class="col-span-2"
|
||||||
|
formats="svg"
|
||||||
|
>
|
||||||
|
<template #topLeft>{{ $t("assetManagement.oriFile") }}</template>
|
||||||
|
</Upload>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<template #modalAction>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="btn btn-outline-success mr-2"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
>
|
||||||
|
{{ $t("button.cancel") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
@click.stop.prevent="onOk"
|
||||||
|
>
|
||||||
|
{{ $t("button.submit") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
144
src/views/setting/components/MITTList.vue
Normal file
144
src/views/setting/components/MITTList.vue
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, watch, computed } from "vue";
|
||||||
|
import { getAssetMainList, getAssetSubList, getIOTSchema } from "@/apis/asset";
|
||||||
|
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const formState = ref({});
|
||||||
|
const dataSource = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
// 系統類別
|
||||||
|
const {
|
||||||
|
items: mainSysItems,
|
||||||
|
changeActiveBtn: changeMainSysActiveBtn,
|
||||||
|
setItems: setMainSysItems,
|
||||||
|
selectedBtn: selectedMainSysItems,
|
||||||
|
} = useActiveBtn();
|
||||||
|
// 設備類別
|
||||||
|
const {
|
||||||
|
items: subSysItems,
|
||||||
|
changeActiveBtn: changeSubSysActiveBtn,
|
||||||
|
setItems: setSubSysItems,
|
||||||
|
selectedBtn: selectedSubSysItems,
|
||||||
|
} = useActiveBtn();
|
||||||
|
|
||||||
|
const getMainSystems = async () => {
|
||||||
|
const res = await getAssetMainList();
|
||||||
|
const cate = res.data.map((d, index) => ({
|
||||||
|
...d,
|
||||||
|
title: d.system_key,
|
||||||
|
key: d.id,
|
||||||
|
active: index === 0,
|
||||||
|
}));
|
||||||
|
setMainSysItems(cate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSubSystems = async (id) => {
|
||||||
|
const res = await getAssetSubList(id);
|
||||||
|
const sub = res.data.map((d, index) => ({
|
||||||
|
...d,
|
||||||
|
title: d.system_key,
|
||||||
|
key: d.id,
|
||||||
|
active: index === 0,
|
||||||
|
}));
|
||||||
|
setSubSysItems(sub);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: "schema",
|
||||||
|
key: "schema_name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "point",
|
||||||
|
key: "pointOrg",
|
||||||
|
filter: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Description",
|
||||||
|
key: "description",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const getDataSource = async (id) => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getIOTSchema(id);
|
||||||
|
dataSource.value = res.data.flatMap((d) =>
|
||||||
|
d.details.map((detail) => ({
|
||||||
|
key: `${d.id}-${detail.pointOrg}`,
|
||||||
|
schema_name: d.name,
|
||||||
|
pointOrg: detail.pointOrg,
|
||||||
|
description: detail.describe,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
selectedMainSysItems,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue && newValue.key) {
|
||||||
|
getSubSystems(parseInt(newValue.key));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
selectedSubSysItems,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue && newValue.key) {
|
||||||
|
getDataSource(parseInt(newValue.key));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getMainSystems();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="">
|
||||||
|
<div class="flex items-center gap-4 mb-4">
|
||||||
|
<h2 class="text-lg font-bold whitespace-nowrap">
|
||||||
|
{{ $t("history.system_category") }} :
|
||||||
|
</h2>
|
||||||
|
<ButtonGroup
|
||||||
|
:items="mainSysItems"
|
||||||
|
:withLine="true"
|
||||||
|
:onclick="
|
||||||
|
(e, item) => {
|
||||||
|
changeMainSysActiveBtn(item);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4 mb-4">
|
||||||
|
<h2 class="text-lg font-bold whitespace-nowrap">
|
||||||
|
{{ $t("history.device_category") }} :
|
||||||
|
</h2>
|
||||||
|
<ButtonGroup
|
||||||
|
:items="subSysItems"
|
||||||
|
:withLine="true"
|
||||||
|
:onclick="
|
||||||
|
(e, item) => {
|
||||||
|
changeSubSysActiveBtn(item);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
:columns="columns"
|
||||||
|
:dataSource="dataSource"
|
||||||
|
:loading="loading"
|
||||||
|
></Table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
128
src/views/setting/components/Vendor.vue
Normal file
128
src/views/setting/components/Vendor.vue
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<script setup>
|
||||||
|
import Table from "@/components/customUI/Table.vue";
|
||||||
|
import VendorModal from "./VendorModal.vue";
|
||||||
|
import { getOperationCompanyList,deleteOperationCompany } from "@/apis/operation";
|
||||||
|
import { onMounted, ref, inject, computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
title: t("operation.vendor"),
|
||||||
|
key: "name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("operation.contact_person"),
|
||||||
|
key: "contact_person",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("operation.phone"),
|
||||||
|
key: "phone",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("operation.email"),
|
||||||
|
key: "email",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("operation.created_at"),
|
||||||
|
key: "created_at",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("operation.operation"),
|
||||||
|
key: "operation",
|
||||||
|
width: 250,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dataSource = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const getDataSource = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await getOperationCompanyList();
|
||||||
|
dataSource.value = res.data;
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataSource();
|
||||||
|
});
|
||||||
|
|
||||||
|
const formState = ref({
|
||||||
|
contact_person: "",
|
||||||
|
email: "",
|
||||||
|
name: "",
|
||||||
|
phone: "",
|
||||||
|
remark: "",
|
||||||
|
tax_id_number: "",
|
||||||
|
city: "",
|
||||||
|
address: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const openModal = (record) => {
|
||||||
|
if (record.id) {
|
||||||
|
formState.value = { ...record };
|
||||||
|
} else {
|
||||||
|
formState.value = {
|
||||||
|
contact_person: "",
|
||||||
|
email: "",
|
||||||
|
name: "",
|
||||||
|
phone: "",
|
||||||
|
remark: "",
|
||||||
|
tax_id_number: "",
|
||||||
|
city: "",
|
||||||
|
address: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
company_modal.showModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = async (id) => {
|
||||||
|
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||||
|
await cancelToastOpen();
|
||||||
|
const res = await deleteOperationCompany(id);
|
||||||
|
if (res.isSuccess) {
|
||||||
|
getDataSource();
|
||||||
|
openToast("success", t("msg.delete_success"));
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex justify-start items-center mt-10 mb-5">
|
||||||
|
<h3 class="text-xl mr-5">{{ $t("assetManagement.company") }}</h3>
|
||||||
|
<VendorModal
|
||||||
|
:formState="formState"
|
||||||
|
:getData="getDataSource"
|
||||||
|
:openModal="openModal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table :columns="columns" :dataSource="dataSource" :loading="loading">
|
||||||
|
<template #bodyCell="{ record, column, index }">
|
||||||
|
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||||
|
<template v-else-if="column.key === 'operation'">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success text-white mr-2"
|
||||||
|
@click.stop.prevent="() => openModal(record)"
|
||||||
|
>
|
||||||
|
{{ $t("button.edit") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-error text-white"
|
||||||
|
@click.stop.prevent="() => remove(record.id)"
|
||||||
|
>
|
||||||
|
{{ $t("button.delete") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ record[column.key] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
153
src/views/setting/components/VendorModal.vue
Normal file
153
src/views/setting/components/VendorModal.vue
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, defineProps, inject, watch } from "vue";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import "yup-phone-lite";
|
||||||
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
|
import {
|
||||||
|
postOperationCompany,
|
||||||
|
updateOperationCompany,
|
||||||
|
} from "@/apis/operation";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openToast } = inject("app_toast");
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formState: Object,
|
||||||
|
getData: Function,
|
||||||
|
openModal: Function
|
||||||
|
});
|
||||||
|
|
||||||
|
const deptScheme = yup.object({
|
||||||
|
name: yup.string().required(t("button.required")),
|
||||||
|
contact_person: yup.string().nullable(true),
|
||||||
|
email: yup.string().email().nullable(true),
|
||||||
|
phone: yup.string().nullable(true),
|
||||||
|
city: yup.string().nullable(true),
|
||||||
|
address: yup.string().nullable(true),
|
||||||
|
tax_id_number: yup.string().nullable(true),
|
||||||
|
remark: yup.string().nullable(true),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||||
|
useFormErrorMessage(deptScheme);
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
handleErrorReset();
|
||||||
|
company_modal.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOk = async () => {
|
||||||
|
const value = await handleSubmit(deptScheme, props.formState);
|
||||||
|
if (props.formState?.id) {
|
||||||
|
res = await updateOperationCompany(value);
|
||||||
|
} else {
|
||||||
|
res = await postOperationCompany(value);
|
||||||
|
}
|
||||||
|
if (res.isSuccess) {
|
||||||
|
props.getData();
|
||||||
|
onCancel();
|
||||||
|
} else {
|
||||||
|
openToast("error", res.msg, "#company_modal");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button class="btn btn-sm btn-add " @click.stop.prevent="props.openModal">
|
||||||
|
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||||
|
</button>
|
||||||
|
<Modal
|
||||||
|
id="company_modal"
|
||||||
|
:title="props.formState?.id ? t('button.edit') : t('button.add')"
|
||||||
|
:onCancel="onCancel"
|
||||||
|
width="710"
|
||||||
|
>
|
||||||
|
<template #modalContent>
|
||||||
|
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
|
||||||
|
<Input :value="formState" class="my-2" name="name">
|
||||||
|
<template #topLeft>{{ $t("operation.name") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.name }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="contact_person">
|
||||||
|
<template #topLeft>{{ $t("operation.contact_person") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.contact_person }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="phone">
|
||||||
|
<template #topLeft>{{ $t("operation.phone") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.phone }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="email">
|
||||||
|
<template #topLeft>{{ $t("operation.email") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.email }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="city">
|
||||||
|
<template #topLeft>{{ $t("operation.city") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.city }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="address">
|
||||||
|
<template #topLeft>{{ $t("operation.address") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.address }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="tax_id_number">
|
||||||
|
<template #topLeft>{{ $t("operation.tax_id_number") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.tax_id_number }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
<Input :value="formState" class="my-2" name="remark">
|
||||||
|
<template #topLeft>{{ $t("operation.remark") }}</template>
|
||||||
|
<template #bottomLeft
|
||||||
|
><span class="text-error text-base">
|
||||||
|
{{ formErrorMsg.remark }}
|
||||||
|
</span></template
|
||||||
|
></Input
|
||||||
|
>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<template #modalAction>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
class="btn btn-outline-success mr-2"
|
||||||
|
@click.prevent="onCancel"
|
||||||
|
>
|
||||||
|
{{ $t("button.cancel") }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
@click.stop.prevent="onOk"
|
||||||
|
>
|
||||||
|
{{ $t("button.submit") }}
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
Loading…
Reference in New Issue
Block a user