大小類篩選

This commit is contained in:
koko1108 2024-12-05 18:17:13 +08:00
parent 5e13d284d3
commit 3d06cab696
17 changed files with 322 additions and 161 deletions

View File

@ -17,8 +17,8 @@ import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import { object } from "yup";
export const getAssetSubList = async () => {
const res = await instance.post(GET_ASSET_SUB_LIST_API);
export const getAssetSubList = async (variable_id) => {
const res = await instance.post(GET_ASSET_SUB_LIST_API, { variable_id });
return apihandler(res.code, res.data, {
msg: res.msg,

View File

@ -6,6 +6,7 @@ import {
POST_OPERATION_RECORD_API,
GET_OPERATION_EXPORT_API,
GET_OPERATION_FORMID_API,
DELETE_OPERATION_RECORD_API,
POST_OPERATION_COMPANY_API,
UPDATE_OPERATION_COMPANY_API,
DELETE_OPERATION_COMPANY_API,
@ -23,10 +24,10 @@ export const getOperationRecord = async ({
}) => {
const res = await instance.post(GET_OPERATION_RECORD_API, {
work_type: parseInt(work_type),
start_created_at: dayjs(start_created_at).format("YYYY-MM-DDTHH:mm:ss"),
end_created_at: dayjs(end_created_at)
.date(dayjs(end_created_at).get("date") + 1)
.format("YYYY-MM-DDTHH:mm:ss"),
// start_created_at: dayjs(start_created_at).format("YYYY-MM-DDTHH:mm:ss"),
// end_created_at: dayjs(end_created_at)
// .date(dayjs(end_created_at).get("date") + 1)
// .format("YYYY-MM-DDTHH:mm:ss"),
serial_number: serial_number || null,
main_system_tag: null,
sub_system_tag:

View File

@ -37,7 +37,7 @@ watch(
role="alert"
:class="
twMerge(
`alert text-xl rounded-md absolute left-1/2 -translate-x-1/2 top-5 z-[1000] max-w-fit`,
`alert text-xl rounded-md fixed left-1/2 -translate-x-1/2 top-24 z-[1000] max-w-fit`,
status === 'info'
? 'alert-info'
: status === 'error'

View File

@ -160,6 +160,7 @@
"start_time": "预计开始时间",
"upload": "档案上传",
"finish_time": "完成时间",
"updated_time": "更新时间",
"operation": "功能",
"vendor": "厂商",
"contact_person": "联络人",
@ -281,6 +282,7 @@
"email_format": "请输入正确 Email 地址",
"password_format": "密码长度至少8码必须包含英文及数字",
"start_time_placeholder": "请输入预计开始日期",
"finish_time_placeholder": "请输入完成日期",
"rename": "重新命名",
"download": "下载",
"confirm": "确认",

View File

@ -160,6 +160,7 @@
"start_time": "預計開始時間",
"upload": "檔案上傳",
"finish_time": "完成時間",
"updated_time": "更新時間",
"operation": "功能",
"vendor": "廠商",
"contact_person": "聯絡人",
@ -281,6 +282,7 @@
"email_format": "請輸入正確的 Email 地址",
"password_format": "密碼長度至少8碼必須包含英文及數字",
"start_time_placeholder": "請輸入預計開始日期",
"finish_time_placeholder": "請輸入完成日期",
"rename": "重新命名",
"download": "下載",
"confirm": "確認",

View File

@ -160,6 +160,7 @@
"start_time": "Estimated Start Time",
"upload": "File Upload",
"finish_time": "Completion Time",
"updated_time": "Update Time",
"operation": "Function",
"vendor": "Company",
"contact_person": "Contact Person",
@ -281,6 +282,7 @@
"email_format": "Please enter correct email address",
"password_format": "The password must be at least 8 characters long and must contain English and numbers.",
"start_time_placeholder": "Please enter expected start date",
"finish_time_placeholder": "Please enter completion date",
"rename": "Rename",
"download": "Download",
"confirm": "Confirm",

View File

@ -1,4 +1,5 @@
<script setup>
import AssetMainList from "./components/AssetMainList.vue";
import AssetSubList from "./components/AssetSubList.vue";
import AssetTable from "./components/AssetTable.vue";
</script>
@ -7,6 +8,7 @@ import AssetTable from "./components/AssetTable.vue";
<h1 class="text-2xl font-extrabold mb-2">
{{ $t("assetManagement.title") }}
</h1>
<AssetMainList />
<AssetSubList />
<AssetTable />
</template>

View File

@ -0,0 +1,59 @@
<script setup>
import { getAssetMainList } from "@/apis/asset";
import { ref, onMounted, watch, inject } from "vue";
import useSearchParam from "@/hooks/useSearchParam";
import useActiveBtn from "@/hooks/useActiveBtn";
const { searchParams, changeParams } = useSearchParam();
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const { openToast, cancelToastOpen } = inject("app_toast");
const getMainSystems = async () => {
const res = await getAssetMainList();
const cate = res.data.map((d, index) => ({
...d,
title: d.system_key,
key: d.id,
active: searchParams.value?.mainSys_id
? parseInt(searchParams.value?.mainSys_id) === d.id
: index === 0,
}));
setItems(cate);
};
onMounted(() => {
getMainSystems();
});
watch(selectedBtn, (newValue) => {
changeParams({
...searchParams.value,
mainSys_id: newValue.key,
subSys_id: null,
});
});
</script>
<template>
<div class="flex items-center gap-4 mb-4">
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
{{ $t("history.system_category") }} :
</h2>
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
changeActiveBtn(item);
}
"
:className="`flex w-full mt-2`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
</template>
</ButtonConnectedGroup>
</div>
</template>
<style lang="scss" scoped></style>

View File

@ -8,9 +8,9 @@ import AssetSubListAddModal from "./AssetSubListAddModal.vue";
const { searchParams, changeParams } = useSearchParam();
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const getSubSystems = async () => {
const res = await getAssetSubList();
const sub = res.data.map((d, index) => ({
const getSubSystems = async (id) => {
const res = await getAssetSubList(id);
sub = res.data.map((d, index) => ({
...d,
title: d.system_key,
key: d.id,
@ -21,14 +21,27 @@ const getSubSystems = async () => {
setItems(sub);
};
onMounted(() => {
getSubSystems();
});
onMounted(() => {});
watch(selectedBtn, (newValue) => {
changeParams({ subSys_id: newValue.key });
changeParams({
...searchParams.value,
subSys_id: newValue.key,
});
});
watch(
() => searchParams,
(newValue) => {
if(newValue.value.mainSys_id){
getSubSystems(newValue.value.mainSys_id);
}
},
{
deep: true,
}
);
const editRecord = ref(null);
// modal
const openModal = () => {
@ -58,20 +71,24 @@ const deleteItem = async (id) => {
:getData="getSubList"
:editRecord="editRecord"
/> -->
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
changeActiveBtn(item);
}
"
:className="`flex w-full mt-4`"
size="sm"
color="info"
>
<template #buttonContent="{ item }">
<span class="text-base">{{ item.title }}</span>
<!-- <template v-if="!item.is_IOT">
<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) => {
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">
<span
class="ml-2 text-base text-warning"
@click.stop.prevent="() => edit(item)"
@ -85,8 +102,9 @@ const deleteItem = async (id) => {
<FontAwesomeIcon :icon="['fas', 'trash-alt']" />
</span>
</template> -->
</template>
</ButtonConnectedGroup>
</template>
</ButtonConnectedGroup>
</div>
</div>
</template>

View File

@ -84,15 +84,15 @@ const submitBtns = computed(() => [
btn: "btn-search",
disabled: isSearchButtonDisabled.value,
},
{
title: t("button.export"),
key: "export",
icon: "download",
btn: "btn-export",
active: false,
onClick: (e) => submit(e, "export"),
disabled: isSearchButtonDisabled.value,
},
// {
// title: t("button.export"),
// key: "export",
// icon: "download",
// btn: "btn-export",
// active: false,
// onClick: (e) => submit(e, "export"),
// disabled: isSearchButtonDisabled.value,
// },
]);
const once = ref(false);

View File

@ -26,6 +26,9 @@ const updateDataSource = (data) => {
finish_time: d?.finish_time
? dayjs(d?.finish_time).format("YYYY-MM-DD")
: "",
updated_at: d?.updated_at
? dayjs(d?.updated_at).format("YYYY-MM-DD")
: "",
}));
};
@ -59,7 +62,7 @@ const getModalDevList = async () => {
device_building_tag: store.buildings[0].building_tag,
device_area_tag: "NTPC",
});
return res.data.map((d) => ({ ...d, key: d.device_number }));
return res.data.map((d) => ({ ...d, key: d.main_id }));
};
const getNewFormId = async (id = "") => {
if (!id) {
@ -102,7 +105,9 @@ const getAllOptions = async (id = "") => {
const openModal = async (id = "") => {
console.log("open modal", id);
getAllOptions(id);
if(searchParams.value?.work_type < 3){
getAllOptions(id);
}
operation_action_item.showModal();
};

View File

@ -37,15 +37,15 @@ const submitBtns = computed(() => [
onClick: search,
disabled: isSearchDisabled.value,
},
{
title: t("button.export"),
key: "export",
icon: "download",
btn: "btn-export",
active: false,
onClick: exportFile,
disabled: isSearchDisabled.value,
},
// {
// title: t("button.export"),
// key: "export",
// icon: "download",
// btn: "btn-export",
// active: false,
// onClick: exportFile,
// disabled: isSearchDisabled.value,
// },
]);
const once = ref(true);

View File

@ -6,8 +6,8 @@ import OperationSearchSubSys from "./OperationSearchSubSys.vue";
import OperationActionButton from "./OperationActionButton.vue";
import useSearchParam from "@/hooks/useSearchParam";
import { twMerge } from "tailwind-merge";
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const { search } = inject("operation_table");
@ -30,7 +30,7 @@ const {
const setButtonItems = () => {
setWorkTypesItems([
{
title: t('operation.repair'),
title: t("operation.repair"),
key: "fix",
active:
searchParams.value.work_type === "2" || !searchParams.value.work_type,
@ -38,14 +38,14 @@ const setButtonItems = () => {
params: ["work_type", "sub_system_tag"],
},
{
title: t('operation.maintenance'),
title: t("operation.maintenance"),
key: "maintain",
active: searchParams.value.work_type === "1",
work_type: 1,
params: ["work_type", "sub_system_tag"],
},
{
title: t('operation.company_info'),
title: t("operation.company_info"),
key: "company_info",
active: false,
active: searchParams.value.work_type === null,
@ -55,18 +55,18 @@ const setButtonItems = () => {
]);
setSearchTypesItems([
// {
// title: t('operation.date'),
// key: "date",
// active:
// searchParams.value.search_type === "date" ||
// !searchParams.value.search_type,
// params: ["start_created_at", "end_created_at"],
// },
{
title: t('operation.date'),
key: "date",
active:
searchParams.value.search_type === "date" ||
!searchParams.value.search_type,
params: ["start_created_at", "end_created_at"],
},
{
title: t('operation.serial'),
title: t("operation.serial"),
key: "serial",
active: searchParams.value.search_type === "serial",
active: 1,
params: ["serial_number"],
},
]);
@ -126,19 +126,22 @@ watch(
ref="form"
class="w-full flex flex-wrap flex-col custom-border p-4 mb-4"
>
<ButtonGroup
:items="workTypesItems"
:withLine="true"
:onclick="
(e, item) => {
changeWorkTypeActiveBtn(item);
}
"
/>
<OperationSearchSubSys
:class="twMerge(selectedWorkType?.work_type === 3 ? 'hidden' : 'block')"
/>
<div class="w-full flex flex-wrap items-center justify-start">
<ButtonGroup
:items="workTypesItems"
:withLine="true"
:onclick="
(e, item) => {
changeWorkTypeActiveBtn(item);
}
"
/>
<ButtonGroup
v-if="selectedWorkType?.work_type !== 3"
:class="twMerge('ml-8 mr-3')"
:class="twMerge('mr-3')"
:items="searchTypesItems"
:withLine="true"
:onclick="
@ -151,9 +154,7 @@ watch(
<OperationSearchType :selected="selectedSearchType" />
<OperationActionButton :selectedWorkType="selectedWorkType" />
</div>
<OperationSearchSubSys
:class="twMerge(selectedWorkType?.work_type === 3 ? 'hidden' : 'block')"
/>
</form>
</template>

View File

@ -1,89 +1,115 @@
<script setup>
import useBuildingStore from "@/stores/useBuildingStore";
import Checkbox from "@/components/customUI/Checkbox.vue";
import { getAssetMainList, getAssetSubList } from "@/apis/asset";
import { computed, onMounted, ref, watch } from "vue";
import useSearchParam from "@/hooks/useSearchParam";
import { useI18n } from 'vue-i18n';
import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const store = useBuildingStore();
//
const {
items: sysMainTagItems,
changeActiveBtn: changeMainSysActiveBtn,
setItems: setMainSysItems,
selectedBtn: selectedMainSysItems,
} = useActiveBtn();
//
const {
items: sysTagItems,
changeActiveBtn: changeSysActiveBtn,
setItems: setSysItems,
selectedBtn: selectedSysItems,
} = useActiveBtn("multiple");
const changeCheckedItem = () => {
if (checkedItem.value.length === store.subSys.length) {
changeParams({
...searchParams.value,
sub_system_tag: [],
});
} else {
changeParams({
...searchParams.value,
sub_system_tag: store.subSys.map(({ sub_system_tag }) => sub_system_tag),
});
}
const getMainSystems = async () => {
const res = await getAssetMainList();
const cate = res.data.map((d, index) => ({
...d,
title: d.system_key,
key: d.id,
active: searchParams.value?.mainSys_id
? parseInt(searchParams.value?.mainSys_id) === d.id
: index === 0,
}));
setMainSysItems(cate);
};
const onChange = (value, checked) => {
if (checked) {
changeParams({
...searchParams.value,
sub_system_tag: searchParams.value.sub_system_tag
? typeof searchParams.value.sub_system_tag === "string"
? [searchParams.value.sub_system_tag, value]
: [...searchParams.value.sub_system_tag, value]
: [value],
});
} else {
changeParams({
...searchParams.value,
sub_system_tag: searchParams.value.sub_system_tag.filter(
(sub) => sub !== value
),
});
}
const getSubSystems = async (id) => {
const res = await getAssetSubList(id);
const sub = res.data.map((d, index) => ({
...d,
title: d.system_key,
key: d.system_value,
active: searchParams.value?.sub_system_tag
? parseInt(searchParams.value?.sub_system_tag) === d.system_value
: index === 0,
}));
setSysItems(sub);
};
const checkedItem = computed(() =>
searchParams.value.sub_system_tag
? typeof searchParams.value.sub_system_tag === "string"
? [searchParams.value.sub_system_tag]
: searchParams.value.sub_system_tag
: []
);
watch(searchParams, (newValue, oldValue) => {
if (
(!oldValue.work_type || oldValue.work_type == "3") &&
!newValue.sub_system_tag
) {
changeParams({
...newValue,
sub_system_tag: [store.subSys[0]?.sub_system_tag],
});
}
onMounted(() => {
getMainSystems();
});
watch(selectedMainSysItems, (newValue) => {
changeParams({
...searchParams.value,
mainSys_id: newValue.key,
sub_system_tag: null,
});
});
// watch(selectedSysItems, (newValue) => {
// changeParams({
// ...searchParams.value,
// sub_system_tag: newValue.map((d) => d.key),
// });
// });
watch(
() => searchParams,
(newValue, oldValue) => {
if (newValue.mainSys_id && newValue.mainSys_id !== oldValue.mainSys_id) {
getSubSystems(newValue.value.mainSys_id);
}
},
{
deep: true,
}
);
</script>
<template>
<div class="flex flex-wrap items-center mt-6">
<h2 class="text-lg font-bold ps-1 pe-4">
<div>
<div class="flex items-center gap-4 my-4">
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
{{ $t("history.system_category") }} :
</h2>
<ButtonGroup
:items="sysMainTagItems"
:withLine="true"
:onclick="
(e, item) => {
changeMainSysActiveBtn(item);
}
"
/>
</div>
<div class="flex items-center gap-4 my-4">
<h2 class="text-lg font-bold ps-2 whitespace-nowrap">
{{ $t("history.device_category") }} :
</h2>
<button
class="btn btn-sm btn-success"
@click.stop.prevent="changeCheckedItem"
>
{{ checkedItem.length === store.subSys.length ? t("button.deselect_all") : t("button.select_all") }}
</button>
<Checkbox
v-for="sub in store.subSys"
:key="sub.key"
:title="sub.full_name"
:value="sub.sub_system_tag"
:checked="checkedItem.includes(sub.sub_system_tag)"
class="mx-3 my-3 xl:my-0 text-lg"
:onChange="onChange"
/>
</h2>
<ButtonGroup
:items="sysTagItems"
:withLine="true"
:onclick="
(e, item) => {
changeSysActiveBtn(item);
}
"
/>
</div>
</div>
</template>

View File

@ -48,7 +48,7 @@ const deleteItem = async (id) => {
<Table :loading="tableLoading" :columns="columns" :dataSource="dataSource">
<template #bodyCell="{ record, column, index }">
<template v-if="column.key === 'lorf'">
<span v-if="record.lorf.length === 0"></span>
<span v-if="record.lorf?.length === 0"></span>
<template v-else>
<span class="flex">
<a

View File

@ -38,6 +38,7 @@ const formState = ref([
status: "",
work_person_id: "",
start_time: "",
finish_time: "",
notice: "",
description: "",
lorf: [],
@ -52,6 +53,7 @@ const formState = ref([
status: "",
work_person_id: "",
start_time: "",
finish_time: "",
notice: "",
description: "",
lorf: [],
@ -109,6 +111,16 @@ const dateItem = ref([
},
]);
const dateItem2 = ref([
{
key: "finish_time",
name: "finish_time",
value: dayjs(),
dateFormat: "yyyy-MM-dd",
placeholder: t("button.finish_time_placeholder"),
},
]);
const form = ref(null);
const {
formErrorMsg: maintainFormErrorMsg,
@ -137,7 +149,13 @@ const saveMaintain = async () => {
"start_time",
dayjs(dateItem.value[0].value).format("YYYY-MM-DD")
);
formData.append(
"finish_time",
dayjs(dateItem2.value[0].value).format("YYYY-MM-DD")
);
props.editRecord.id && formData.append("id", props.editRecord.id);
props.editRecord.id &&
formData.append("fix_do_code", props.editRecord.fix_do_code);
const value = await handleMaintainSubmit(
maintainSchema,
@ -162,7 +180,7 @@ const saveCompany = async () => {
formState.value[searchParams.value?.work_type - 1]
);
let res;
if (props.editRecord.id) {
if (props.editRecord) {
res = await updateOperationCompany(value);
} else {
res = await postOperationCompany(value);
@ -222,6 +240,15 @@ watch(
) {
dateItem.value[0].value = newVal.start_time;
}
if (
Object.hasOwn(
formState.value[searchParams.value?.work_type - 1],
"finish_time"
)
) {
dateItem2.value[0].value = newVal.finish_time;
}
}
if (
Object.hasOwn(
@ -314,9 +341,9 @@ watch(
class="my-2"
selectClass="border-info focus-within:border-info"
name="fix_do_code"
Attribute="device_name"
Attribute="full_name"
:options="model_data.model_devList"
:disabled="formState[searchParams?.work_type - 1].error_code"
:disabled="props.editRecord?.id !== ''"
>
<template #topLeft>{{ $t("operation.repair_item_code") }}</template>
<template #bottomLeft
@ -338,7 +365,9 @@ watch(
:options="model_data.model_companyList"
:required="true"
>
<template #topLeft>{{ $t("operation.responsible_vendor") }}</template>
<template #topLeft>{{
$t("operation.responsible_vendor")
}}</template>
<template #bottomLeft
><span class="text-error text-base">
{{ maintainFormErrorMsg.fix_firm }}
@ -369,6 +398,19 @@ watch(
>
<template #topLeft>{{ $t("operation.status") }}</template>
</RadioGroup>
<DateGroup
class="my-2"
:items="dateItem2"
inputClass="w-full shadow-none"
:required="true"
>
<template #topLeft>{{ $t("operation.finish_time") }}</template>
<template #bottomLeft
><span class="text-error text-base">
{{ maintainFormErrorMsg.finish_time }}
</span></template
>
</DateGroup>
<Select
v-if="
searchParams?.work_type &&

View File

@ -3,10 +3,10 @@ export const getFIX_COL = (t) => [
title: t("operation.project"),
key: "work_type_name",
},
{
title: t("operation.location"),
key: "location",
},
// {
// title: t("operation.location"),
// key: "location",
// },
{
title: t("operation.uuid"),
key: "error_code",
@ -44,10 +44,11 @@ export const getFIX_COL = (t) => [
key: "finish_time",
sort: true,
},
// {
// title: "建立時間",
// key: "created_at",
// },
{
title: t("operation.updated_time"),
key: "updated_at",
sort: true,
},
{
title: t("operation.operation"),
key: "operation",