Migrate all Vue components from Options API to <script setup>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 17:10:06 +08:00
parent a619be7881
commit 3b7b6ae859
61 changed files with 10835 additions and 11750 deletions

View File

@@ -9,7 +9,7 @@
<!-- 這裡不使用迴圈是因為src值用變數的話會沒辦法顯示svg -->
<li v-if="isAdmin" id="btn_acct_mgmt"
class="w-full h-[40px] flex py-2 px-4 hover:text-[#000000] hover:bg-[#F1F5F9] cursor-pointer
items-center" @click="onBtnAcctMgmtClick">
items-center" @click="onBtnAcctMgmtClick">
<span class="w-[24px] h-[24px] flex"><img src="@/assets/icon-crown.svg" alt="accountManagement"></span>
<span class="flex ml-[8px]">{{i18next.t("AcctMgmt.acctMgmt")}}</span>
</li>
@@ -29,110 +29,90 @@
</div>
</template>
<script>
import { computed, onMounted, ref, } from 'vue';
import { mapActions, mapState, storeToRefs } from 'pinia';
<script setup>
import { computed, onMounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import i18next from '@/i18n/i18n';
import { useRouter } from 'vue-router';
import { useRouter, useRoute } from 'vue-router';
import { useLoginStore } from '@/stores/login';
import { useAcctMgmtStore } from '@/stores/acctMgmt';
import { useAllMapDataStore } from '@/stores/allMapData';
import { useConformanceStore } from '@/stores/conformance';
import { leaveFilter, leaveConformance } from '@/module/alertModal.js';
import emitter from '@/utils/emitter';
export default {
setup() {
const { logOut } = useLoginStore();
const loginStore = useLoginStore();
const router = useRouter();
const allMapDataStore = useAllMapDataStore();
const conformanceStore = useConformanceStore();
const acctMgmtStore = useAcctMgmtStore();
const { tempFilterId } = storeToRefs(allMapDataStore);
const { conformanceLogTempCheckId } = storeToRefs(conformanceStore);
const router = useRouter();
const route = useRoute();
const loginStore = useLoginStore();
const allMapDataStore = useAllMapDataStore();
const conformanceStore = useConformanceStore();
const acctMgmtStore = useAcctMgmtStore();
const loginUserData = ref(null);
const currentViewingUserDetail = computed(() => acctMgmtStore.currentViewingUser.detail);
const isAdmin = ref(false);
const { logOut } = loginStore;
const { tempFilterId } = storeToRefs(allMapDataStore);
const { conformanceLogTempCheckId, conformanceFilterTempCheckId } = storeToRefs(conformanceStore);
const { userData } = storeToRefs(loginStore);
const { isAcctMenuOpen } = storeToRefs(acctMgmtStore);
const getIsAdminValue = async () => {
await loginStore.getUserData();
loginUserData.value = loginStore.userData;
await acctMgmtStore.getUserDetail(loginUserData.value.username);
isAdmin.value = acctMgmtStore.currentViewingUser.is_admin;
};
const onBtnMyAccountClick = async() => {
acctMgmtStore.closeAcctMenu();
await acctMgmtStore.getAllUserAccounts(); // in case we haven't fetched yet
await acctMgmtStore.setCurrentViewingUser(loginUserData.value.username);
await router.push('/my-account');
}
const loginUserData = ref(null);
const currentViewingUserDetail = computed(() => acctMgmtStore.currentViewingUser.detail);
const isAdmin = ref(false);
onMounted(async () => {
await getIsAdminValue();
});
return {
logOut,
tempFilterId,
conformanceLogTempCheckId,
allMapDataStore,
conformanceStore,
isAdmin,
onBtnMyAccountClick,
};
},
data() {
return {
i18next: i18next,
}
},
computed: {
...mapState(useLoginStore, ['userData']),
...mapState(useAcctMgmtStore, ['isAcctMenuOpen']),
},
methods: {
clickOtherPlacesThenCloseMenu(){
const acctMgmtButton = document.getElementById('acct_mgmt_button');
const acctMgmtMenu = document.getElementById('account_menu');
document.addEventListener('click', (event) => {
if (!acctMgmtMenu.contains(event.target) && !acctMgmtButton.contains(event.target)) {
this.closeAcctMenu();
}
});
},
onBtnAcctMgmtClick(){
this.$router.push({name: 'AcctAdmin'});
this.closeAcctMenu();
},
onLogoutBtnClick(){
if ((this.$route.name === 'Map' || this.$route.name === 'CheckMap') && this.tempFilterId) {
// 傳給 Map通知 Sidebar 要關閉。
this.$emitter.emit('leaveFilter', false);
leaveFilter(false, this.allMapDataStore.addFilterId, false, this.logOut)
} else if((this.$route.name === 'Conformance' || this.$route.name === 'CheckConformance')
&& (this.conformanceLogTempCheckId || this.conformanceFilterTempCheckId)) {
leaveConformance(false, this.conformanceStore.addConformanceCreateCheckId, false, this.logOut)
} else {
this.logOut();
}
},
...mapActions(useLoginStore, ['getUserData']),
...mapActions(useAcctMgmtStore, ['closeAcctMenu']),
},
created() {
this.getUserData();
},
mounted(){
this.clickOtherPlacesThenCloseMenu();
},
const getIsAdminValue = async () => {
await loginStore.getUserData();
loginUserData.value = loginStore.userData;
await acctMgmtStore.getUserDetail(loginUserData.value.username);
isAdmin.value = acctMgmtStore.currentViewingUser.is_admin;
};
const onBtnMyAccountClick = async () => {
acctMgmtStore.closeAcctMenu();
await acctMgmtStore.getAllUserAccounts(); // in case we haven't fetched yet
await acctMgmtStore.setCurrentViewingUser(loginUserData.value.username);
await router.push('/my-account');
};
const clickOtherPlacesThenCloseMenu = () => {
const acctMgmtButton = document.getElementById('acct_mgmt_button');
const acctMgmtMenu = document.getElementById('account_menu');
document.addEventListener('click', (event) => {
if (acctMgmtMenu && acctMgmtButton && !acctMgmtMenu.contains(event.target) && !acctMgmtButton.contains(event.target)) {
acctMgmtStore.closeAcctMenu();
}
});
};
const onBtnAcctMgmtClick = () => {
router.push({name: 'AcctAdmin'});
acctMgmtStore.closeAcctMenu();
};
const onLogoutBtnClick = () => {
if ((route.name === 'Map' || route.name === 'CheckMap') && tempFilterId.value) {
// 傳給 Map通知 Sidebar 要關閉。
emitter.emit('leaveFilter', false);
leaveFilter(false, allMapDataStore.addFilterId, false, logOut)
} else if((route.name === 'Conformance' || route.name === 'CheckConformance')
&& (conformanceLogTempCheckId.value || conformanceFilterTempCheckId.value)) {
leaveConformance(false, conformanceStore.addConformanceCreateCheckId, false, logOut)
} else {
logOut();
}
};
// created
loginStore.getUserData();
// mounted
onMounted(async () => {
await getIsAdminValue();
clickOtherPlacesThenCloseMenu();
});
</script>
<style>
#account_menu {
z-index: 2147483648;
}
</style>
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div id="search_bar_container" class="flex w-[280px] h-8 px-4 items-center border-[#64748B] border-[1px] rounded-full
<div id="search_bar_container" class="flex w-[280px] h-8 px-4 items-center border-[#64748B] border-[1px] rounded-full
justify-between">
<input id="input_search" class="w-full outline-0" :placeholder="i18next.t('AcctMgmt.Search')"
v-model="inputQuery" @keypress="handleKeyPressOfSearch"
@@ -9,30 +9,22 @@
</div>
</template>
<script>
import { ref, } from 'vue';
<script setup>
import { ref } from 'vue';
import i18next from '@/i18n/i18n.js';
export default {
setup(props, { emit, }) {
const inputQuery = ref("");
const onSearchClick = (event) => {
event.preventDefault();
emit('on-search-account-button-click', inputQuery.value);
};
const emit = defineEmits(['on-search-account-button-click']);
const handleKeyPressOfSearch = (event) => {
if (event.key === 'Enter') {
emit('on-search-account-button-click', inputQuery.value);
}
}
const inputQuery = ref("");
return {
inputQuery,
onSearchClick,
handleKeyPressOfSearch,
i18next,
};
},
const onSearchClick = (event) => {
event.preventDefault();
emit('on-search-account-button-click', inputQuery.value);
};
</script>
const handleKeyPressOfSearch = (event) => {
if (event.key === 'Enter') {
emit('on-search-account-button-click', inputQuery.value);
}
};
</script>