feat: PageFront에 모바일용 BottomBar 재구현
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<nav class="gameBottomBar navbar-expand navbar-dark bg-dark d-sm-block d-md-none p-0">
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav me-auto mx-auto">
|
||||
<li class="nav-item dropup">
|
||||
<div
|
||||
id="navbarGlobal"
|
||||
class="dropdown-toggle text-white btn btn-sammo-base2"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
외부 메뉴
|
||||
</div>
|
||||
<GlobalMenuBar
|
||||
id="navbarGlobalItems"
|
||||
aria-labelledby="navbarGlobal"
|
||||
:globalInfo="globalInfo"
|
||||
:modelValue="globalMenu"
|
||||
:columns="3"
|
||||
/>
|
||||
</li>
|
||||
<li class="nav-item dropup">
|
||||
<div
|
||||
id="navbarNation"
|
||||
class="dropdown-toggle btn btn-sammo-nation controlBar"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
국가 메뉴
|
||||
</div>
|
||||
<MainControlDropdown
|
||||
id="navbarNationItems"
|
||||
aria-labelledby="navbarNation"
|
||||
:showSecret="showSecret"
|
||||
:permission="frontInfo.general.permission"
|
||||
:myLevel="frontInfo.general.officerLevel"
|
||||
:nationLevel="nationInfo.level"
|
||||
/>
|
||||
</li>
|
||||
<li class="nav-item dropup">
|
||||
<div
|
||||
id="navbarQuick"
|
||||
class="dropdown-toggle text-white btn btn-dark"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
빠른 이동
|
||||
</div>
|
||||
<ul id="navbarQuickItems" class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item disabled">국가 정보</a></li>
|
||||
<hr class="dropdown-divider" />
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.nationNotice')">방침</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('#reservedCommandPanel')">명령</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.nationInfo')">국가</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.generalInfo')">장수</button>
|
||||
</li>
|
||||
<li><button type="button" class="dropdown-item" @click="scrollToSelector('.cityInfo')">도시</button></li>
|
||||
<li><a class="dropdown-item disabled">동향 정보</a></li>
|
||||
<hr class="dropdown-divider" />
|
||||
<li><button type="button" class="dropdown-item" @click="scrollToSelector('.mapView')">지도</button></li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.PublicRecord')">
|
||||
동향
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.GeneralLog')">개인</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.WorldHistory')">정세</button>
|
||||
</li>
|
||||
<li><span> </span></li>
|
||||
<li><a class="dropdown-item disabled">메시지</a></li>
|
||||
<hr class="dropdown-divider" />
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.PublicTalk')">전체</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.NationalTalk')">국가</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.PrivateTalk')">개인</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item" @click="scrollToSelector('.DiplomacyTalk')">외교</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="btn btn-sammo-base2" @click="moveLobby">로비로</button>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { GetFrontInfoResponse, GetMenuResponse } from "@/defs/API/Global";
|
||||
import { scrollToSelector } from "@/util/scrollToSelector";
|
||||
import { toRefs, watch, ref, computed } from "vue";
|
||||
import GlobalMenuBar from "./GlobalMenuDropdown.vue";
|
||||
import MainControlDropdown from "./MainControlDropdown.vue";
|
||||
|
||||
//FIXME: scrollToSelector
|
||||
|
||||
const props = defineProps<{
|
||||
frontInfo: GetFrontInfoResponse;
|
||||
globalMenu: GetMenuResponse["menu"];
|
||||
}>();
|
||||
|
||||
const { frontInfo, globalMenu } = toRefs(props);
|
||||
|
||||
const globalInfo = ref(frontInfo.value.global);
|
||||
watch(frontInfo, (frontInfo) => {
|
||||
globalInfo.value = frontInfo.global;
|
||||
});
|
||||
|
||||
const nationInfo = ref(frontInfo.value.nation);
|
||||
watch(frontInfo, (frontInfo) => {
|
||||
nationInfo.value = frontInfo.nation;
|
||||
});
|
||||
|
||||
function moveLobby() {
|
||||
location.replace("../");
|
||||
}
|
||||
|
||||
const showSecret = computed(() => {
|
||||
if (!frontInfo.value) {
|
||||
return false;
|
||||
}
|
||||
if (frontInfo.value.general.permission >= 1) {
|
||||
return true;
|
||||
}
|
||||
if (frontInfo.value.general.officerLevel >= 2) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@scss/common/break_500px.scss";
|
||||
@import "@scss/common/base.scss";
|
||||
|
||||
@include media-500px {
|
||||
.gameBottomBar {
|
||||
.nav-item ul.dropdown-menu {
|
||||
max-height: calc(100vh - 50px);
|
||||
overflow-y: auto;
|
||||
|
||||
li {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item > .btn {
|
||||
text-align: center;
|
||||
width: 125px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
box-shadow: 0 -1px 0 $dark;
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
}
|
||||
|
||||
#navbarNationItems {
|
||||
columns: 3;
|
||||
}
|
||||
|
||||
#navbarQuickItems {
|
||||
columns: 3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<ul class="dropdown-menu dropdown-menu-start">
|
||||
<template v-for="(item, idx) in filteredMenu" :key="idx">
|
||||
<li v-if="item.type === 'item'">
|
||||
<a class="dropdown-item" :href="item.url" :target="item.newTab ? '_blank' : undefined">
|
||||
{{ item.name }}
|
||||
</a>
|
||||
</li>
|
||||
<template v-else-if="item.type === 'multi'">
|
||||
<li :style="{ orphans: item.subMenu.length + 1 }">
|
||||
<span class="dropdown-item disabled">{{ item.name }}</span>
|
||||
</li>
|
||||
<li v-for="(subItem, subIdx) in item.subMenu" :key="subIdx">
|
||||
<a class="dropdown-item subItem" :href="subItem.url" :target="subItem.newTab ? '_blank' : undefined">{{
|
||||
subItem.name
|
||||
}}</a>
|
||||
</li>
|
||||
</template>
|
||||
<template v-else-if="item.type === 'split'">
|
||||
<li :style="{ orphans: item.subMenu.length + 1 }">
|
||||
<a class="dropdown-item" :href="item.main.url" :target="item.main.newTab ? '_blank' : undefined">{{
|
||||
item.main.name
|
||||
}}</a>
|
||||
</li>
|
||||
<li v-for="(subItem, subIdx) in item.subMenu" :key="subIdx">
|
||||
<a class="dropdown-item subItem" :href="subItem.url" :target="subItem.newTab ? '_blank' : undefined">{{
|
||||
subItem.name
|
||||
}}</a>
|
||||
</li>
|
||||
</template>
|
||||
</template>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { GetFrontInfoResponse, GetMenuResponse, MenuItem, MenuMulti, MenuSplit } from "@/defs/API/Global";
|
||||
import { isArray } from "lodash";
|
||||
import { computed, toRef } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: GetMenuResponse["menu"];
|
||||
globalInfo: GetFrontInfoResponse["global"];
|
||||
mobileRowSize?: number;
|
||||
desktopRowSize?: number;
|
||||
columns?: number;
|
||||
}>();
|
||||
|
||||
const columns = computed(() => {
|
||||
return props.columns ?? 3;
|
||||
});
|
||||
|
||||
const modelValue = toRef(props, "modelValue");
|
||||
const globalInfo = toRef(props, "globalInfo");
|
||||
|
||||
type MenuVariant = MenuItem | MenuSplit | MenuMulti;
|
||||
|
||||
function filterMenu(menu: MenuVariant | MenuVariant[]): MenuVariant | MenuVariant[] | undefined {
|
||||
if (isArray(menu)) {
|
||||
return menu.filter(filterMenu) as MenuVariant[];
|
||||
}
|
||||
|
||||
if (menu.type === "item") {
|
||||
if (!menu.condShowVar) {
|
||||
return menu;
|
||||
}
|
||||
const cond = menu.condShowVar;
|
||||
if (cond in globalInfo.value) {
|
||||
if (cond.startsWith("!")) {
|
||||
if (!globalInfo.value[cond.slice(1) as keyof GetFrontInfoResponse["global"]]) {
|
||||
return menu;
|
||||
}
|
||||
} else if (globalInfo.value[cond as keyof GetFrontInfoResponse["global"]]) {
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (menu.type === "multi") {
|
||||
const filtered = menu.subMenu.filter(filterMenu) as MenuVariant[];
|
||||
if (filtered.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
if (filtered.length === 1) {
|
||||
return filtered[0];
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
if (menu.type === "split") {
|
||||
const filterMain = filterMenu(menu.main);
|
||||
if (!filterMain) {
|
||||
return undefined;
|
||||
}
|
||||
const filtered = menu.subMenu.filter(filterMenu) as MenuVariant[];
|
||||
if (filtered.length === 0) {
|
||||
return filterMain;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
|
||||
const filteredMenu = computed(() => filterMenu(modelValue.value) as GetMenuResponse["menu"]);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@scss/common/break_500px.scss";
|
||||
|
||||
.subItem {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
columns: v-bind(columns);
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="`sam-color-${nationColor} controlBar`">
|
||||
<div class="controlBar">
|
||||
<a href="v_board.php" :class="`commandButton btn btn-sammo-nation ${myLevel >= 1 ? '' : 'disabled'}`">회 의 실</a>
|
||||
<a
|
||||
href="v_board.php?isSecret=true"
|
||||
@@ -84,10 +84,9 @@ const props = defineProps<{
|
||||
permission: number;
|
||||
myLevel: number;
|
||||
nationLevel: number;
|
||||
nationColor: string;
|
||||
}>();
|
||||
|
||||
const { showSecret, permission, myLevel, nationLevel, nationColor } = toRefs(props);
|
||||
const { showSecret, permission, myLevel, nationLevel } = toRefs(props);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -104,7 +103,7 @@ const { showSecret, permission, myLevel, nationLevel, nationColor } = toRefs(pro
|
||||
}
|
||||
}
|
||||
|
||||
@include media-1000px{
|
||||
@include media-1000px {
|
||||
.controlBar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 1fr);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<ul class="dropdown-menu dromdown-menu-start">
|
||||
<li><a href="v_board.php" :class="`dropdown-item ${myLevel >= 1 ? '' : 'disabled'}`">회의실</a></li>
|
||||
<li>
|
||||
<a href="v_board.php?isSecret=true" :class="`dropdown-item ${permission >= 2 ? '' : 'disabled'} `">기밀실</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="v_troop.php" :class="`dropdown-item ${myLevel >= 1 && nationLevel >= 1 ? '' : 'disabled'} `">부대 편성</a>
|
||||
</li>
|
||||
<li><a href="t_diplomacy.php" :class="`dropdown-item ${showSecret ? '' : 'disabled'} `">외교부</a></li>
|
||||
<li><a href="b_myBossInfo.php" :class="`dropdown-item ${myLevel >= 1 ? '' : 'disabled'} `">인사부</a></li>
|
||||
<li><a href="v_nationStratFinan.php" :class="`dropdown-item ${showSecret ? '' : 'disabled'} `">내무부</a></li>
|
||||
<li><a href="v_chiefCenter.php" :class="`dropdown-item ${showSecret ? '' : 'disabled'} `">사령부</a></li>
|
||||
<li><a href="v_NPCControl.php" :class="`dropdown-item ${showSecret ? '' : 'disabled'} `">NPC 정책</a></li>
|
||||
<li>
|
||||
<a href="b_genList.php" target="_blank" :class="`dropdown-item open-window ${showSecret ? '' : 'disabled'}`"
|
||||
>암행부</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="b_tournament.php" class="dropdown-item" target="_blank">토너먼트</a></li>
|
||||
<li><a href="b_myKingdomInfo.php" :class="`dropdown-item ${myLevel >= 1 ? '' : 'disabled'}`">세력 정보</a></li>
|
||||
<li>
|
||||
<a href="b_myCityInfo.php" :class="`dropdown-item ${myLevel >= 1 && nationLevel >= 1 ? '' : 'disabled'}`"
|
||||
>세력도시</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="v_nationGeneral.php" :class="`dropdown-item ${myLevel >= 1 ? '' : 'disabled'}`">세력 장수</a></li>
|
||||
<li><a href="v_globalDiplomacy.php" class="dropdown-item">중원 정보</a></li>
|
||||
<li><a href="b_currentCity.php" class="dropdown-item">현재 도시</a></li>
|
||||
<li>
|
||||
<a href="v_battleCenter.php" target="_blank" :class="`dropdown-item open-window ${showSecret ? '' : 'disabled'}`"
|
||||
>감찰부</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="v_inheritPoint.php" class="dropdown-item">유산 관리</a></li>
|
||||
<li><a href="b_myPage.php" class="dropdown-item">내 정보&설정</a></li>
|
||||
<li style="orphans: 2">
|
||||
<a href="v_auction.php" target="_blank" class="dropdown-item open-window">금/쌀 경매장</a>
|
||||
</li>
|
||||
<li><a href="v_auction.php?type=unique" target="_blank" class="dropdown-item open-window">유니크 경매장</a></li>
|
||||
<li><a href="b_betting.php" class="dropdown-item" target="_blank">베팅장</a></li>
|
||||
</ul>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, toRefs } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
showSecret: boolean;
|
||||
permission: number;
|
||||
myLevel: number;
|
||||
nationLevel: number;
|
||||
columns?: number;
|
||||
}>();
|
||||
|
||||
const columns = computed(() => {
|
||||
return props.columns ?? 4;
|
||||
});
|
||||
const { showSecret, permission, myLevel, nationLevel } = toRefs(props);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.subItem {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
columns: v-bind(columns);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user