Files
web/app/pages/index.vue
2026-07-09 17:22:19 +07:00

137 lines
3.6 KiB
Vue

<template>
<ClientOnly>
<TopMenu @changeTab="changeTab" />
<main class="is-flex-grow-1 is-flex is-flex-direction-column is-gap-1">
<div
class="is-flex is-justify-content-space-between is-align-items-center is-gap-1"
v-if="tab"
>
<div>
<div class="fs-17 font-semibold is-flex is-gap-1 is-align-items-center mb-1">
<div
v-if="subtab"
class="is-flex is-gap-1 is-align-items-center"
>
<span>{{ tab[$store.lang] }}</span>
<Icon
name="material-symbols:arrow-forward-ios-rounded"
:size="13"
class="has-text-grey"
/>
<span>{{ subtab[$store.lang] }}</span>
</div>
<p v-else>{{ tab[$store.lang] }}</p>
<button
@click="refresh"
class="button is-primary is-light rounded-full p-1"
>
<Icon
name="material-symbols:refresh-rounded"
:size="20"
/>
</button>
</div>
<p class="has-text-grey fs-13 font-normal">
Cập nhật:
<NuxtTime
:datetime="Date.now() - 1000 * 60 * Math.random() * 10"
locale="vi-VN"
relative
/>
</p>
</div>
<div id="header-right-slot"></div>
</div>
<KeepAlive :exclude="exclude">
<component
:is="componentMap[vbind.component]"
v-bind="vbind"
/>
</KeepAlive>
</main>
</ClientOnly>
</template>
<script setup>
const { $createMeta, $filter, $copy, $store } = useNuxtApp();
const componentMap = {};
const exclude = ref([]);
const vbind = ref({});
const tab = ref();
const subtab = ref();
const currentTab = ref();
const toPascalCase = (str) => {
if (!str || typeof str !== "string") return str;
return str
.split("/")
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join("");
};
function changeTab(_tab, _subtab) {
tab.value = _tab;
subtab.value = _subtab;
currentTab.value = subtab.value || tab.value;
if (currentTab.value.detail) {
vbind.value =
$store.lang === "en" ? currentTab.value.detail_en || currentTab.value.detail : currentTab.value.detail;
}
componentMap[vbind.value.component] = vbind.value.base || toPascalCase(vbind.value.component);
$store.commit("tabinfo", {
tab: tab.value,
subtab: subtab.value,
current: currentTab.value,
vbind: vbind.value,
});
const meta = {
title: currentTab.value[$store.lang],
image: undefined,
description: "ERP",
type: "article",
keywords: "erp",
};
useHead($createMeta(meta));
}
function changeToRandomTab(originalTabId) {
const topmenus = $filter($store.common, { category: "topmenu" });
const otherTabs = topmenus.filter((m) => m.id !== originalTabId);
const randomTab = otherTabs[0];
changeTab(randomTab);
}
async function refresh() {
const oriTab = $copy(tab.value);
const oriSubTab = $copy(subtab.value);
const oriCurrentTab = $copy(currentTab.value);
const oriComp = oriCurrentTab.detail.base;
exclude.value.push(oriComp);
changeToRandomTab(oriCurrentTab.id);
await nextTick();
changeTab(oriTab, oriSubTab);
exclude.value.splice(0, 1);
}
</script>
<style lang="scss" scoped>
@use "bulma/sass/utilities/mixins.scss" as *;
main {
padding: 1rem 2rem 2rem;
@include mobile {
padding: 1rem;
}
}
.v-enter-active,
.v-leave-active {
transition: all 0.3s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>