wip
This commit is contained in:
+301
-35
@@ -1,72 +1,213 @@
|
||||
<template>
|
||||
<div id="container">
|
||||
<div id="container" ref="container">
|
||||
<TopBackBar :reloadable="true" title="부대 편성" @reload="refresh" />
|
||||
<div v-for="[troopID, troop] of troopList" :key="troopID">
|
||||
{{ troop.troopName }} {{ troop.turnTime }}
|
||||
<span v-for="member of troop.members" :key="member.no">
|
||||
{{ member.name }}
|
||||
</span>
|
||||
<div v-if="asyncReady && gameConstStore && me" id="troopList" class="bg0">
|
||||
<div v-for="[troopID, troop] of troopList" :key="troopID" class="troopItem">
|
||||
<div class="troopInfo">
|
||||
{{ troop.troopName }}<br />
|
||||
【 {{ gameConstStore.cityConst[troop.troopLeader.city].name }} 】
|
||||
</div>
|
||||
<div class="troopTurn">【턴】 {{ troop.turnTime.slice(14, 19) }}</div>
|
||||
<div class="troopLeaderIcon">
|
||||
<img height="64" width="64" :src="getIconPath(troop.troopLeader.imgsvr, troop.troopLeader.picture)" />
|
||||
</div>
|
||||
<div class="troopLeaderName">
|
||||
{{ troop.troopLeader.name }}
|
||||
</div>
|
||||
<div class="troopMembers">
|
||||
<template v-for="(member, idx) in troop.members" :key="member.no">
|
||||
<template v-if="idx != 0">, </template>
|
||||
<span
|
||||
v-if="member.troop == member.no"
|
||||
class="troopMember troopLeader"
|
||||
@mouseover="setPopup($event, member)"
|
||||
@mouseout="setPopup($event, undefined)"
|
||||
>
|
||||
{{ member.name }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="troopMember"
|
||||
@mouseover="setPopup($event, member)"
|
||||
@mouseout="setPopup($event, undefined)"
|
||||
>
|
||||
{{ member.name }}
|
||||
</span>
|
||||
</template>
|
||||
({{ troop.members.length }}명)
|
||||
</div>
|
||||
<div class="troopReservedCommand">
|
||||
<div v-for="(brief, idx) in troop.reservedCommandBrief" :key="idx">
|
||||
{{ `${idx + 1}: ${brief}` }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="troopAction">
|
||||
<BButton v-if="!me.troop">부대 탑승</BButton>
|
||||
<BButton v-if="me.troop == troop.troopID">부대 탈퇴</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BottomBar />
|
||||
<div
|
||||
v-if="asyncReady && gameConstStore"
|
||||
id="generalPopup"
|
||||
:style="{ display: popupGeneralTarget ? 'block' : 'none', top: `${popupTop}px` }"
|
||||
>
|
||||
<div v-if="!popupGeneralTarget || !nationInfo"></div>
|
||||
<template v-else-if="popupGeneralTarget.st1">
|
||||
<GeneralBasicCard
|
||||
:general="popupGeneralTarget"
|
||||
:troopInfo="convBasicCardTroopInfo(popupGeneralTarget)"
|
||||
:nation="nationInfo"
|
||||
/>
|
||||
<GeneralSupplementCard :general="popupGeneralTarget" :showCommandList="true" />
|
||||
</template>
|
||||
|
||||
<GeneralLiteCard v-else :general="popupGeneralTarget" :nation="nationInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopBackBar from "@/components/TopBackBar.vue";
|
||||
import BottomBar from "@/components/BottomBar.vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, provide, ref, toRef } from "vue";
|
||||
import { SammoAPI } from "./SammoAPI";
|
||||
import { useToast } from "bootstrap-vue-3";
|
||||
import { BButton, useToast } from "bootstrap-vue-3";
|
||||
import { unwrap } from "./util/unwrap";
|
||||
import { isString } from "lodash";
|
||||
import type { GeneralListItem } from "./defs/API/Nation";
|
||||
import type { GeneralListItem, GeneralListItemP1 } from "./defs/API/Nation";
|
||||
import { merge2DArrToObjectArr } from "./util/merge2DArrToObjectArr";
|
||||
import { convertIterableToMap } from '@/util/convertIterableToMap';
|
||||
import { convertIterableToMap } from "@/util/convertIterableToMap";
|
||||
import { GameConstStore, getGameConstStore } from "./GameConstStore";
|
||||
import { getIconPath } from "@/util/getIconPath";
|
||||
import GeneralBasicCard from "./components/GeneralBasicCard.vue";
|
||||
import type { NationStaticItem } from "./defs";
|
||||
import GeneralLiteCard from "./components/GeneralLiteCard.vue";
|
||||
import GeneralSupplementCard from "./components/GeneralSupplementCard.vue";
|
||||
const toasts = unwrap(useToast());
|
||||
|
||||
type TroopInfo = {
|
||||
troopID: number,
|
||||
troopName: string,
|
||||
troopLeader: GeneralListItem,
|
||||
turnTime: string,
|
||||
members: GeneralListItem[],
|
||||
const asyncReady = ref(false);
|
||||
const gameConstStore = ref<GameConstStore>();
|
||||
provide("gameConstStore", gameConstStore);
|
||||
const storeP = getGameConstStore().then((store) => {
|
||||
gameConstStore.value = store;
|
||||
});
|
||||
|
||||
void Promise.all([storeP]).then(() => {
|
||||
asyncReady.value = true;
|
||||
});
|
||||
|
||||
const container = ref<HTMLElement>();
|
||||
|
||||
const popupGeneralTarget = ref<GeneralListItem>();
|
||||
const popupTop = ref<number>(0);
|
||||
|
||||
function convBasicCardTroopInfo(general: GeneralListItemP1): { leader: GeneralListItemP1; name: string } | undefined {
|
||||
const troop = troopList.value.get(general.troop);
|
||||
if (!troop) {
|
||||
return undefined;
|
||||
}
|
||||
const troopLeader = troop.troopLeader;
|
||||
if (!troopLeader.st1) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
leader: troopLeader,
|
||||
name: troop.troopName,
|
||||
};
|
||||
}
|
||||
|
||||
function setPopup(e: MouseEvent, general: GeneralListItem | undefined) {
|
||||
if (general === undefined || !e.target) {
|
||||
popupTop.value = 0;
|
||||
popupGeneralTarget.value = undefined;
|
||||
return;
|
||||
}
|
||||
console.log("e", e);
|
||||
|
||||
const target = e.target as HTMLElement;
|
||||
popupGeneralTarget.value = general;
|
||||
let parent = target.parentElement;
|
||||
console.log("parent", parent);
|
||||
while (parent !== null && !parent.classList.contains("troopMembers")) {
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
|
||||
if (parent === null) {
|
||||
popupTop.value = 0;
|
||||
popupGeneralTarget.value = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(parent.offsetTop, parent.offsetHeight, parent);
|
||||
|
||||
popupTop.value = parent.offsetTop + parent.offsetHeight;
|
||||
}
|
||||
|
||||
type TroopInfo = {
|
||||
troopID: number;
|
||||
troopName: string;
|
||||
troopLeader: GeneralListItem;
|
||||
turnTime: string;
|
||||
reservedCommandBrief: string[];
|
||||
members: GeneralListItem[];
|
||||
};
|
||||
|
||||
const me = ref<GeneralListItem>({} as GeneralListItem);
|
||||
|
||||
const troopList = ref(new Map<number, TroopInfo>());
|
||||
const generalList = ref(new Map<number, GeneralListItem>());
|
||||
const nationInfo = ref<NationStaticItem>();
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const { column, list, permission, troops, env } = await SammoAPI.Nation.GeneralList();
|
||||
const generalListP = SammoAPI.Nation.GeneralList();
|
||||
const nationP = SammoAPI.Nation.GetNationInfo({});
|
||||
nationInfo.value = (await nationP).nation;
|
||||
const { column, list, permission, troops, env, myGeneralID } = await generalListP;
|
||||
|
||||
//빠른 턴 순서로 정렬되어있다.
|
||||
|
||||
//XXX: 로직상 똑같은데....
|
||||
if (permission == 0) {
|
||||
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||
generalList.value = convertIterableToMap(rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: false, st2: false, ...v };
|
||||
}), 'no');
|
||||
generalList.value = convertIterableToMap(
|
||||
rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: false, st2: false, ...v };
|
||||
}),
|
||||
"no"
|
||||
);
|
||||
} else if (permission == 1) {
|
||||
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||
generalList.value = convertIterableToMap(rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: true, st2: false, ...v };
|
||||
}), 'no');
|
||||
generalList.value = convertIterableToMap(
|
||||
rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: true, st2: false, ...v };
|
||||
}),
|
||||
"no"
|
||||
);
|
||||
} else if ([2, 3, 4].includes(permission)) {
|
||||
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||
generalList.value = convertIterableToMap(rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: true, st2: true, ...v };
|
||||
}), 'no');
|
||||
generalList.value = convertIterableToMap(
|
||||
rawGeneralList.map((v) => {
|
||||
return { permission, st0: true, st1: true, st2: true, ...v };
|
||||
}),
|
||||
"no"
|
||||
);
|
||||
} else {
|
||||
throw `?? ${permission}`;
|
||||
}
|
||||
|
||||
me.value = unwrap(generalList.value.get(myGeneralID));
|
||||
|
||||
troopList.value = new Map();
|
||||
|
||||
for (const { id: troopLeaderID, name: troopName, turntime: troopTurntime } of troops) {
|
||||
for (const { id: troopLeaderID, name: troopName, turntime: troopTurntime, reservedCommand } of troops) {
|
||||
if (!generalList.value.has(troopLeaderID)) {
|
||||
toasts.warning({
|
||||
'title': '경고',
|
||||
'body': `${troopName} 부대장(${troopLeaderID})이 아국 소속이 아닌 것 같습니다.`
|
||||
title: "경고",
|
||||
body: `${troopName} 부대장(${troopLeaderID})이 아국 소속이 아닌 것 같습니다.`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -75,6 +216,7 @@ async function refresh() {
|
||||
troopName,
|
||||
troopLeader: unwrap(generalList.value.get(troopLeaderID)),
|
||||
turnTime: troopTurntime,
|
||||
reservedCommandBrief: reservedCommand,
|
||||
members: [],
|
||||
});
|
||||
}
|
||||
@@ -91,22 +233,146 @@ async function refresh() {
|
||||
}
|
||||
troop.members.push(general);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
if (isString(e)) {
|
||||
toasts.danger({
|
||||
title: '오류',
|
||||
body: e
|
||||
title: "오류",
|
||||
body: e,
|
||||
});
|
||||
}
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void refresh();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@scss/common/break_500px.scss";
|
||||
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#generalPopup {
|
||||
position: absolute;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.troopItem {
|
||||
display: grid;
|
||||
border-right: solid 1px gray;
|
||||
|
||||
> div {
|
||||
border-top: solid 1px gray;
|
||||
border-left: solid 1px gray;
|
||||
}
|
||||
|
||||
.troopInfo {
|
||||
grid-column: 1/2;
|
||||
grid-row: 1/2;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.troopTurn {
|
||||
grid-column: 1/2;
|
||||
grid-row: 2/3;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.troopLeaderIcon {
|
||||
grid-column: 2/3;
|
||||
grid-row: 1/2;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.troopLeaderName {
|
||||
grid-column: 2/3;
|
||||
grid-row: 2/3;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.troopReservedCommand {
|
||||
grid-column: 4/5;
|
||||
grid-row: 1/3;
|
||||
font-size: 85%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.troopAction {
|
||||
grid-column: 5/6;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
|
||||
.troopMembers {
|
||||
text-align: left;
|
||||
padding: 0.5em 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-1000px {
|
||||
#container {
|
||||
width: 1000px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#generalPopup {
|
||||
left: 260px;
|
||||
}
|
||||
|
||||
.troopItem {
|
||||
grid-template-rows: 65px 28px;
|
||||
grid-template-columns: 130px 130px 1fr 110px 130px;
|
||||
|
||||
.troopMembers {
|
||||
grid-column: 3/4;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: solid 1px gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-500px {
|
||||
#container {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#generalPopup {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.troopItem {
|
||||
grid-template-rows: 65px 28px auto;
|
||||
grid-template-columns: 130px 130px 0px 110px 130px;
|
||||
|
||||
.troopMembers {
|
||||
grid-column: 2/6;
|
||||
grid-row: 3/4;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
.troopMembers,
|
||||
.troopTurn {
|
||||
border-bottom: solid 1px gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user