refac: 감찰부 vue3 재 작성 (#222)
- 장수 정보, 추가 정보 vue3 component - b_battleCenter -> v_battleCenter Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/222
This commit was merged in pull request #222.
This commit is contained in:
@@ -254,6 +254,7 @@ function pushGeneralHistoryLog(int $generalID, ?array $history, $year=null, $mon
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
function getGeneralHistoryLogAll(int $generalID):array {
|
function getGeneralHistoryLogAll(int $generalID):array {
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
@@ -263,6 +264,15 @@ function getGeneralHistoryLogAll(int $generalID):array {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getGeneralHistoryLogWithLogID(int $generalID):array {
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
return Util::convertPairArrayToDict($db->queryAllLists(
|
||||||
|
'SELECT `id`, `text` from general_record WHERE general_id = %i AND log_type = "history" order by id desc',
|
||||||
|
$generalID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function pushNationHistoryLog(int $nationID, ?array $history, ?int $year=null, ?int $month=null) {
|
function pushNationHistoryLog(int $nationID, ?array $history, ?int $year=null, ?int $month=null) {
|
||||||
if(!$history){
|
if(!$history){
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ class GetGeneralLog extends GetNationGeneralLog
|
|||||||
$v = new Validator($this->args);
|
$v = new Validator($this->args);
|
||||||
$v
|
$v
|
||||||
->rule('required', [
|
->rule('required', [
|
||||||
'type',
|
'reqType',
|
||||||
])
|
])
|
||||||
->rule('int', [
|
->rule('int', [
|
||||||
'reqTo',
|
'reqTo',
|
||||||
])
|
])
|
||||||
->rule('in', 'type', [
|
->rule('in', 'reqType', [
|
||||||
self::GENERAL_HISTORY,
|
self::GENERAL_HISTORY,
|
||||||
self::GENERAL_ACTION,
|
self::GENERAL_ACTION,
|
||||||
self::BATTLE_RESULT,
|
self::BATTLE_RESULT,
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ use sammo\Validator;
|
|||||||
use function sammo\checkLimit;
|
use function sammo\checkLimit;
|
||||||
use function sammo\checkSecretPermission;
|
use function sammo\checkSecretPermission;
|
||||||
use function sammo\getBattleDetailLogMore;
|
use function sammo\getBattleDetailLogMore;
|
||||||
|
use function sammo\getBattleDetailLogRecent;
|
||||||
use function sammo\getBattleResultMore;
|
use function sammo\getBattleResultMore;
|
||||||
use function sammo\getBattleResultRecent;
|
use function sammo\getBattleResultRecent;
|
||||||
use function sammo\getGeneralActionLogMore;
|
use function sammo\getGeneralActionLogMore;
|
||||||
use function sammo\getGeneralActionLogRecent;
|
use function sammo\getGeneralActionLogRecent;
|
||||||
use function sammo\getGeneralHistoryLogAll;
|
use function sammo\getGeneralHistoryLogWithLogID;
|
||||||
|
|
||||||
class GetGeneralLog extends \sammo\BaseAPI
|
class GetGeneralLog extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
@@ -28,13 +29,13 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
$v
|
$v
|
||||||
->rule('required', [
|
->rule('required', [
|
||||||
'generalID',
|
'generalID',
|
||||||
'type',
|
'reqType',
|
||||||
])
|
])
|
||||||
->rule('integer', [
|
->rule('integer', [
|
||||||
'generalID',
|
'generalID',
|
||||||
'reqTo',
|
'reqTo',
|
||||||
])
|
])
|
||||||
->rule('in', 'type', [
|
->rule('in', 'reqType', [
|
||||||
self::GENERAL_HISTORY,
|
self::GENERAL_HISTORY,
|
||||||
self::GENERAL_ACTION,
|
self::GENERAL_ACTION,
|
||||||
self::BATTLE_RESULT,
|
self::BATTLE_RESULT,
|
||||||
@@ -76,7 +77,7 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
return '같은 나라의 장수가 아닙니다.';
|
return '같은 나라의 장수가 아닙니다.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$reqType = $this->args['type'];
|
$reqType = $this->args['reqType'];
|
||||||
if (
|
if (
|
||||||
$reqType === self::GENERAL_ACTION &&
|
$reqType === self::GENERAL_ACTION &&
|
||||||
$testGeneralNPCType < 2 &&
|
$testGeneralNPCType < 2 &&
|
||||||
@@ -103,7 +104,7 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
$userID = $session->userID;
|
$userID = $session->userID;
|
||||||
|
|
||||||
$targetGeneralID = $this->getTargetGeneralID($session);
|
$targetGeneralID = $this->getTargetGeneralID($session);
|
||||||
$reqType = $this->args['type'];
|
$reqType = $this->args['reqType'];
|
||||||
$reqTo = $this->args['reqTo'] ?? null;
|
$reqTo = $this->args['reqTo'] ?? null;
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
@@ -124,7 +125,7 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
'result' => true,
|
'result' => true,
|
||||||
'reqType' => $reqType,
|
'reqType' => $reqType,
|
||||||
'generalID' => $targetGeneralID,
|
'generalID' => $targetGeneralID,
|
||||||
'log' => getGeneralHistoryLogAll($targetGeneralID)
|
'log' => getGeneralHistoryLogWithLogID($targetGeneralID)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@ class GetGeneralLog extends \sammo\BaseAPI
|
|||||||
'reqType' => $reqType,
|
'reqType' => $reqType,
|
||||||
'generalID' => $targetGeneralID,
|
'generalID' => $targetGeneralID,
|
||||||
'log' => $reqTo === null
|
'log' => $reqTo === null
|
||||||
? getBattleResultRecent($targetGeneralID, 30)
|
? getBattleDetailLogRecent($targetGeneralID, 30)
|
||||||
: getBattleDetailLogMore($targetGeneralID, $reqTo, 30)
|
: getBattleDetailLogMore($targetGeneralID, $reqTo, 30)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Nation;
|
||||||
|
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\GameConst;
|
||||||
|
use sammo\General;
|
||||||
|
use sammo\KVStorage;
|
||||||
|
use sammo\LastTurn;
|
||||||
|
use sammo\Session;
|
||||||
|
use sammo\Util;
|
||||||
|
use sammo\Validator;
|
||||||
|
|
||||||
|
use function sammo\buildNationCommandClass;
|
||||||
|
use function sammo\checkLimit;
|
||||||
|
use function sammo\checkSecretPermission;
|
||||||
|
use function sammo\getBattleDetailLogMore;
|
||||||
|
use function sammo\getBattleResultMore;
|
||||||
|
use function sammo\getBattleResultRecent;
|
||||||
|
use function sammo\getGeneralActionLogMore;
|
||||||
|
use function sammo\getGeneralActionLogRecent;
|
||||||
|
use function sammo\getGeneralHistoryLogAll;
|
||||||
|
use function sammo\getNationStaticInfo;
|
||||||
|
|
||||||
|
class GetNationInfo extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v->rule('boolean', 'full');
|
||||||
|
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$userID = $session->userID;
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$nationID = $db->queryFirstField('SELECT nation FROM general WHERE `owner` = %i', $userID);
|
||||||
|
|
||||||
|
if (!$nationID) {
|
||||||
|
return [
|
||||||
|
'result' => true,
|
||||||
|
'nation' => getNationStaticInfo(0)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$isFull = $this->args['full'] ?? false;
|
||||||
|
|
||||||
|
if(!$isFull){
|
||||||
|
$nation = getNationStaticInfo($nationID);
|
||||||
|
return [
|
||||||
|
'result' => true,
|
||||||
|
'nation' => $nation,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$generalObj = General::createGeneralObjFromDB($session->generalID, null, 1);
|
||||||
|
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$gameEnv = $gameStor->getValues(['year', 'month', 'startyear']);
|
||||||
|
|
||||||
|
$nation = $db->queryFirstRow(
|
||||||
|
'SELECT nation, `name`, color, capital, gennum, gold, rice, bill, rate, secretlimit, chief_set, scout, war, strategic_cmd_limit, surlimit, tech, `power`, `level`, `type` FROM nation WHERE id = %i',
|
||||||
|
$nationID
|
||||||
|
);
|
||||||
|
$nationStor = \sammo\KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||||
|
$nationStor->cacheAll();
|
||||||
|
|
||||||
|
|
||||||
|
//전략 정보를 매번 읽어와야하나?
|
||||||
|
$impossibleStrategicCommandLists = [];
|
||||||
|
$strategicCommandLists = GameConst::$availableChiefCommand['전략'];
|
||||||
|
$yearMonth = Util::joinYearMonth($gameEnv['year'], $gameEnv['month']);
|
||||||
|
foreach ($strategicCommandLists as $command) {
|
||||||
|
$cmd = buildNationCommandClass($command, $generalObj, $gameEnv, new LastTurn());
|
||||||
|
$nextAvailableTurn = $cmd->getNextAvailableTurn();
|
||||||
|
if ($nextAvailableTurn > $yearMonth) {
|
||||||
|
$impossibleStrategicCommandLists[] = [$cmd->getName(), $nextAvailableTurn - $yearMonth];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$troopName = [];
|
||||||
|
foreach ($db->queryAllLists('SELECT troop_leader, name FROM troop WHERE nation=%i', $nationID) as [$troopID, $tName]) {
|
||||||
|
$troopName[$troopID] = $tName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'result' => true,
|
||||||
|
'nation' => $nation,
|
||||||
|
'impossibleStrategicCommandLists' => $impossibleStrategicCommandLists,
|
||||||
|
'troops' => $troopName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
.small_war_log {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .war_type_attack {
|
||||||
|
color: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .war_type_defense {
|
||||||
|
color: magenta;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .war_type_siege {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .name_plate {
|
||||||
|
font-size: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .name_plate_cover {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small_war_log .crew_plate {
|
||||||
|
color: orangered;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden_but_copyable {
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<?=$btnBegin??''?><a href='v_nationGeneral.php' class='commandButton <?=$btnClass??""?> <?= $meLevel >= 1 ? '' : 'disabled' ?>'>세력 장수</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='v_nationGeneral.php' class='commandButton <?=$btnClass??""?> <?= $meLevel >= 1 ? '' : 'disabled' ?>'>세력 장수</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='v_globalDiplomacy.php' class='commandButton <?=$btnClass??""?>'>중원 정보</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='v_globalDiplomacy.php' class='commandButton <?=$btnClass??""?>'>중원 정보</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_currentCity.php' class='commandButton <?=$btnClass??""?>'>현재 도시</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_currentCity.php' class='commandButton <?=$btnClass??""?>'>현재 도시</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_battleCenter.php' target='_blank' class='open-window commandButton <?=$btnClass??""?> <?= $showSecret ? '' : 'disabled' ?>'>감 찰 부</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='v_battleCenter.php' target='_blank' class='open-window commandButton <?=$btnClass??""?> <?= $showSecret ? '' : 'disabled' ?>'>감 찰 부</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='v_inheritPoint.php' class='commandButton <?=$btnClass??""?>'>유산 관리</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='v_inheritPoint.php' class='commandButton <?=$btnClass??""?>'>유산 관리</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_myPage.php' class='commandButton <?=$btnClass??""?>'>내 정보&설정</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_myPage.php' class='commandButton <?=$btnClass??""?>'>내 정보&설정</a><?=$btnEnd??''?>
|
||||||
<?=$splitBtnBegin??''?>
|
<?=$splitBtnBegin??''?>
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<BContainer v-if="asyncReady" id="container" :toast="{ root: true }">
|
||||||
|
<TopBackBar title="감찰부" :reloadable="true" type="close" @reload="reload" />
|
||||||
|
|
||||||
|
<div class="row gx-0">
|
||||||
|
<div class="col-4">
|
||||||
|
<BFormSelect v-model="orderBy">
|
||||||
|
<BFormSelectOption
|
||||||
|
v-for="[orderKey, [orderName]] of Object.entries(textMap)"
|
||||||
|
:key="orderKey"
|
||||||
|
:value="orderKey"
|
||||||
|
>
|
||||||
|
{{ orderName }}
|
||||||
|
</BFormSelectOption>
|
||||||
|
</BFormSelect>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<BFormSelect v-model="targetGeneralID">
|
||||||
|
<BFormSelectOption v-for="general of orderedGeneralList" :key="general.no" :value="general.no">
|
||||||
|
<span
|
||||||
|
:style="{
|
||||||
|
color: getNpcColor(general.npc),
|
||||||
|
}"
|
||||||
|
>{{ general.officerLevel > 5 ? `*${general.name}*` : general.name }}({{ general.turntime.slice(-5) }}){{
|
||||||
|
textMap[orderBy][3](general)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</BFormSelectOption>
|
||||||
|
</BFormSelect>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="targetGeneral && nationInfo && targetGeneralLogs" class="row gx-0 bg0">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="bg1 header-cell" style="color: skyblue">장수 정보</div>
|
||||||
|
<GeneralBasicCard :general="targetGeneral" :nation="nationInfo" />
|
||||||
|
<GeneralSupplementCard :general="targetGeneral" />
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="bg1 header-cell">장수 열전</div>
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<div v-for="[id, log] of targetGeneralLogs.generalHistory" :key="id" v-html="log" />
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="bg1 header-cell">전투 기록</div>
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<div v-for="[id, log] of targetGeneralLogs.battleDetail" :key="id" v-html="log" />
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<div class="bg1 header-cell">전투 결과</div>
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<div v-for="[id, log] of targetGeneralLogs.battleResult" :key="id" v-html="log" />
|
||||||
|
</div>
|
||||||
|
<div v-if="targetGeneralLogs.generalAction.size > 0" class="col-12 col-md-6">
|
||||||
|
<div class="bg1 header-cell">개인 기록</div>
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<div v-for="[id, log] of targetGeneralLogs.generalAction" :key="id" v-html="log" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<BottomBar type="close"></BottomBar>
|
||||||
|
</BContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
declare const queryValues: {
|
||||||
|
generalID: number | null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { BContainer, useToast, BFormSelect, BFormSelectOption } from "bootstrap-vue-3";
|
||||||
|
import { onMounted, provide, ref, watch } from "vue";
|
||||||
|
import { getGameConstStore, type GameConstStore } from "./GameConstStore";
|
||||||
|
import TopBackBar from "@/components/TopBackBar.vue";
|
||||||
|
import BottomBar from "@/components/BottomBar.vue";
|
||||||
|
import type { GeneralListItemP1 } from "./defs/API/Nation";
|
||||||
|
import { SammoAPI } from "./SammoAPI";
|
||||||
|
import { unwrap } from "@/util/unwrap";
|
||||||
|
import { merge2DArrToObjectArr } from "@/util/merge2DArrToObjectArr";
|
||||||
|
import { getNpcColor } from "@/common_legacy";
|
||||||
|
import GeneralBasicCard from "./components/GeneralBasicCard.vue";
|
||||||
|
import GeneralSupplementCard from "@/components/GeneralSupplementCard.vue";
|
||||||
|
import type { NationStaticItem } from "./defs";
|
||||||
|
import type { GeneralLogType } from "./defs/API/General";
|
||||||
|
import { isString } from "lodash";
|
||||||
|
import { formatLog } from "./utilGame/formatLog";
|
||||||
|
|
||||||
|
const toasts = unwrap(useToast());
|
||||||
|
|
||||||
|
const generalList = ref(new Map<number, GeneralListItemP1>());
|
||||||
|
const textMap = {
|
||||||
|
recent_war: [
|
||||||
|
"최근 전투",
|
||||||
|
(gen: GeneralListItemP1) => gen.recent_war,
|
||||||
|
false,
|
||||||
|
(gen: GeneralListItemP1) => `[${gen.recent_war.slice(-5)}]`,
|
||||||
|
],
|
||||||
|
warnum: ["전투 횟수", (gen: GeneralListItemP1) => gen.warnum, false, (gen: GeneralListItemP1) => `[${gen.warnum}회]`],
|
||||||
|
turntime: ["최근 턴", (gen: GeneralListItemP1) => gen.turntime, false, (gen: GeneralListItemP1) => ""],
|
||||||
|
name: ["이름", (gen: GeneralListItemP1) => `${gen.npc} ${gen.name}`, false, (gen: GeneralListItemP1) => ""],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const orderedGeneralList = ref<GeneralListItemP1[]>([]);
|
||||||
|
const orderBy = ref<keyof typeof textMap>("turntime");
|
||||||
|
const targetGeneral = ref<GeneralListItemP1>();
|
||||||
|
const targetGeneralID = ref(queryValues.generalID ?? undefined);
|
||||||
|
|
||||||
|
type GeneralLogs = {
|
||||||
|
[key in GeneralLogType]: Map<number, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const targetGeneralLogs = ref<GeneralLogs>();
|
||||||
|
|
||||||
|
const nationInfo = ref<NationStaticItem>();
|
||||||
|
|
||||||
|
watch([generalList, targetGeneralID], async ([generalList, targetGeneralID]) => {
|
||||||
|
if (targetGeneralID === undefined) {
|
||||||
|
targetGeneral.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
targetGeneral.value = generalList.get(targetGeneralID);
|
||||||
|
|
||||||
|
const logs: GeneralLogs = {
|
||||||
|
generalHistory: new Map(),
|
||||||
|
battleResult: new Map(),
|
||||||
|
battleDetail: new Map(),
|
||||||
|
generalAction: new Map(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const waiter: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
for (const reqType of ["generalHistory", "battleResult", "battleDetail", "generalAction"] as const) {
|
||||||
|
waiter.push(
|
||||||
|
SammoAPI.Nation.GetGeneralLog({ generalID: targetGeneralID, reqType }).then(
|
||||||
|
(res) => {
|
||||||
|
const rawLogs: [number, string][] = Object.entries(res.log).map(([key, value]) => [
|
||||||
|
Number(key),
|
||||||
|
formatLog(value),
|
||||||
|
]);
|
||||||
|
rawLogs.sort(([keyLhs], [keyRhs]) => keyRhs - keyLhs);
|
||||||
|
for (const [idx, log] of rawLogs) {
|
||||||
|
logs[reqType].set(Number(idx), formatLog(log));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if (!isString(err)) {
|
||||||
|
toasts.danger({
|
||||||
|
title: "에러",
|
||||||
|
body: `${err}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(waiter);
|
||||||
|
console.log(logs);
|
||||||
|
targetGeneralLogs.value = logs;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch([generalList, orderBy], ([generalList, orderBy], [, oldOrderBy]) => {
|
||||||
|
console.log(generalList);
|
||||||
|
const list = Array.from(generalList.values());
|
||||||
|
if (orderBy != oldOrderBy) {
|
||||||
|
targetGeneralID.value = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const idSet = new Set<number>(list.map((gen) => gen.no));
|
||||||
|
list.sort((a, b) => {
|
||||||
|
const [, getter, isAsc] = textMap[orderBy];
|
||||||
|
const aVal = getter(a);
|
||||||
|
const bVal = getter(b);
|
||||||
|
if (aVal === bVal) return 0;
|
||||||
|
return isAsc ? (aVal > bVal ? 1 : -1) : aVal < bVal ? 1 : -1;
|
||||||
|
});
|
||||||
|
orderedGeneralList.value = list;
|
||||||
|
const oldTargetGeneralID = targetGeneralID.value;
|
||||||
|
if (!oldTargetGeneralID) {
|
||||||
|
targetGeneralID.value = list[0].no;
|
||||||
|
} else if (!idSet.has(oldTargetGeneralID)) {
|
||||||
|
targetGeneralID.value = list[0].no;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function reload(): Promise<void> {
|
||||||
|
console.log("갱신 시도");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const nationP = SammoAPI.Nation.GetNationInfo({});
|
||||||
|
const { column, list, permission, troops, env } = await SammoAPI.Nation.GeneralList();
|
||||||
|
|
||||||
|
if (permission === 0) {
|
||||||
|
throw "권한이 부족합니다.";
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(list);
|
||||||
|
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||||
|
|
||||||
|
const newList = new Map<number, GeneralListItemP1>();
|
||||||
|
for (const general of rawGeneralList) {
|
||||||
|
newList.set(general.no, general);
|
||||||
|
}
|
||||||
|
generalList.value = newList;
|
||||||
|
|
||||||
|
const { nation } = await nationP;
|
||||||
|
nationInfo.value = nation;
|
||||||
|
} catch (e) {
|
||||||
|
toasts.danger({
|
||||||
|
title: "오류",
|
||||||
|
body: `${e}`,
|
||||||
|
});
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await reload();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-cell {
|
||||||
|
color: orange;
|
||||||
|
font-size: 1.3em;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px gray solid;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -97,7 +97,7 @@ async function reload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openBattleCenter(generalID: number){
|
function openBattleCenter(generalID: number){
|
||||||
window.open(`b_battleCenter.php?gen=${generalID}`)
|
window.open(`v_battleCenter.php?gen=${generalID}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|||||||
+2
-1
@@ -18,7 +18,7 @@ import type { BettingDetailResponse, BettingListResponse } from "./defs/API/Bett
|
|||||||
import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command";
|
import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command";
|
||||||
import type { ChiefResponse } from "./defs/API/NationCommand";
|
import type { ChiefResponse } from "./defs/API/NationCommand";
|
||||||
import type { inheritBuffType, InheritLogResponse } from "./defs/API/InheritAction";
|
import type { inheritBuffType, InheritLogResponse } from "./defs/API/InheritAction";
|
||||||
import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse } from "./defs/API/Nation";
|
import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse, NationInfoResponse } from "./defs/API/Nation";
|
||||||
import type { UploadImageResponse } from "./defs/API/Misc";
|
import type { UploadImageResponse } from "./defs/API/Misc";
|
||||||
import type { GeneralLogType, GetGeneralLogResponse, JoinArgs } from "./defs/API/General";
|
import type { GeneralLogType, GetGeneralLogResponse, JoinArgs } from "./defs/API/General";
|
||||||
import type {
|
import type {
|
||||||
@@ -231,6 +231,7 @@ const apiRealPath = {
|
|||||||
troopID: number;
|
troopID: number;
|
||||||
troopName: string;
|
troopName: string;
|
||||||
}>,
|
}>,
|
||||||
|
GetNationInfo: GET as APICallT<{full?: boolean}, NationInfoResponse>,
|
||||||
},
|
},
|
||||||
Vote: {
|
Vote: {
|
||||||
AddComment: POST as APICallT<{
|
AddComment: POST as APICallT<{
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
},
|
},
|
||||||
"ingame_vue": {
|
"ingame_vue": {
|
||||||
"v_auction": "v_auction.ts",
|
"v_auction": "v_auction.ts",
|
||||||
|
"v_battleCenter": "v_battleCenter.ts",
|
||||||
"v_inheritPoint": "v_inheritPoint.ts",
|
"v_inheritPoint": "v_inheritPoint.ts",
|
||||||
"v_board": "v_board.ts",
|
"v_board": "v_board.ts",
|
||||||
"v_cachedMap": "v_cachedMap",
|
"v_cachedMap": "v_cachedMap",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="general-card-basic">
|
<div class="general-card-basic bg2">
|
||||||
<div
|
<div
|
||||||
class="general-icon"
|
class="general-icon"
|
||||||
:style="{
|
:style="{
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
】 {{ general.turntime.substring(11, 19) }}
|
】 {{ general.turntime.substring(11, 19) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>통솔</div>
|
<div class="bg1">통솔</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@@ -27,46 +27,46 @@
|
|||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
<span v-if="general.lbonus > 0" style="color: cyan">+{{ general.lbonus }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col align-self-center">
|
||||||
<SammoBar :height="10" :percent="general.leadership_exp / 20" />
|
<SammoBar :height="10" :percent="(general.leadership_exp / 20) * 100" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>무력</div>
|
<div class="bg1">무력</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.strength }}
|
{{ general.strength }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col align-self-center">
|
||||||
<SammoBar :height="10" :percent="general.strength_exp / 20" />
|
<SammoBar :height="10" :percent="(general.strength_exp / 20) * 100" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>지력</div>
|
<div class="bg1">지력</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="row gx-0">
|
<div class="row gx-0">
|
||||||
<div class="col" :style="{ color: injuryInfo.color }">
|
<div class="col" :style="{ color: injuryInfo.color }">
|
||||||
{{ general.intel }}
|
{{ general.intel }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col align-self-center">
|
||||||
<SammoBar :height="10" :percent="general.intel_exp / 20" />
|
<SammoBar :height="10" :percent="(general.intel_exp / 20) * 100" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>명마</div>
|
<div class="bg1">명마</div>
|
||||||
<div v-b-tooltip.hover :title="horse.info ?? undefined">{{ horse.name }}</div>
|
<div v-b-tooltip.hover :title="horse.info ?? undefined">{{ horse.name }}</div>
|
||||||
<div>무기</div>
|
<div class="bg1">무기</div>
|
||||||
<div v-b-tooltip.hover :title="weapon.info ?? undefined">{{ weapon.name }}</div>
|
<div v-b-tooltip.hover :title="weapon.info ?? undefined">{{ weapon.name }}</div>
|
||||||
<div>서적</div>
|
<div class="bg1">서적</div>
|
||||||
<div v-b-tooltip.hover :title="book.info ?? undefined">{{ book.name }}</div>
|
<div v-b-tooltip.hover :title="book.info ?? undefined">{{ book.name }}</div>
|
||||||
|
|
||||||
<div>자금</div>
|
<div class="bg1">자금</div>
|
||||||
<div>{{ general.gold.toLocaleString() }}</div>
|
<div>{{ general.gold.toLocaleString() }}</div>
|
||||||
<div>군량</div>
|
<div class="bg1">군량</div>
|
||||||
<div>{{ general.rice.toLocaleString() }}</div>
|
<div>{{ general.rice.toLocaleString() }}</div>
|
||||||
<div>도구</div>
|
<div class="bg1">도구</div>
|
||||||
<div v-b-tooltip.hover :title="item.info ?? undefined">{{ item.name }}</div>
|
<div v-b-tooltip.hover :title="item.info ?? undefined">{{ item.name }}</div>
|
||||||
|
|
||||||
<!-- TODO: show_img_level을 고려 -->
|
<!-- TODO: show_img_level을 고려 -->
|
||||||
@@ -77,55 +77,65 @@
|
|||||||
}"
|
}"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div>병종</div>
|
<div class="bg1">병종</div>
|
||||||
<div v-b-tooltip.hover :title="crewtype.info ?? undefined">{{ crewtype.name }}</div>
|
<div v-b-tooltip.hover :title="crewtype.info ?? undefined">{{ crewtype.name }}</div>
|
||||||
<div>병사</div>
|
<div class="bg1">병사</div>
|
||||||
<div>{{ general.crew.toLocaleString() }}</div>
|
<div>{{ general.crew.toLocaleString() }}</div>
|
||||||
<div>성격</div>
|
<div class="bg1">성격</div>
|
||||||
<div v-b-tooltip.hover :title="personal.info ?? undefined">{{ personal.name }}</div>
|
<div v-b-tooltip.hover :title="personal.info ?? undefined">{{ personal.name }}</div>
|
||||||
|
|
||||||
<!-- TODO: bonusTrain 같은 개념이 필요 -->
|
<!-- TODO: bonusTrain 같은 개념이 필요 -->
|
||||||
<div>훈련</div>
|
<div class="bg1">훈련</div>
|
||||||
<div>{{ general.train }}</div>
|
<div>{{ general.train }}</div>
|
||||||
<div>사기</div>
|
<div class="bg1">사기</div>
|
||||||
<div>{{ general.atmos }}</div>
|
<div>{{ general.atmos }}</div>
|
||||||
<div>특기</div>
|
<div class="bg1">특기</div>
|
||||||
<div>
|
<div>
|
||||||
<span v-b-tooltip.hover :title="specialDomestic.info ?? undefined"> {{ specialDomestic.name }}</span> /
|
<span v-b-tooltip.hover :title="specialDomestic.info ?? undefined"> {{ specialDomestic.name }}</span> /
|
||||||
<span v-b-tooltip.hover :title="specialWar.info ?? undefined"> {{ specialWar.name }}</span>
|
<span v-b-tooltip.hover :title="specialWar.info ?? undefined"> {{ specialWar.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>Lv</div>
|
<div class="bg1">Lv</div>
|
||||||
<!-- TODO: 경험치 막대가 필요 -->
|
<!-- TODO: 경험치 막대가 필요 -->
|
||||||
<div class="general-exp-level">
|
<div class="general-exp-level">
|
||||||
{{ general.explevel }}
|
{{ general.explevel }}
|
||||||
</div>
|
</div>
|
||||||
<div class="general-exp-level-bar">{{ nextExpLevelRemain(general.experience, general.explevel) }}</div>
|
<div class="general-exp-level-bar d-grid">
|
||||||
<div>연령</div>
|
<div class="align-self-center">
|
||||||
|
<SammoBar
|
||||||
|
:height="10"
|
||||||
|
:percent="(([a, b]) => (a / b) * 100)(nextExpLevelRemain(general.experience, general.explevel))"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg1">연령</div>
|
||||||
<div :style="{ color: ageColor }">{{ general.age }}세</div>
|
<div :style="{ color: ageColor }">{{ general.age }}세</div>
|
||||||
|
|
||||||
<div>수비</div>
|
<div class="bg1">수비</div>
|
||||||
<div class="general-defence-train">
|
<div class="general-defence-train">
|
||||||
<span v-if="general.defence_train === 999" style="color: red">수비 안함</span>
|
<span v-if="general.defence_train === 999" style="color: red">수비 안함</span>
|
||||||
<span v-else style="color: limegreen">수비 함(훈사{{ general.defence_train }})</span>
|
<span v-else style="color: limegreen">수비 함(훈사{{ general.defence_train }})</span>
|
||||||
</div>
|
</div>
|
||||||
<div>삭턴</div>
|
<div class="bg1">삭턴</div>
|
||||||
<div>{{ general.killturn }} 턴</div>
|
<div>{{ general.killturn }} 턴</div>
|
||||||
<div>실행</div>
|
<div class="bg1">실행</div>
|
||||||
<div>{{ nextExecuteMinute }}분 남음</div>
|
<div>{{ nextExecuteMinute }}분 남음</div>
|
||||||
|
|
||||||
<div>부대</div>
|
<div class="bg1">부대</div>
|
||||||
<div v-if="!troopInfo" class="general-troop">-</div>
|
<div v-if="!troopInfo" class="general-troop">-</div>
|
||||||
<div v-else class="general-troop">
|
<div v-else class="general-troop">
|
||||||
<s v-if="troopInfo.leader.reservedCommand && troopInfo.leader.reservedCommand[0].action != 'che_집합'" style="color: gray">
|
<s
|
||||||
|
v-if="troopInfo.leader.reservedCommand && troopInfo.leader.reservedCommand[0].action != 'che_집합'"
|
||||||
|
style="color: gray"
|
||||||
|
>
|
||||||
{{ troopInfo.name }}
|
{{ troopInfo.name }}
|
||||||
</s>
|
</s>
|
||||||
<span v-else style="color: orange">
|
<span v-else style="color: orange">
|
||||||
{{ troopInfo.name }}({{ gameConstStore.cityConst[troopInfo.leader.city].name }})
|
{{ troopInfo.name }}({{ gameConstStore.cityConst[troopInfo.leader.city].name }})
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>벌점</div>
|
<div class="bg1">벌점</div>
|
||||||
<div class="general-v">
|
<div class="general-connect-score">
|
||||||
{{ formatConnectScore(general.connect) }} {{ general.connect.toLocaleString() }}점({{ general.con }})
|
{{ formatConnectScore(general.connect) }} {{ general.connect.toLocaleString() }}점({{ general.con }})
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -233,7 +243,18 @@ onMounted(() => {
|
|||||||
grid-template-rows: repeat(9, calc(64px / 3));
|
grid-template-rows: repeat(9, calc(64px / 3));
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
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 {
|
.general-icon {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@@ -263,4 +284,12 @@ onMounted(() => {
|
|||||||
.general-defence-train {
|
.general-defence-train {
|
||||||
grid-column: 2 / 4;
|
grid-column: 2 / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.general-troop {
|
||||||
|
grid-column: 2 / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.general-connect-score {
|
||||||
|
grid-column: 5 / 8;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="general-card-supplement row gx-0">
|
<div class="general-card-supplement row gx-0 bg2">
|
||||||
<div class="col-12 general-card-info">
|
<div class="col-12 general-card-info">
|
||||||
<div class="part-title">추가 정보</div>
|
<div class="part-title bg1">추가 정보</div>
|
||||||
<div>명성</div>
|
<div class="bg1">명성</div>
|
||||||
<div>{{ formatHonor(general.experience) }} ({{ general.experience.toLocaleString() }})</div>
|
<div>{{ formatHonor(general.experience) }} ({{ general.experience.toLocaleString() }})</div>
|
||||||
<div>계급</div>
|
<div class="bg1">계급</div>
|
||||||
<div>{{ general.dedLevelText }} ({{ general.dedication.toLocaleString() }}</div>
|
<div>{{ general.dedLevelText }} ({{ general.dedication.toLocaleString() }})</div>
|
||||||
<div>봉급</div>
|
<div class="bg1">봉급</div>
|
||||||
<div>{{ general.bill.toLocaleString() }}</div>
|
<div>{{ general.bill.toLocaleString() }}</div>
|
||||||
|
|
||||||
<div>전투</div>
|
<div class="bg1">전투</div>
|
||||||
<div>{{ general.warnum.toLocaleString() }}</div>
|
<div>{{ general.warnum.toLocaleString() }}</div>
|
||||||
<div>계략</div>
|
<div class="bg1">계략</div>
|
||||||
<div>{{ general.firenum.toLocaleString() }}</div>
|
<div>{{ general.firenum.toLocaleString() }}</div>
|
||||||
<div>사관</div>
|
<div class="bg1">사관</div>
|
||||||
<div>{{ general.belong }}년차</div>
|
<div>{{ general.belong }}년차</div>
|
||||||
|
|
||||||
<div>승률</div>
|
<div class="bg1">승률</div>
|
||||||
<div>{{ ((general.killnum / Math.max(general.warnum, 1)) * 100).toFixed(2) }} %</div>
|
<div>{{ ((general.killnum / Math.max(general.warnum, 1)) * 100).toFixed(2) }} %</div>
|
||||||
<div>승리</div>
|
<div class="bg1">승리</div>
|
||||||
<div>{{ general.killnum.toLocaleString() }}</div>
|
<div>{{ general.killnum.toLocaleString() }}</div>
|
||||||
<div>패배</div>
|
<div class="bg1">패배</div>
|
||||||
<div>{{ general.deathnum.toPrecision() }}</div>
|
<div>{{ general.deathnum.toPrecision() }}</div>
|
||||||
|
|
||||||
<div>살상률</div>
|
<div class="bg1">살상률</div>
|
||||||
<div>
|
<div>
|
||||||
{{
|
{{
|
||||||
((general.killcrew / Math.max(general.deathcrew, 1)) * 100).toLocaleString(undefined, {
|
((general.killcrew / Math.max(general.deathcrew, 1)) * 100).toLocaleString(undefined, {
|
||||||
@@ -33,30 +33,30 @@
|
|||||||
}}
|
}}
|
||||||
%
|
%
|
||||||
</div>
|
</div>
|
||||||
<div>사살</div>
|
<div class="bg1">사살</div>
|
||||||
<div>{{ general.killcrew.toLocaleString() }}</div>
|
<div>{{ general.killcrew.toLocaleString() }}</div>
|
||||||
<div>피살</div>
|
<div class="bg1">피살</div>
|
||||||
<div>{{ general.deathcrew.toLocaleString() }}</div>
|
<div>{{ general.deathcrew.toLocaleString() }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-7 general-card-dex">
|
<div :class="[props.showCommandList ? 'col-7' : 'col', 'general-card-dex']">
|
||||||
<div class="part-title">숙련도</div>
|
<div class="part-title bg1">숙련도</div>
|
||||||
<template v-for="[dexType, dex, dexInfo] of dexList" :key="dexType">
|
<template v-for="[dexType, dex, dexInfo] of dexList" :key="dexType">
|
||||||
<div>{{ dexType }}</div>
|
<div class="bg1">{{ dexType }}</div>
|
||||||
<div :style="{ color: dexInfo.color }">{{ dexInfo.name }}</div>
|
<div :style="{ color: dexInfo.color }">{{ dexInfo.name }}</div>
|
||||||
<div>{{ (dex / 1000).toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) }}K</div>
|
<div>{{ (dex / 1000).toLocaleString(undefined, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) }}K</div>
|
||||||
<div>
|
<div class="d-grid">
|
||||||
<SammoBar :height="10" :percent="dex / 1_000_000" />
|
<div class="align-self-center"><SammoBar :height="10" :percent="dex / 1_000_000 * 100" /></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5 general-card-turn">
|
<div
|
||||||
|
v-if="props.showCommandList && general.reservedCommand && general.reservedCommand.length > 0"
|
||||||
|
class="col-5 general-card-turn"
|
||||||
|
>
|
||||||
<div class="part-title">예약턴</div>
|
<div class="part-title">예약턴</div>
|
||||||
<template v-if="general.reservedCommand">
|
<div v-for="(turn, idx) in general.reservedCommand.slice(0, 5)" :key="idx">
|
||||||
<div v-for="(turn, idx) in general.reservedCommand.slice(0, 5)" :key="idx">
|
{{ turn.brief }}
|
||||||
{{ turn.brief }}
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div v-else style="grid-row: 2 / 7">NPC</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -69,6 +69,7 @@ import { formatDexLevel, type DexInfo } from "@/utilGame/formatDexLevel";
|
|||||||
import { formatHonor } from "@/utilGame/formatHonor";
|
import { formatHonor } from "@/utilGame/formatHonor";
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
general: GeneralListItemP1;
|
general: GeneralListItemP1;
|
||||||
|
showCommandList?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const dexList = computed((): [string, number, DexInfo][] => {
|
const dexList = computed((): [string, number, DexInfo][] => {
|
||||||
@@ -83,13 +84,14 @@ const dexList = computed((): [string, number, DexInfo][] => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.general-card-basic {
|
.general-card-supplement {
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 64px repeat(3, 2fr 5fr);
|
|
||||||
grid-template-rows: repeat(9, calc(64px / 3));
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.part-title {
|
||||||
|
grid-column: 1 / 7;
|
||||||
|
}
|
||||||
.general-icon {
|
.general-icon {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@@ -124,9 +126,18 @@ const dexList = computed((): [string, number, DexInfo][] => {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 64px 1fr);
|
grid-template-columns: repeat(3, 64px 1fr);
|
||||||
grid-template-rows: repeat(5, calc(64px / 3));
|
grid-template-rows: repeat(5, calc(64px / 3));
|
||||||
|
border-right: solid 1px gray;
|
||||||
|
|
||||||
.part-title {
|
.part-title {
|
||||||
grid-column: 1 / 4;
|
grid-column: 1 / 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg1 {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
border-bottom: solid 1px gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,15 +145,28 @@ const dexList = computed((): [string, number, DexInfo][] => {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 64px 40px 60px 1fr;
|
grid-template-columns: 64px 40px 60px 1fr;
|
||||||
grid-template-rows: repeat(6, calc(64px / 3));
|
grid-template-rows: repeat(6, calc(64px / 3));
|
||||||
|
border-right: solid 1px gray;
|
||||||
|
|
||||||
.part-title {
|
.part-title {
|
||||||
grid-column: 1 / 5;
|
grid-column: 1 / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg1 {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
border-bottom: solid 1px gray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.general-card-turn {
|
.general-card-turn {
|
||||||
display: grid;
|
.bg1 {
|
||||||
grid-template-columns: 1fr;
|
border-left: solid 1px gray;
|
||||||
grid-template-rows: repeat(6, calc(64px / 3));
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
border-bottom: solid 1px gray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,25 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-b-tooltip.hover.top
|
v-b-tooltip.hover.top
|
||||||
:title="`${props.percent}$`"
|
:title="`${props.percent.toLocaleString(undefined, { maximumFractionDigits: 2 })}%`"
|
||||||
class="sammo-bar"
|
class="sammo-bar"
|
||||||
:style="{
|
:style="{
|
||||||
height: `${props.height}px`,
|
height: `${props.height + 2}px`,
|
||||||
backgroundImage: `url(${imagePath}/pr${props.height - 2}.png)`,
|
position: 'relative',
|
||||||
backgroundRepeat: 'repeat-x',
|
|
||||||
backgroundPosition: 'center',
|
|
||||||
borderTop: 'solid 1px #888',
|
borderTop: 'solid 1px #888',
|
||||||
borderBottom: 'solid 1px #333',
|
borderBottom: 'solid 1px #333',
|
||||||
|
margin: 'auto',
|
||||||
|
width: props.width === undefined ? '100%' : props.width,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
class="sammo-bar-base"
|
||||||
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '0',
|
||||||
|
width: '100%',
|
||||||
|
height: `${props.height}px`,
|
||||||
|
backgroundImage: `url(${imagePath}/pr${props.height - 2}.gif)`,
|
||||||
|
backgroundRepeat: 'repeat-x',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
<div
|
<div
|
||||||
class="sammo-bar-in"
|
class="sammo-bar-in"
|
||||||
:style="{
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '0',
|
||||||
|
width: `${clamp(props.percent, 0, 100)}%`,
|
||||||
height: `${props.height}px`,
|
height: `${props.height}px`,
|
||||||
backgroundImage: `url(${imagePath}/pb${props.height - 2}.png)`,
|
backgroundImage: `url(${imagePath}/pb${props.height - 2}.gif)`,
|
||||||
backgroundRepeat: 'repeat-x',
|
backgroundRepeat: 'repeat-x',
|
||||||
backgroundPosition: 'left center',
|
backgroundPosition: 'left center',
|
||||||
width: `${clamp(props.percent, 0, 100)}%`,
|
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,6 +45,7 @@ import { clamp } from "lodash";
|
|||||||
const imagePath = window.pathConfig.gameImage;
|
const imagePath = window.pathConfig.gameImage;
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
height: 7 | 10;
|
height: 7 | 10;
|
||||||
|
width?: string;
|
||||||
percent: number;
|
percent: number;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValuesOf, TurnObj } from "@/defs";
|
import type { ValuesOf, TurnObj, NationStaticItem } from "@/defs";
|
||||||
import type { GameObjClassKey } from "@/defs/GameObj";
|
import type { GameObjClassKey } from "@/defs/GameObj";
|
||||||
import type { ValidResponse } from "@/SammoAPI";
|
import type { ValidResponse } from "@/SammoAPI";
|
||||||
|
|
||||||
@@ -127,3 +127,29 @@ export type RawGeneralListP2 = ValidResponse & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2;
|
export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2;
|
||||||
|
|
||||||
|
export type NationItem = NationStaticItem & {
|
||||||
|
gold: number;
|
||||||
|
rice: number;
|
||||||
|
bill: number;
|
||||||
|
rate: number;
|
||||||
|
secretlimit: number;
|
||||||
|
chief_set: number;
|
||||||
|
scout: number;
|
||||||
|
war: number;
|
||||||
|
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>;
|
||||||
|
})
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import "@scss/nationGeneral.scss";
|
||||||
|
import "ag-grid-community/dist/styles/ag-grid.css";
|
||||||
|
import "ag-grid-community/dist/styles/ag-theme-balham-dark.css";
|
||||||
|
import "@scss/battleLog.scss";
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import PageBattleCenter from '@/PageBattleCenter.vue';
|
||||||
|
import { BootstrapVue3, BToastPlugin } from 'bootstrap-vue-3';
|
||||||
|
import { auto500px } from './util/auto500px';
|
||||||
|
import { htmlReady } from "./util/htmlReady";
|
||||||
|
import { insertCustomCSS } from "./util/customCSS";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto500px();
|
||||||
|
|
||||||
|
htmlReady(() => {
|
||||||
|
insertCustomCSS();
|
||||||
|
});
|
||||||
|
createApp(PageBattleCenter).use(BootstrapVue3).use(BToastPlugin).mount('#app');
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo;
|
||||||
|
|
||||||
|
include "lib.php";
|
||||||
|
include "func.php";
|
||||||
|
//로그인 검사
|
||||||
|
$session = Session::requireGameLogin()->setReadOnly();
|
||||||
|
$userID = Session::getUserID();
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$gen = Util::getReq('gen', 'int');
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=500" />
|
||||||
|
<title><?= UniqueConst::$serverName ?>: 감찰부</title>
|
||||||
|
<?= WebUtil::printStaticValues([
|
||||||
|
'staticValues' => [
|
||||||
|
'serverNick' => DB::prefix(),
|
||||||
|
'mapName' => GameConst::$mapName,
|
||||||
|
'unitSet' => GameConst::$unitSet,
|
||||||
|
],
|
||||||
|
'queryValues' => [
|
||||||
|
'generalID' => $gen,
|
||||||
|
]
|
||||||
|
], false) ?>
|
||||||
|
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
||||||
|
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||||
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
|
||||||
|
<?= WebUtil::printDist('vue', 'v_battleCenter', true) ?>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user