wip
This commit is contained in:
@@ -46,10 +46,11 @@ class GeneralList extends \sammo\BaseAPI
|
||||
'connect' => 0,
|
||||
|
||||
'troop' => 0,
|
||||
'city' => 0,
|
||||
|
||||
'con' => 1,
|
||||
'specage' => 1,
|
||||
'specage2' => 1,
|
||||
'specage' => 0,
|
||||
'specage2' => 0,
|
||||
'leadership_exp' => 1,
|
||||
'strength_exp' => 1,
|
||||
'intel_exp' => 1,
|
||||
@@ -59,7 +60,6 @@ class GeneralList extends \sammo\BaseAPI
|
||||
'dex4' => 1,
|
||||
'dex5' => 1,
|
||||
|
||||
'city' => 1,
|
||||
'experience' => 1,
|
||||
'dedication' => 1,
|
||||
|
||||
@@ -315,6 +315,7 @@ class GeneralList extends \sammo\BaseAPI
|
||||
'list' => $generalList,
|
||||
'troops' => array_values($troops),
|
||||
'env' => $env,
|
||||
'myGeneralID' => $session->generalID,
|
||||
];
|
||||
|
||||
return $result;
|
||||
|
||||
+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>
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div class="general-card-basic bg2">
|
||||
<div class="general-icon" :style="{
|
||||
backgroundImage: `url(${iconPath})`,
|
||||
}"></div>
|
||||
|
||||
<div class="general-name" :style="{
|
||||
color: isBrightColor(nation.color) ? '#000' : '#fff',
|
||||
backgroundColor: nation.color,
|
||||
}">
|
||||
{{ general.name }} 【{{ general.officerLevelText }} | {{ generalTypeCall }} |
|
||||
<span :style="{ color: injuryInfo.color }">{{ injuryInfo.text }}</span>
|
||||
】
|
||||
</div>
|
||||
|
||||
<div class="bg1">통솔</div>
|
||||
<div>
|
||||
<div class="row gx-0">
|
||||
<div class="col">
|
||||
<span :style="{ color: injuryInfo.color }">{{ general.leadership }}</span>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg1">무력</div>
|
||||
<div>
|
||||
<div class="row gx-0">
|
||||
<div class="col" :style="{ color: injuryInfo.color }">
|
||||
{{ general.strength }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg1">지력</div>
|
||||
<div>
|
||||
<div class="row gx-0">
|
||||
<div class="col" :style="{ color: injuryInfo.color }">
|
||||
{{ general.intel }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg1">자금</div>
|
||||
<div>{{ general.gold.toLocaleString() }}</div>
|
||||
<div class="bg1">군량</div>
|
||||
<div>{{ general.rice.toLocaleString() }}</div>
|
||||
<div class="bg1">성격</div>
|
||||
<div v-b-tooltip.hover :title="personal.info ?? undefined">{{ personal.name }}</div>
|
||||
|
||||
<div class="bg1">특기</div>
|
||||
<div>
|
||||
<span v-b-tooltip.hover :title="specialDomestic.info ?? undefined"> {{ specialDomestic.name }}</span> /
|
||||
<span v-b-tooltip.hover :title="specialWar.info ?? undefined"> {{ specialWar.name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="bg1">Lv</div>
|
||||
<div class="general-exp-level">
|
||||
{{ general.explevel }}
|
||||
</div>
|
||||
|
||||
<div class="bg1">연령</div>
|
||||
<div :style="{ color: ageColor }">{{ general.age }}세</div>
|
||||
|
||||
<div class="bg1">삭턴</div>
|
||||
<div>{{ general.killturn }} 턴</div>
|
||||
|
||||
<div class="bg1">벌점</div>
|
||||
<div class="general-connect-score">
|
||||
{{ formatConnectScore(general.connect) }} {{ general.connect.toLocaleString() }}점
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { GeneralListItemP0 } from "@/defs/API/Nation";
|
||||
import { computed, inject, toRefs, type Ref } from "vue";
|
||||
import { getIconPath } from "@/util/getIconPath";
|
||||
import { isBrightColor } from "@/util/isBrightColor";
|
||||
import { formatInjury } from "@/utilGame/formatInjury";
|
||||
import type { NationStaticItem } from "@/defs";
|
||||
import { unwrap } from "@/util/unwrap";
|
||||
import type { GameConstStore } from "@/GameConstStore";
|
||||
import { formatGeneralTypeCall } from "@/utilGame/formatGeneralTypeCall";
|
||||
import { formatConnectScore } from "@/utilGame/formatConnectScore";
|
||||
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
||||
const props = defineProps<{
|
||||
general: GeneralListItemP0;
|
||||
nation: NationStaticItem;
|
||||
}>();
|
||||
|
||||
const { general, nation } = toRefs(props);
|
||||
const iconPath = computed(() => getIconPath(general.value.imgsvr, general.value.picture));
|
||||
const injuryInfo = computed(() => {
|
||||
const [text, color] = formatInjury(general.value.injury);
|
||||
return {
|
||||
text,
|
||||
color,
|
||||
};
|
||||
});
|
||||
const generalTypeCall = computed(() =>
|
||||
formatGeneralTypeCall(
|
||||
general.value.leadership,
|
||||
general.value.strength,
|
||||
general.value.intel,
|
||||
gameConstStore.value.gameConst
|
||||
)
|
||||
);
|
||||
|
||||
const personal = computed(
|
||||
() => gameConstStore.value.iActionInfo.personality[general.value.personal] ?? { value: "None", name: "-" }
|
||||
);
|
||||
const specialDomestic = computed(
|
||||
() =>
|
||||
gameConstStore.value.iActionInfo.specialDomestic[general.value.specialDomestic] ?? {
|
||||
value: "None",
|
||||
name: `-`,
|
||||
}
|
||||
);
|
||||
const specialWar = computed(
|
||||
() =>
|
||||
gameConstStore.value.iActionInfo.specialWar[general.value.specialWar] ?? {
|
||||
value: "None",
|
||||
name: `-`,
|
||||
}
|
||||
);
|
||||
|
||||
const ageColor = computed(() => {
|
||||
const age = general.value.age;
|
||||
const retirementYear = gameConstStore.value.gameConst.retirementYear;
|
||||
if (age < retirementYear * 0.75) {
|
||||
return "limegreen";
|
||||
}
|
||||
if (age < retirementYear) {
|
||||
return "yellow";
|
||||
}
|
||||
return "red";
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.general-card-basic {
|
||||
display: grid;
|
||||
grid-template-columns: 64px repeat(3, 2fr 5fr);
|
||||
grid-template-rows: repeat(9, calc(64px / 3));
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
|
||||
border-bottom: 1px solid gray;
|
||||
border-right: 1px solid gray;
|
||||
|
||||
>div.bg1,
|
||||
>.general-crew-type-icon,
|
||||
>.general-icon {
|
||||
border-left: 1px solid gray;
|
||||
}
|
||||
|
||||
>div {
|
||||
border-top: 1px solid gray;
|
||||
}
|
||||
}
|
||||
|
||||
.general-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
grid-row: 1 / 4;
|
||||
}
|
||||
|
||||
.general-name {
|
||||
grid-row: 1 / 2;
|
||||
grid-column: 2 / 8;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.general-connect-score {
|
||||
grid-column: 5 / 8;
|
||||
}
|
||||
</style>
|
||||
@@ -38,24 +38,24 @@
|
||||
<div class="bg1">피살</div>
|
||||
<div>{{ general.deathcrew.toLocaleString() }}</div>
|
||||
</div>
|
||||
<div :class="[props.showCommandList ? 'col-7' : 'col', 'general-card-dex']">
|
||||
<div :class="[(props.showCommandList && general.reservedCommand) ? 'col-8' : 'col', 'general-card-dex']">
|
||||
<div class="part-title bg1">숙련도</div>
|
||||
<template v-for="[dexType, dex, dexInfo] of dexList" :key="dexType">
|
||||
<div class="bg1">{{ dexType }}</div>
|
||||
<div :style="{ color: dexInfo.color }">{{ dexInfo.name }}</div>
|
||||
<div>{{ (dex / 1000).toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) }}K</div>
|
||||
<div class="d-grid">
|
||||
<div class="align-self-center"><SammoBar :height="10" :percent="dex / 1_000_000 * 100" /></div>
|
||||
<div class="align-self-center"><SammoBar :height="10" :percent="(dex / 1_000_000) * 100" /></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
v-if="props.showCommandList && general.reservedCommand && general.reservedCommand.length > 0"
|
||||
class="col-5 general-card-turn"
|
||||
class="col-4 general-card-turn"
|
||||
>
|
||||
<div class="part-title">예약턴</div>
|
||||
<div v-for="(turn, idx) in general.reservedCommand.slice(0, 5)" :key="idx">
|
||||
{{ turn.brief }}
|
||||
<div class="part-title bg1">예약턴</div>
|
||||
<div v-for="(turn, idx) in general.reservedCommand.slice(0, 5)" :key="idx" class="command">
|
||||
<span>{{ turn.brief }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -161,12 +161,16 @@ const dexList = computed((): [string, number, DexInfo][] => {
|
||||
}
|
||||
|
||||
.general-card-turn {
|
||||
.bg1 {
|
||||
border-left: solid 1px gray;
|
||||
> div {
|
||||
height: calc(64px / 3);
|
||||
border-bottom: solid 1px gray;
|
||||
border-right: solid 1px gray;
|
||||
}
|
||||
|
||||
> div {
|
||||
border-bottom: solid 1px gray;
|
||||
> .command{
|
||||
font-size: 90%;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+112
-107
@@ -7,79 +7,79 @@ export type SetBlockWarResponse = ValidResponse & {
|
||||
};
|
||||
|
||||
export type GeneralListItemP0 = {
|
||||
no: number,
|
||||
name: string,
|
||||
nation: number,
|
||||
npc: number,
|
||||
injury: number,
|
||||
leadership: number,
|
||||
strength: number,
|
||||
intel: number,
|
||||
explevel: number,
|
||||
dedlevel: number,
|
||||
gold: number,
|
||||
rice: number,
|
||||
killturn: number,
|
||||
picture: string,
|
||||
imgsvr: 0 | 1,
|
||||
age: number,
|
||||
specialDomestic: GameObjClassKey,
|
||||
specialWar: GameObjClassKey,
|
||||
personal: GameObjClassKey,
|
||||
belong: number,
|
||||
connect: number,
|
||||
no: number;
|
||||
name: string;
|
||||
nation: number;
|
||||
npc: number;
|
||||
injury: number;
|
||||
leadership: number;
|
||||
strength: number;
|
||||
intel: number;
|
||||
explevel: number;
|
||||
dedlevel: number;
|
||||
gold: number;
|
||||
rice: number;
|
||||
killturn: number;
|
||||
picture: string;
|
||||
imgsvr: 0 | 1;
|
||||
age: number;
|
||||
specialDomestic: GameObjClassKey;
|
||||
specialWar: GameObjClassKey;
|
||||
personal: GameObjClassKey;
|
||||
belong: number;
|
||||
connect: number;
|
||||
|
||||
officerLevel: number, //권한에따라 태수,군사,시종 노출 여부가 다름
|
||||
officerLevelText: string,
|
||||
lbonus: number,
|
||||
ownerName: string | null, //NPC 출력용에 따라 결과가 다름
|
||||
honorText: string,
|
||||
dedLevelText: string,
|
||||
bill: number,
|
||||
reservedCommand: TurnObj[] | null,
|
||||
officerLevel: number; //권한에따라 태수,군사,시종 노출 여부가 다름
|
||||
officerLevelText: string;
|
||||
lbonus: number;
|
||||
ownerName: string | null; //NPC 출력용에 따라 결과가 다름
|
||||
honorText: string;
|
||||
dedLevelText: string;
|
||||
bill: number;
|
||||
reservedCommand: TurnObj[] | null;
|
||||
|
||||
autorun_limit: number,
|
||||
autorun_limit: number;
|
||||
|
||||
troop: number,
|
||||
}
|
||||
city: number;
|
||||
troop: number;
|
||||
};
|
||||
|
||||
export type GeneralListItemP1 = {
|
||||
con: number,
|
||||
specage: number,
|
||||
specage2: number,
|
||||
leadership_exp: number,
|
||||
strength_exp: number,
|
||||
intel_exp: number,
|
||||
con: number;
|
||||
specage: number;
|
||||
specage2: number;
|
||||
leadership_exp: number;
|
||||
strength_exp: number;
|
||||
intel_exp: number;
|
||||
|
||||
dex1: number,
|
||||
dex2: number,
|
||||
dex3: number,
|
||||
dex4: number,
|
||||
dex5: number,
|
||||
dex1: number;
|
||||
dex2: number;
|
||||
dex3: number;
|
||||
dex4: number;
|
||||
dex5: number;
|
||||
|
||||
city: number,
|
||||
experience: number,
|
||||
dedication: number,
|
||||
officer_level: number,
|
||||
officer_city: number,
|
||||
defence_train: number,
|
||||
crewtype: GameObjClassKey,
|
||||
crew: number,
|
||||
train: number,
|
||||
atmos: number,
|
||||
turntime: string,
|
||||
recent_war: string,
|
||||
horse: GameObjClassKey,
|
||||
weapon: GameObjClassKey,
|
||||
book: GameObjClassKey,
|
||||
item: GameObjClassKey,
|
||||
experience: number;
|
||||
dedication: number;
|
||||
officer_level: number;
|
||||
officer_city: number;
|
||||
defence_train: number;
|
||||
crewtype: GameObjClassKey;
|
||||
crew: number;
|
||||
train: number;
|
||||
atmos: number;
|
||||
turntime: string;
|
||||
recent_war: string;
|
||||
horse: GameObjClassKey;
|
||||
weapon: GameObjClassKey;
|
||||
book: GameObjClassKey;
|
||||
item: GameObjClassKey;
|
||||
|
||||
warnum: number,
|
||||
killnum: number,
|
||||
deathnum: number,
|
||||
killcrew: number,
|
||||
deathcrew: number,
|
||||
firenum: number,
|
||||
warnum: number;
|
||||
killnum: number;
|
||||
deathnum: number;
|
||||
killcrew: number;
|
||||
deathcrew: number;
|
||||
firenum: number;
|
||||
} & GeneralListItemP0;
|
||||
|
||||
export type GeneralListItemP2 = GeneralListItemP1;
|
||||
@@ -87,45 +87,48 @@ export type GeneralListItemP2 = GeneralListItemP1;
|
||||
export type RawGeneralListItem = GeneralListItemP0 | GeneralListItemP1 | GeneralListItemP2;
|
||||
|
||||
export type GeneralListItem =
|
||||
(GeneralListItemP0 & { st0: true, st1: false, st2: false, permission: 0 }) |
|
||||
(GeneralListItemP1 & { st0: true, st1: true, st2: false, permission: 1 }) |
|
||||
(GeneralListItemP2 & { st0: true, st1: true, st2: true, permission: 2 | 3 | 4 });
|
||||
| (GeneralListItemP0 & { st0: true; st1: false; st2: false; permission: 0 })
|
||||
| (GeneralListItemP1 & { st0: true; st1: true; st2: false; permission: 1 })
|
||||
| (GeneralListItemP2 & { st0: true; st1: true; st2: true; permission: 2 | 3 | 4 });
|
||||
|
||||
type ResponseEnv = {
|
||||
year: number,
|
||||
month: number,
|
||||
turntime: string,
|
||||
turnterm: number,
|
||||
killturn: number,
|
||||
year: number;
|
||||
month: number;
|
||||
turntime: string;
|
||||
turnterm: number;
|
||||
killturn: number;
|
||||
autorun_user?: {
|
||||
limit_minutes: number,
|
||||
options: Record<string, number>,
|
||||
}
|
||||
}
|
||||
limit_minutes: number;
|
||||
options: Record<string, number>;
|
||||
};
|
||||
};
|
||||
|
||||
export type RawGeneralListP0 = ValidResponse & {
|
||||
permission: 0,
|
||||
column: (keyof GeneralListItemP0)[],
|
||||
list: ValuesOf<GeneralListItemP0>[][],
|
||||
troops: {id: number, name: string, turntime: string, reservedCommand: string[]}[],
|
||||
env: ResponseEnv,
|
||||
}
|
||||
type RawGeneralCommon = {
|
||||
troops: { id: number; name: string; turntime: string; reservedCommand: string[] }[];
|
||||
env: ResponseEnv;
|
||||
myGeneralID: number;
|
||||
};
|
||||
|
||||
export type RawGeneralListP1 = ValidResponse & {
|
||||
permission: 1,
|
||||
column: (keyof GeneralListItemP1)[],
|
||||
list: ValuesOf<GeneralListItemP1>[][],
|
||||
troops: {id: number, name: string, turntime: string, reservedCommand: string[]}[],
|
||||
env: ResponseEnv,
|
||||
}
|
||||
export type RawGeneralListP0 = ValidResponse &
|
||||
RawGeneralCommon & {
|
||||
permission: 0;
|
||||
column: (keyof GeneralListItemP0)[];
|
||||
list: ValuesOf<GeneralListItemP0>[][];
|
||||
};
|
||||
|
||||
export type RawGeneralListP2 = ValidResponse & {
|
||||
permission: 2 | 3 | 4,
|
||||
column: (keyof GeneralListItemP2)[],
|
||||
list: ValuesOf<GeneralListItemP2>[][],
|
||||
troops: {id: number, name: string, turntime: string, reservedCommand: string[]}[],
|
||||
env: ResponseEnv,
|
||||
}
|
||||
export type RawGeneralListP1 = ValidResponse &
|
||||
RawGeneralCommon & {
|
||||
permission: 1;
|
||||
column: (keyof GeneralListItemP1)[];
|
||||
list: ValuesOf<GeneralListItemP1>[][];
|
||||
};
|
||||
|
||||
export type RawGeneralListP2 = ValidResponse &
|
||||
RawGeneralCommon & {
|
||||
permission: 2 | 3 | 4;
|
||||
column: (keyof GeneralListItemP2)[];
|
||||
list: ValuesOf<GeneralListItemP2>[][];
|
||||
};
|
||||
|
||||
export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2;
|
||||
|
||||
@@ -141,16 +144,18 @@ export type NationItem = NationStaticItem & {
|
||||
strategic_cmd_limit: number;
|
||||
surlimit: number;
|
||||
tech: number;
|
||||
}
|
||||
};
|
||||
|
||||
export type LiteNationInfoResponse = ValidResponse & {
|
||||
nation: NationStaticItem;
|
||||
}
|
||||
};
|
||||
|
||||
export type NationInfoResponse = (ValidResponse & {
|
||||
nation: NationStaticItem;
|
||||
}) | (ValidResponse &{
|
||||
nation: NationItem;
|
||||
impossibleStrategicCommandLists: [string, number][];
|
||||
troops: Record<number, string>;
|
||||
})
|
||||
export type NationInfoResponse =
|
||||
| (ValidResponse & {
|
||||
nation: NationStaticItem;
|
||||
})
|
||||
| (ValidResponse & {
|
||||
nation: NationItem;
|
||||
impossibleStrategicCommandLists: [string, number][];
|
||||
troops: Record<number, string>;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user