設備管理:新增修改刪除大小類 | upload組件避免誤觸label

This commit is contained in:
koko 2024-12-11 11:55:38 +08:00
parent d05f9ab130
commit da8eb0d539
11 changed files with 305 additions and 70 deletions

View File

@ -1,5 +1,8 @@
export const GET_ASSET_SUB_LIST_API = `/AssetManage/GetAssetSubList`;
export const GET_ASSET_MAIN_LIST_API = `/AssetManage/GetAssetMainList`;
export const DELETE_ASSET_MAIN_LIST_API = `/AssetManage/DeleteAssetMain`;
export const POST_ASSET_MAIN_LIST_API = `/AssetManage/SaveAssetMain`;
export const GET_ASSET_SUB_LIST_API = `/AssetManage/GetAssetSubList`;
export const POST_ASSET_SUB_LIST_API = `/AssetManage/SaveAssetSub`;
export const DELETE_ASSET_SUB_LIST_API = `/AssetManage/DeleteAssetSub`;

View File

@ -1,6 +1,8 @@
import {
GET_ASSET_SUB_LIST_API,
GET_ASSET_MAIN_LIST_API,
DELETE_ASSET_MAIN_LIST_API,
POST_ASSET_MAIN_LIST_API,
GET_ASSET_SUB_LIST_API,
DELETE_ASSET_SUB_LIST_API,
POST_ASSET_SUB_LIST_API,
GET_ASSET_LIST_API,
@ -17,8 +19,8 @@ import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import { object } from "yup";
export const getAssetSubList = async (id) => {
const res = await instance.post(GET_ASSET_SUB_LIST_API, { id });
export const getAssetMainList = async () => {
const res = await instance.post(GET_ASSET_MAIN_LIST_API);
return apihandler(res.code, res.data, {
msg: res.msg,
@ -26,8 +28,30 @@ export const getAssetSubList = async (id) => {
});
};
export const getAssetMainList = async () => {
const res = await instance.post(GET_ASSET_MAIN_LIST_API);
export const deleteAssetMainItem = async (id) => {
const res = await instance.post(DELETE_ASSET_MAIN_LIST_API, { id });
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const postAssetMainList = async ({ id, system_key, system_value }) => {
const res = await instance.post(POST_ASSET_MAIN_LIST_API, {
id,
system_key,
system_value,
});
return apihandler(res.code, res.data, {
msg: res.msg,
code: res.code,
});
};
export const getAssetSubList = async (id) => {
const res = await instance.post(GET_ASSET_SUB_LIST_API, { id });
return apihandler(res.code, res.data, {
msg: res.msg,

View File

@ -142,7 +142,7 @@ const revokeURL = (src) => {
<template>
<label class="form-control w-full">
<div class="label">
<div class="label" @click.stop.prevent="() => {}">
<span class="label-text text-lg"><slot name="topLeft"></slot></span>
<span class="label-text-alt"> <slot name="topRight"></slot></span>
</div>

View File

@ -79,7 +79,7 @@
"total_elec_cost": "总电费",
"carbon_equivalent": "碳排当量",
"edit_carbon_emission": "编辑碳排放系数",
"carbon_emission_coefficient":"碳排放系数"
"carbon_emission_coefficient": "碳排放系数"
},
"alarm": {
"title": "显示警告",
@ -207,10 +207,13 @@
},
"assetManagement": {
"title": "资产管理",
"add_category": "新增类别",
"add_system_category": "新增系统类别",
"edit_system_category": "修改系统类别",
"add_device_category": "新增设备类别",
"edit_device_category": "修改设备类别",
"system_name": "名称",
"system_value": "代号",
"system_parent": "所属大类",
"system_parent": "所属系統",
"device_number": "设备编号",
"device_name": "设备名称",
"asset_number": "资产编号",
@ -286,9 +289,11 @@
"rename": "重新命名",
"download": "下载",
"confirm": "确认",
"restore": "复原"
"restore": "复原",
"stop_edit": "停止修改",
"start_edit": "开始修改"
},
"msg":{
"msg": {
"sure_to_delete": "是否确认删除该项目?",
"sure_to_delete_permanent": "是否确认永久删除该项目?",
"delete_success": "删除成功",

View File

@ -207,10 +207,13 @@
},
"assetManagement": {
"title": "資產管理",
"add_category": "新增類別",
"add_system_category": "新增系統類別",
"edit_system_category": "修改系統類別",
"add_device_category": "新增設備類別",
"edit_device_category": "修改設備類別",
"system_name": "名稱",
"system_value": "代號",
"system_parent": "所屬大類",
"system_parent": "所屬系統",
"device_number": "設備編號",
"device_name": "設備名稱",
"asset_number": "資產編號",
@ -286,7 +289,9 @@
"rename": "重新命名",
"download": "下載",
"confirm": "確認",
"restore": "復原"
"restore": "復原",
"stop_edit":"停止修改",
"start_edit":"開始修改"
},
"msg":{
"sure_to_delete": "是否確認刪除該項目?",

View File

@ -79,7 +79,7 @@
"total_elec_cost": "Total Elec. Cost",
"carbon_equivalent": "Carbon Equivalent",
"edit_carbon_emission": "Edit carbon emission coefficient",
"carbon_emission_coefficient":"Carbon emission coefficient"
"carbon_emission_coefficient": "Carbon emission coefficient"
},
"alarm": {
"title": "Warning",
@ -207,10 +207,13 @@
},
"assetManagement": {
"title": "Asset Management",
"add_category": "Add Category",
"add_system_category": "Add system category",
"edit_system_category": "Edit system category",
"add_device_category": "Add device category",
"edit_device_category": "Edit device category",
"system_name": "Name",
"system_value": "Code",
"system_parent": "Category",
"system_parent": "System category",
"device_number": "Device Number",
"device_name": "Device Name",
"asset_number": "Asset Number",
@ -286,7 +289,9 @@
"rename": "Rename",
"download": "Download",
"confirm": "Confirm",
"restore": "Restore"
"restore": "Restore",
"stop_edit": "Stop editing",
"start_edit": "Start editing"
},
"msg": {
"sure_to_delete": "Are you sure to delete this item?",

View File

@ -1,12 +1,21 @@
<script setup>
import { getAssetMainList } from "@/apis/asset";
import { getAssetMainList, deleteAssetMainItem } from "@/apis/asset";
import AssetMainListAddModal from "./AssetMainListAddModal.vue";
import { ref, onMounted, watch, inject } from "vue";
import useSearchParam from "@/hooks/useSearchParam";
import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const { openToast, cancelToastOpen } = inject("app_toast");
const isEditMode = ref(false);
const formState = ref({
id: 0,
system_key: "",
system_value: "",
});
const getMainSystems = async () => {
const res = await getAssetMainList();
const cate = res.data.map((d, index) => ({
@ -20,6 +29,37 @@ const getMainSystems = async () => {
setItems(cate);
};
const openModal = () => {
asset_add_main_item.showModal();
};
const onCancel = () => {
formState.value = {
id: 0,
system_key: "",
system_value: "",
};
asset_add_main_item.close();
};
const edit = (item) => {
formState.value = { ...item };
openModal();
};
const deleteItem = async (id) => {
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await deleteAssetMainItem(id);
if (res.isSuccess) {
openToast("success", t("msg.delete_success"));
getMainSystems();
} else {
openToast("error", res.msg);
}
});
};
onMounted(() => {
getMainSystems();
});
@ -38,22 +78,50 @@ watch(selectedBtn, (newValue) => {
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
{{ $t("history.system_category") }} :
</h2>
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
<AssetMainListAddModal
:openModal="openModal"
:onCancel="onCancel"
:getData="getMainSystems"
:formState="formState"
/>
<button
@click.stop.prevent="isEditMode = !isEditMode"
class="btn btn-sm btn-outline-success"
>
{{ isEditMode ? t("button.stop_edit") : t("button.start_edit") }}
</button>
</div>
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
if (!isEditMode) {
changeActiveBtn(item);
}
"
:className="`flex w-full mt-2`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
}
"
:className="`flex w-full mt-2`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
<template v-if="isEditMode">
<span
class="ml-2 text-base text-warning"
@click.stop.prevent="() => edit(item)"
>
<FontAwesomeIcon :icon="['fas', 'pencil-alt']"></FontAwesomeIcon>
</span>
<span
class="text-base mx-1 text-error"
@click.stop.prevent="() => deleteItem(item.id)"
>
<FontAwesomeIcon :icon="['fas', 'trash-alt']" />
</span>
</template>
</ButtonConnectedGroup>
</div>
</template>
</ButtonConnectedGroup>
</template>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,103 @@
<script setup>
import { ref, defineProps, inject } from "vue";
import * as yup from "yup";
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
import { postAssetMainList } from "@/apis/asset";
import useSearchParam from "@/hooks/useSearchParam";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast } = inject("app_toast");
const { searchParams, changeParams } = useSearchParam();
const props = defineProps({
openModal: Function,
onCancel: Function,
getData: Function,
formState: Object,
isEdit: Boolean,
});
let subSysSchema = yup.object({
system_key: yup.string().required(t("button.required")), //
system_value: yup.string().required(t("button.required")), //
});
const { formErrorMsg, handleSubmit, handleErrorReset } =
useFormErrorMessage(subSysSchema);
const onOk = async () => {
const value = await handleSubmit(subSysSchema, props.formState);
const res = await postAssetMainList({
...props.formState,
id: props.formState ? props.formState.id : 0,
});
if (res.isSuccess) {
props.getData();
onReset();
} else {
openToast("error", res.msg);
}
};
const onReset = () => {
handleErrorReset(); //
props.onCancel(); // 調 onCancel
};
</script>
<template>
<button class="btn btn-sm btn-success" @click.stop.prevent="openModal">
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
</button>
<Modal
id="asset_add_main_item"
:title="
props.formState?.id
? t('assetManagement.edit_system_category')
: t('assetManagement.add_system_category')
"
:open="open"
:onCancel="onReset"
width="300"
>
<template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center">
<Input name="system_key" :value="formState">
<template #topLeft>{{ $t("assetManagement.system_name") }}</template>
<template #bottomLeft
><span class="text-error text-base">
{{ formErrorMsg.system_key }}
</span></template
>
</Input>
<Input name="system_value" :value="formState">
<template #topLeft>{{ $t("assetManagement.system_value") }}</template>
<template #bottomLeft
><span class="text-error text-base">
{{ formErrorMsg.system_value }}
</span></template
>
</Input>
</form>
</template>
<template #modalAction>
<button
type="reset"
class="btn btn-outline-success mr-2"
@click.prevent="onReset"
>
{{ $t("button.cancel") }}
</button>
<button
type="submit"
class="btn btn-outline-success"
@click.prevent="onOk"
>
{{ $t("button.submit") }}
</button>
</template>
</Modal>
</template>
<style lang="scss" scoped></style>

View File

@ -1,13 +1,15 @@
<script setup>
import { getAssetSubList, deleteAssetSubItem } from "@/apis/asset";
import { ref, onMounted, watch } from "vue";
import { ref, onMounted, watch, inject } from "vue";
import useSearchParam from "@/hooks/useSearchParam";
import useActiveBtn from "@/hooks/useActiveBtn";
import AssetSubListAddModal from "./AssetSubListAddModal.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const { openToast, cancelToastOpen } = inject("app_toast");
const isEditMode = ref(false);
const getSubSystems = async (id) => {
const res = await getAssetSubList(id);
const sub = res.data.map((d, index) => ({
@ -24,16 +26,18 @@ const getSubSystems = async (id) => {
onMounted(() => {});
watch(selectedBtn, (newValue) => {
changeParams({
...searchParams.value,
subSys_id: newValue.key,
});
if (newValue && newValue.key) {
changeParams({
...searchParams.value,
subSys_id: newValue.key,
});
}
});
watch(
() => searchParams,
(newValue) => {
if(newValue.value.mainSys_id){
if (newValue.value.mainSys_id) {
getSubSystems(parseInt(newValue.value.mainSys_id));
}
},
@ -58,37 +62,54 @@ const edit = (item) => {
};
const deleteItem = async (id) => {
deleteAssetSubItem(id);
getSubSystems();
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await deleteAssetSubItem(id);
if (res.isSuccess) {
openToast("success", t("msg.delete_success"));
getSubSystems(parseInt(searchParams.value.mainSys_id));
} else {
openToast("error", res.msg);
}
});
};
</script>
<template>
<div class="mt-4">
<!-- <AssetSubListAddModal
:openModal="openModal"
:onCancel="onCancel"
:getData="getSubList"
:editRecord="editRecord"
/> -->
<div class="flex items-center gap-4 mb-4">
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
{{ $t("history.device_category") }} :
</h2>
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
<AssetSubListAddModal
:openModal="openModal"
:onCancel="onCancel"
:getData="getSubSystems"
:editRecord="editRecord"
/>
<button
@click.stop.prevent="isEditMode = !isEditMode"
class="btn btn-sm btn-outline-success mr-3"
>
{{ isEditMode ? t("button.stop_edit") : t("button.start_edit") }}
</button>
</div>
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
if (!isEditMode) {
changeActiveBtn(item);
}
"
:className="`flex w-full mt-2`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
<!-- <template v-if="!item.is_IOT">
}
"
:className="`flex w-full mt-2`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
<template v-if="isEditMode">
<span
class="ml-2 text-base text-warning"
@click.stop.prevent="() => edit(item)"
@ -101,10 +122,9 @@ const deleteItem = async (id) => {
>
<FontAwesomeIcon :icon="['fas', 'trash-alt']" />
</span>
</template> -->
</template>
</ButtonConnectedGroup>
</div>
</template>
</ButtonConnectedGroup>
</div>
</template>

View File

@ -2,9 +2,11 @@
import { ref, defineProps, onMounted, watch } from "vue";
import * as yup from "yup";
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
import useSearchParam from "@/hooks/useSearchParam";
import { getAssetMainList, postAssetSubList } from "@/apis/asset";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const props = defineProps({
openModal: Function,
onCancel: Function,
@ -66,19 +68,19 @@ const onOk = async () => {
});
if (res.isSuccess) {
props.getData();
props.getData(parseInt(searchParams.value.mainSys_id));
props.onCancel();
}
};
</script>
<template>
<button class="btn btn-sm btn-success mr-3" @click.stop.prevent="openModal">
<button class="btn btn-sm btn-success" @click.stop.prevent="openModal">
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
</button>
<Modal
id="asset_add_sub_item"
:title="t('assetManagement.add_category')"
:title="props.editRecord?.id ? t('assetManagement.edit_device_category') : t('assetManagement.add_device_category')"
:open="open"
:onCancel="onCancel"
width="300"
@ -104,7 +106,7 @@ const onOk = async () => {
<Select
:options="mainSystem"
Attribute="system_key"
class="mr-5"
class=""
name="system_parent_id"
:value="formState"
selectClass="border-info focus-within:border-info"

View File

@ -15,7 +15,7 @@ const getSubSystems = async () => {
key: subSystem.sub_system_tag,
active: searchParams.value?.subSys_id
? searchParams.value.subSys_id === subSystem.sub_system_tag
: subSystem.sub_system_tag == "DP",
: index == 0,
}));
});
setItems(subSystems);