fix: 設定 - 維運廠商 - modal 無法關閉問題

This commit is contained in:
MJM_2025_05\polly 2025-09-24 16:09:04 +08:00
parent 4db268d86b
commit 36e390d300
2 changed files with 190 additions and 125 deletions

View File

@ -1,38 +1,22 @@
<script setup> <script setup>
import Table from "@/components/customUI/Table.vue"; import Table from "@/components/customUI/Table.vue";
import VendorModal from "./VendorModal.vue"; import VendorModal from "./VendorModal.vue";
import { getOperationCompanyList,deleteOperationCompany } from "@/apis/operation"; import {
getOperationCompanyList,
deleteOperationCompany,
} from "@/apis/operation";
import { onMounted, ref, inject, computed } from "vue"; import { onMounted, ref, inject, computed } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast"); const { openToast, cancelToastOpen } = inject("app_toast");
const columns = computed(() => [ const columns = computed(() => [
{ { title: t("operation.vendor"), key: "name" },
title: t("operation.vendor"), { title: t("operation.contact_person"), key: "contact_person" },
key: "name", { title: t("operation.phone"), key: "phone" },
}, { title: t("operation.email"), key: "email" },
{ { title: t("operation.created_at"), key: "created_at" },
title: t("operation.contact_person"), { title: t("operation.operation"), key: "operation", width: 200 },
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: 200,
},
]); ]);
const dataSource = ref([]); const dataSource = ref([]);
@ -49,7 +33,9 @@ onMounted(() => {
getDataSource(); getDataSource();
}); });
const formState = ref({ // ====== Modal ======
const MODAL_ID = "company_modal";
const emptyForm = () => ({
contact_person: "", contact_person: "",
email: "", email: "",
name: "", name: "",
@ -60,22 +46,36 @@ const formState = ref({
address: "", address: "",
}); });
const openModal = (record) => { const formState = ref(emptyForm());
if (record.id) {
formState.value = { ...record }; // (/)
} else { const openModal = (payload) => {
formState.value = { const el = document.getElementById(MODAL_ID);
contact_person: "",
email: "", //
name: "", if (payload === false) {
phone: "", try {
remark: "", el?.close?.();
tax_id_number: "", } catch {}
city: "", return;
address: "", }
};
// true
if (payload === true || payload == null) {
formState.value = emptyForm();
try {
el?.showModal?.();
} catch {}
return;
}
// record
if (payload && typeof payload === "object") {
formState.value = { ...emptyForm(), ...payload }; //
try {
el?.showModal?.();
} catch {}
} }
company_modal.showModal();
}; };
const remove = async (id) => { const remove = async (id) => {
@ -95,15 +95,19 @@ const remove = async (id) => {
<template> <template>
<div class="flex justify-start items-center mt-10 mb-5"> <div class="flex justify-start items-center mt-10 mb-5">
<h3 class="text-xl mr-5">{{ $t("assetManagement.company") }}</h3> <h3 class="text-xl mr-5">{{ $t("assetManagement.company") }}</h3>
<!-- 子層會渲染新增按鈕照你的原樣 -->
<VendorModal <VendorModal
:formState="formState" :formState="formState"
:getData="getDataSource" :getData="getDataSource"
:openModal="openModal" :openModal="openModal"
/> />
</div> </div>
<Table :columns="columns" :dataSource="dataSource" :loading="loading"> <Table :columns="columns" :dataSource="dataSource" :loading="loading">
<template #bodyCell="{ record, column, index }"> <template #bodyCell="{ record, column, index }">
<template v-if="column.key === 'index'">{{ index + 1 }}</template> <template v-if="column.key === 'index'">{{ index + 1 }}</template>
<template v-else-if="column.key === 'operation'"> <template v-else-if="column.key === 'operation'">
<button <button
class="btn btn-sm btn-success text-white mr-2" class="btn btn-sm btn-success text-white mr-2"
@ -118,6 +122,7 @@ const remove = async (id) => {
{{ $t("button.delete") }} {{ $t("button.delete") }}
</button> </button>
</template> </template>
<template v-else> <template v-else>
{{ record[column.key] }} {{ record[column.key] }}
</template> </template>

View File

@ -1,23 +1,21 @@
<script setup> <script setup>
import { ref, onMounted, defineProps, inject, watch } from "vue"; import { ref, inject } from "vue";
import * as yup from "yup"; import * as yup from "yup";
import "yup-phone-lite"; import "yup-phone-lite";
import useFormErrorMessage from "@/hooks/useFormErrorMessage"; import useFormErrorMessage from "@/hooks/useFormErrorMessage";
import { import { postOperationCompany, updateOperationCompany } from "@/apis/operation";
postOperationCompany,
updateOperationCompany,
} from "@/apis/operation";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { t } = useI18n();
const { openToast } = inject("app_toast"); const { openToast } = inject("app_toast");
const props = defineProps({ const props = defineProps({
formState: Object, formState: Object,
getData: Function, getData: Function,
openModal: Function openModal: Function, // / modal
}); });
const deptScheme = yup.object({ const schema = yup.object({
name: yup.string().required(t("button.required")), name: yup.string().required(t("button.required")),
contact_person: yup.string().nullable(true), contact_person: yup.string().nullable(true),
email: yup.string().email().nullable(true), email: yup.string().email().nullable(true),
@ -28,34 +26,104 @@ const deptScheme = yup.object({
remark: yup.string().nullable(true), remark: yup.string().nullable(true),
}); });
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } = const { formErrorMsg, handleSubmit, handleErrorReset } =
useFormErrorMessage(deptScheme); useFormErrorMessage(schema);
const loading = ref(false);
const MODAL_ID = "company_modal";
/** ====== 關閉 Modal多重保險 ====== */
const closeModal = () => {
// 1) boolean
if (typeof props.openModal === "function") {
try {
if (props.openModal.length >= 1) {
// openModal(false)
props.openModal(false);
} else {
// toggler false
try {
props.openModal(false);
} catch {
props.openModal();
}
}
return;
} catch (_) {}
}
// 2) <dialog> close() Modal
const el = document.getElementById(MODAL_ID);
if (el?.close) {
try {
el.close();
return;
} catch (_) {}
}
// 3) Modal
try {
el?.dispatchEvent?.(new CustomEvent("close", { bubbles: true }));
} catch (_) {}
};
/** ====== 開啟 Modal呼叫父層 ====== */
const openModal = () => {
if (typeof props.openModal === "function") {
try {
if (props.openModal.length >= 1) props.openModal(true);
else props.openModal();
} catch {
//
}
}
};
const onCancel = () => { const onCancel = () => {
handleErrorReset(); //
company_modal.close(); //
closeModal();
}; };
const onOk = async () => { const onOk = async () => {
const value = await handleSubmit(deptScheme, props.formState); try {
loading.value = true;
const value = await handleSubmit(schema, props.formState);
let res;
if (props.formState?.id) { if (props.formState?.id) {
// API id updateOperationCompany(props.formState.id, value)
res = await updateOperationCompany(value); res = await updateOperationCompany(value);
} else { } else {
res = await postOperationCompany(value); res = await postOperationCompany(value);
} }
if (res.isSuccess) {
props.getData(); if (res?.isSuccess) {
onCancel(); await props.getData?.();
props.openModal(false);
//
closeModal();
//
handleErrorReset();
props.openModal(false);
openToast?.("success", t("common.success"), `#${MODAL_ID}`);
} else { } else {
openToast("error", res.msg, "#company_modal"); openToast?.("error", res?.msg ?? t("common.failed"), `#${MODAL_ID}`);
}
} catch (err) {
openToast?.("error", err?.message ?? t("common.failed"), `#${MODAL_ID}`);
} finally {
loading.value = false;
} }
}; };
</script> </script>
<template> <template>
<button class="btn btn-sm btn-add " @click.stop.prevent="props.openModal"> <button class="btn btn-sm btn-add" @click.stop.prevent="openModal">
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }} <font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
</button> </button>
<Modal <Modal
id="company_modal" id="company_modal"
:title="props.formState?.id ? t('button.edit') : t('button.add')" :title="props.formState?.id ? t('button.edit') : t('button.add')"
@ -63,87 +131,79 @@ const onOk = async () => {
width="710" width="710"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form class="mt-5 w-full flex flex-wrap justify-between">
<Input :value="formState" class="my-2" name="name"> <Input :value="props.formState" class="my-2" name="name">
<template #topLeft>{{ $t("operation.name") }}</template> <template #topLeft>{{ $t("operation.name") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.name }}</span>
{{ formErrorMsg.name }} </template>
</span></template </Input>
></Input <Input :value="props.formState" class="my-2" name="contact_person">
>
<Input :value="formState" class="my-2" name="contact_person">
<template #topLeft>{{ $t("operation.contact_person") }}</template> <template #topLeft>{{ $t("operation.contact_person") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{
{{ formErrorMsg.contact_person }} formErrorMsg.contact_person
</span></template }}</span>
></Input </template>
> </Input>
<Input :value="formState" class="my-2" name="phone"> <Input :value="props.formState" class="my-2" name="phone">
<template #topLeft>{{ $t("operation.phone") }}</template> <template #topLeft>{{ $t("operation.phone") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.phone }}</span>
{{ formErrorMsg.phone }} </template>
</span></template </Input>
></Input <Input :value="props.formState" class="my-2" name="email">
>
<Input :value="formState" class="my-2" name="email">
<template #topLeft>{{ $t("operation.email") }}</template> <template #topLeft>{{ $t("operation.email") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.email }}</span>
{{ formErrorMsg.email }} </template>
</span></template </Input>
></Input <Input :value="props.formState" class="my-2" name="city">
>
<Input :value="formState" class="my-2" name="city">
<template #topLeft>{{ $t("operation.city") }}</template> <template #topLeft>{{ $t("operation.city") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.city }}</span>
{{ formErrorMsg.city }} </template>
</span></template </Input>
></Input <Input :value="props.formState" class="my-2" name="address">
>
<Input :value="formState" class="my-2" name="address">
<template #topLeft>{{ $t("operation.address") }}</template> <template #topLeft>{{ $t("operation.address") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.address }}</span>
{{ formErrorMsg.address }} </template>
</span></template </Input>
></Input <Input :value="props.formState" class="my-2" name="tax_id_number">
>
<Input :value="formState" class="my-2" name="tax_id_number">
<template #topLeft>{{ $t("operation.tax_id_number") }}</template> <template #topLeft>{{ $t("operation.tax_id_number") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{
{{ formErrorMsg.tax_id_number }} formErrorMsg.tax_id_number
</span></template }}</span>
></Input </template>
> </Input>
<Input :value="formState" class="my-2" name="remark"> <Input :value="props.formState" class="my-2" name="remark">
<template #topLeft>{{ $t("operation.remark") }}</template> <template #topLeft>{{ $t("operation.remark") }}</template>
<template #bottomLeft <template #bottomLeft>
><span class="text-error text-base"> <span class="text-error text-base">{{ formErrorMsg.remark }}</span>
{{ formErrorMsg.remark }} </template>
</span></template </Input>
></Input
>
</form> </form>
</template> </template>
<template #modalAction> <template #modalAction>
<button <button
type="reset" type="button"
class="btn btn-outline-success mr-2" class="btn btn-outline-success mr-2"
@click.prevent="onCancel" @click.prevent="onCancel"
:disabled="loading"
> >
{{ $t("button.cancel") }} {{ $t("button.cancel") }}
</button> </button>
<button <button
type="submit" type="button"
class="btn btn-outline-success" class="btn btn-outline-success"
@click.stop.prevent="onOk" @click.stop.prevent="onOk"
:disabled="loading"
> >
<span v-if="loading" class="loading loading-spinner loading-xs mr-2" />
{{ $t("button.submit") }} {{ $t("button.submit") }}
</button> </button>
</template> </template>