feat: 통합 세력 장수/암행부 페이지 (#213)
- ag-grid 기반 - 컬럼 사용자 정의 기능 제공 - 컬럼 재정렬, 고정, 정렬 기능 - 컬럼 상태 저장, 불러오기 - 마지막 컬럼 재 사용 - 아이콘, 장수명 클릭 시 특수 기능 제공 - 기본 세력 장수/암행부에서는 '감찰부' - 추가 컬럼 - 최근 전투 - 전투 수 - 승리 수 - 살상률 - API/Nation/GeneralList 추가 Co-authored-by: hide_d <hided62@gmail.com> Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/213
This commit is contained in:
+1
-2
@@ -101,8 +101,7 @@ return [
|
|||||||
'hwe/j_general_set_permission.php',
|
'hwe/j_general_set_permission.php',
|
||||||
'hwe/j_get_basic_general_list.php',
|
'hwe/j_get_basic_general_list.php',
|
||||||
'hwe/j_get_city_list.php',
|
'hwe/j_get_city_list.php',
|
||||||
'hwe/j_get_general_list.php',
|
'hwe/j_get_reserved_command.php',
|
||||||
'hwe/j_get_nation_general_list.php',
|
|
||||||
'hwe/j_get_select_npc_token.php',
|
'hwe/j_get_select_npc_token.php',
|
||||||
'hwe/j_get_select_pool.php',
|
'hwe/j_get_select_pool.php',
|
||||||
'hwe/j_image_upload.php',
|
'hwe/j_image_upload.php',
|
||||||
|
|||||||
Vendored
+2
-1
@@ -28,5 +28,6 @@
|
|||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"josa",
|
"josa",
|
||||||
"sammo"
|
"sammo"
|
||||||
]
|
],
|
||||||
|
"editor.tabSize": 2
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ $showGeneral = General::createGeneralObjFromDB($gen);
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form name=form1 method=post>
|
<form name=form1 method=get>
|
||||||
정렬순서 :
|
정렬순서 :
|
||||||
<select name='query_type' size=1>
|
<select name='query_type' size=1>
|
||||||
<?php foreach ($queryMap as $queryType => [$queryTypeText,]) : ?>
|
<?php foreach ($queryMap as $queryType => [$queryTypeText,]) : ?>
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace sammo;
|
|
||||||
|
|
||||||
include "lib.php";
|
|
||||||
include "func.php";
|
|
||||||
|
|
||||||
|
|
||||||
//로그인 검사
|
|
||||||
$session = Session::requireLogin([]);
|
|
||||||
$userID = Session::getUserID();
|
|
||||||
|
|
||||||
$db = DB::db();
|
|
||||||
$withToken = Util::getPost('with_token', 'bool', false);
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
|
|
||||||
if($session->isGameLoggedIn()){
|
|
||||||
increaseRefresh("장수일람", 2);
|
|
||||||
|
|
||||||
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
|
||||||
$con = checkLimit($me['con']);
|
|
||||||
if ($con >= 2) {
|
|
||||||
Json::die([
|
|
||||||
'result'=>false,
|
|
||||||
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
|
|
||||||
$now = new \DateTimeImmutable();
|
|
||||||
|
|
||||||
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
|
|
||||||
Json::die([
|
|
||||||
'result'=>false,
|
|
||||||
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
|
|
||||||
$session->availableNextCallGetGeneralList = $availableNextCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
$session->setReadOnly();
|
|
||||||
|
|
||||||
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
|
|
||||||
|
|
||||||
$ownerNameList = [];
|
|
||||||
if($gameStor->isunited){
|
|
||||||
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
|
|
||||||
$ownerNameList[$ownerID] = $ownerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$generalList = [];
|
|
||||||
foreach($rawGeneralList as $rawGeneral){
|
|
||||||
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
|
|
||||||
|
|
||||||
if(key_exists($owner, $ownerNameList)){
|
|
||||||
$ownerName = $ownerNameList[$owner];
|
|
||||||
}
|
|
||||||
|
|
||||||
$nationArr = getNationStaticInfo($nation);
|
|
||||||
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
|
|
||||||
|
|
||||||
$generalList[] = [
|
|
||||||
$no,
|
|
||||||
$picture,
|
|
||||||
$imgsvr,
|
|
||||||
$npc,
|
|
||||||
$age,
|
|
||||||
$nationArr['name'],
|
|
||||||
getGeneralSpecialDomesticName($special),
|
|
||||||
getGeneralSpecialWarName($special2),
|
|
||||||
getGenChar($personal),
|
|
||||||
$name,
|
|
||||||
$npc==1?$ownerName:null,
|
|
||||||
$injury,
|
|
||||||
$leadership,
|
|
||||||
$lbonus,
|
|
||||||
$strength,
|
|
||||||
$intel,
|
|
||||||
getExpLevel($experience),
|
|
||||||
getHonor($experience),
|
|
||||||
getDed($dedication),
|
|
||||||
getOfficerLevelText($officerLevel, $nationArr['level']),
|
|
||||||
$killturn,
|
|
||||||
$connectCnt
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = [
|
|
||||||
'result'=>'true',
|
|
||||||
'list'=>$generalList,
|
|
||||||
];
|
|
||||||
|
|
||||||
if($withToken){
|
|
||||||
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
|
||||||
$tokens = [];
|
|
||||||
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
|
|
||||||
$validUntil = $token['valid_until'];
|
|
||||||
|
|
||||||
foreach(Json::decode($token['pick_result']) as $pickResult){
|
|
||||||
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result['token'] = $tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
Json::die($result);
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace sammo;
|
|
||||||
|
|
||||||
//통합 세력장수&암행부 viewer
|
|
||||||
|
|
||||||
include "lib.php";
|
|
||||||
include "func.php";
|
|
||||||
|
|
||||||
//로그인 검사
|
|
||||||
$session = Session::requireGameLogin([])->setReadOnly();
|
|
||||||
$userID = Session::getUserID();
|
|
||||||
|
|
||||||
$db = DB::db();
|
|
||||||
$reqType = Util::getReq('req', 'int', 1);
|
|
||||||
$reqForce = Util::getReq('force', 'bool', false);
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
|
||||||
|
|
||||||
increaseRefresh("세력장수", 1);
|
|
||||||
|
|
||||||
$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $userID);
|
|
||||||
$con = checkLimit($me['con']);
|
|
||||||
if ($con >= 2) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$nationID = $me['nation'];
|
|
||||||
$permission = checkSecretPermission($me, true);
|
|
||||||
if ($reqForce && $reqType > $permission) {
|
|
||||||
Json::die([
|
|
||||||
'result' => false,
|
|
||||||
'reason' => '권한이 부족합니다.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$permission = min($reqType, $permission);
|
|
||||||
$nationArr = getNationStaticInfo($nationID);
|
|
||||||
$viewColumns = [
|
|
||||||
'no' => 0,
|
|
||||||
'name' => 0,
|
|
||||||
'owner_name' => 9,
|
|
||||||
'nation' => 0,
|
|
||||||
'city' => 1,
|
|
||||||
'officer_level' => 2,
|
|
||||||
'officer_city' => 2,
|
|
||||||
'npc' => 0,
|
|
||||||
'defence_train' => 2,
|
|
||||||
'troop' => 2,
|
|
||||||
'injury' => 0,
|
|
||||||
'leadership' => 0,
|
|
||||||
'strength' => 0,
|
|
||||||
'intel' => 0,
|
|
||||||
'experience' => 1,
|
|
||||||
'explevel' => 0,
|
|
||||||
'dedication' => 1,
|
|
||||||
'dedlevel' => 0,
|
|
||||||
'gold' => 0,
|
|
||||||
'rice' => 0,
|
|
||||||
'crewtype' => 2,
|
|
||||||
'crew' => 2,
|
|
||||||
'train' => 2,
|
|
||||||
'atmos' => 2,
|
|
||||||
'killturn' => 0,
|
|
||||||
'turntime' => 2,
|
|
||||||
'picture' => 0,
|
|
||||||
'imgsvr' => 0,
|
|
||||||
'age' => 0,
|
|
||||||
'special' => 0,
|
|
||||||
'special2' => 0,
|
|
||||||
'personal' => 0,
|
|
||||||
'belong' => 0,
|
|
||||||
'horse' => 2,
|
|
||||||
'weapon' => 2,
|
|
||||||
'book' => 2,
|
|
||||||
'item' => 2,
|
|
||||||
'connect' => 0
|
|
||||||
];
|
|
||||||
|
|
||||||
$customViewColumns = [
|
|
||||||
'officerLevel' => 0,
|
|
||||||
'officerLevelText' => 0,
|
|
||||||
'lbonus' => 0,
|
|
||||||
'ownerName' => 0,
|
|
||||||
'honorText' => 0
|
|
||||||
];
|
|
||||||
|
|
||||||
function getOfficerLevel($rawGeneral)
|
|
||||||
{
|
|
||||||
global $permission;
|
|
||||||
$level = $rawGeneral['officer_level'];
|
|
||||||
if ($level >= 5) {
|
|
||||||
return $level;
|
|
||||||
}
|
|
||||||
if ($permission > 1) {
|
|
||||||
return $level;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$specialViewFilter = [
|
|
||||||
'officerLevel' => function ($rawGeneral){
|
|
||||||
return getOfficerLevel($rawGeneral);
|
|
||||||
},
|
|
||||||
'special' => function ($rawGeneral) {
|
|
||||||
return getGeneralSpecialDomesticName($rawGeneral['special']);
|
|
||||||
},
|
|
||||||
'special2' => function ($rawGeneral) {
|
|
||||||
return getGeneralSpecialWarName($rawGeneral['special2']);
|
|
||||||
},
|
|
||||||
'personal' => function ($rawGeneral) {
|
|
||||||
return getGenChar($rawGeneral['personal']);
|
|
||||||
},
|
|
||||||
'lbonus' => function ($rawGeneral) use ($nationArr) {
|
|
||||||
return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']);
|
|
||||||
},
|
|
||||||
'ownerName' => function ($rawGeneral) {
|
|
||||||
if ($rawGeneral['npc'] != 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $rawGeneral['owner_name'];
|
|
||||||
},
|
|
||||||
'officerLevelText' => function ($rawGeneral) use ($nationArr) {
|
|
||||||
$level = getOfficerLevel($rawGeneral);
|
|
||||||
return getOfficerLevelText($level, $nationArr['level']);
|
|
||||||
},
|
|
||||||
'honorText' => function ($rawGeneral) {
|
|
||||||
return getHonor($rawGeneral['experience']);
|
|
||||||
},
|
|
||||||
'dedLevelText' => function ($rawGeneral) {
|
|
||||||
return getDedLevelText($rawGeneral['dedLevel']);
|
|
||||||
},
|
|
||||||
'turntime' => function ($rawGeneral) {
|
|
||||||
//'0000-00-00 11:23';
|
|
||||||
return substr($rawGeneral['turntime'], 11, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1);
|
|
||||||
|
|
||||||
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no');
|
|
||||||
|
|
||||||
$resultColumns = [];
|
|
||||||
foreach ($viewColumns as $column => $reqPermission) {
|
|
||||||
if ($reqPermission > $permission) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$resultColumns[] = $column;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($customViewColumns as $column => $reqPermission) {
|
|
||||||
if ($reqPermission > $permission) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$resultColumns[] = $column;
|
|
||||||
}
|
|
||||||
|
|
||||||
$generalList = [];
|
|
||||||
foreach ($rawGeneralList as $rawGeneral) {
|
|
||||||
//General 생성?
|
|
||||||
|
|
||||||
$item = [];
|
|
||||||
foreach ($resultColumns as $column) {
|
|
||||||
if (key_exists($column, $specialViewFilter)) {
|
|
||||||
$value = $specialViewFilter[$column]($rawGeneral);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$value = $rawGeneral[$column];
|
|
||||||
}
|
|
||||||
$item[] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
$generalList[] = $item;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = [
|
|
||||||
'result' => true,
|
|
||||||
'column' => $resultColumns,
|
|
||||||
'list' => $generalList,
|
|
||||||
];
|
|
||||||
|
|
||||||
Json::die($result);
|
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\List\Nation;
|
||||||
|
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\General;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\KVStorage;
|
||||||
|
use sammo\RootDB;
|
||||||
|
use sammo\Session;
|
||||||
|
use sammo\Util;
|
||||||
|
use sammo\Validator;
|
||||||
|
|
||||||
|
use function sammo\calcLeadershipBonus;
|
||||||
|
use function sammo\checkLimit;
|
||||||
|
use function sammo\checkSecretPermission;
|
||||||
|
use function sammo\getDed;
|
||||||
|
use function sammo\getDedLevelText;
|
||||||
|
use function sammo\getExpLevel;
|
||||||
|
use function sammo\getGenChar;
|
||||||
|
use function sammo\getGeneralSpecialDomesticName;
|
||||||
|
use function sammo\getGeneralSpecialWarName;
|
||||||
|
use function sammo\getHonor;
|
||||||
|
use function sammo\getNationStaticInfo;
|
||||||
|
use function sammo\getOfficerLevelText;
|
||||||
|
use function sammo\increaseRefresh;
|
||||||
|
|
||||||
|
class GeneralList extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v
|
||||||
|
->rule('boolean', 'with_token');
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$db = DB::db();
|
||||||
|
$withToken = $this->args['with_token']??false;
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
|
||||||
|
$userID = $session->userID;
|
||||||
|
if ($session->isGameLoggedIn()) {
|
||||||
|
increaseRefresh("장수일람", 2);
|
||||||
|
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
|
||||||
|
$con = checkLimit($me['con']);
|
||||||
|
if ($con >= 2) {
|
||||||
|
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$availableNextCall = $session->availableNextCallGetGeneralList ?? '2000-01-01 00:00:00';
|
||||||
|
$now = new \DateTimeImmutable();
|
||||||
|
|
||||||
|
if ($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5) {
|
||||||
|
return "장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : " . $availableNextCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
|
||||||
|
$session->availableNextCallGetGeneralList = $availableNextCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
$session->setReadOnly();
|
||||||
|
|
||||||
|
|
||||||
|
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
|
||||||
|
|
||||||
|
$ownerNameList = [];
|
||||||
|
if ($gameStor->isunited) {
|
||||||
|
foreach (RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]) {
|
||||||
|
$ownerNameList[$ownerID] = $ownerName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$generalList = [];
|
||||||
|
foreach ($rawGeneralList as $rawGeneral) {
|
||||||
|
[$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $connectCnt] = $rawGeneral;
|
||||||
|
|
||||||
|
if (key_exists($owner, $ownerNameList)) {
|
||||||
|
$ownerName = $ownerNameList[$owner];
|
||||||
|
}
|
||||||
|
|
||||||
|
$nationArr = getNationStaticInfo($nation);
|
||||||
|
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
|
||||||
|
|
||||||
|
$generalList[] = [
|
||||||
|
$no,
|
||||||
|
$picture,
|
||||||
|
$imgsvr,
|
||||||
|
$npc,
|
||||||
|
$age,
|
||||||
|
$nationArr['name'],
|
||||||
|
getGeneralSpecialDomesticName($special),
|
||||||
|
getGeneralSpecialWarName($special2),
|
||||||
|
getGenChar($personal),
|
||||||
|
$name,
|
||||||
|
$npc == 1 ? $ownerName : null,
|
||||||
|
$injury,
|
||||||
|
$leadership,
|
||||||
|
$lbonus,
|
||||||
|
$strength,
|
||||||
|
$intel,
|
||||||
|
getExpLevel($experience),
|
||||||
|
getHonor($experience),
|
||||||
|
getDed($dedication),
|
||||||
|
getOfficerLevelText($officerLevel, $nationArr['level']),
|
||||||
|
$killturn,
|
||||||
|
$connectCnt
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$resultColumns = [
|
||||||
|
'no',
|
||||||
|
'picture',
|
||||||
|
'imgsvr',
|
||||||
|
'npc',
|
||||||
|
'age',
|
||||||
|
'nationName',
|
||||||
|
'special',
|
||||||
|
'special2',
|
||||||
|
'personal',
|
||||||
|
'name',
|
||||||
|
'ownerName',
|
||||||
|
'injury',
|
||||||
|
'leadership',
|
||||||
|
'lbonus',
|
||||||
|
'strength',
|
||||||
|
'intel',
|
||||||
|
'explevel',
|
||||||
|
'honorText',
|
||||||
|
'dedLevelText',
|
||||||
|
'officerLevelText',
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'result' => 'true',
|
||||||
|
'column' => $resultColumns,
|
||||||
|
'list' => $generalList,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
if ($withToken) {
|
||||||
|
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
|
||||||
|
$tokens = [];
|
||||||
|
foreach ($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token) {
|
||||||
|
$validUntil = $token['valid_until'];
|
||||||
|
|
||||||
|
foreach (Json::decode($token['pick_result']) as $pickResult) {
|
||||||
|
$tokens[$pickResult['no']] = $pickResult['keepCnt'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result['token'] = $tokens;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ use function sammo\prepareDir;
|
|||||||
class GetConst extends \sammo\BaseAPI
|
class GetConst extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
/** 반환하는 StaticValues 타입이 달라지면 +1 */
|
/** 반환하는 StaticValues 타입이 달라지면 +1 */
|
||||||
const CONST_API_VERSION = 1;
|
const CONST_API_VERSION = 2;
|
||||||
const CACHE_KEY = 'JSConst';
|
const CACHE_KEY = 'JSConst';
|
||||||
|
|
||||||
private ?string $cacheKey = null;
|
private ?string $cacheKey = null;
|
||||||
@@ -109,7 +109,7 @@ class GetConst extends \sammo\BaseAPI
|
|||||||
public function tryCache(): ?APICacheResult
|
public function tryCache(): ?APICacheResult
|
||||||
{
|
{
|
||||||
if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) {
|
if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) {
|
||||||
return new APICacheResult(TimeUtil::secondsToDateTime($this->findLastModified(), true, true));
|
return new APICacheResult(TimeUtil::secondsToDateTime($this->findLastModified()??\time(), true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new APICacheResult(null, $this->getCacheKey());
|
return new APICacheResult(null, $this->getCacheKey());
|
||||||
@@ -258,6 +258,18 @@ class GetConst extends \sammo\BaseAPI
|
|||||||
|
|
||||||
$iActionInfo[$mappedKey] = $actionInfo;
|
$iActionInfo[$mappedKey] = $actionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$crewtypeMap = [];
|
||||||
|
foreach(GameUnitConst::all() as $crewtypeObj){
|
||||||
|
$crewtypeMap[$crewtypeObj->id] = [
|
||||||
|
'value'=>(string)$crewtypeObj->id,
|
||||||
|
'name'=>$crewtypeObj->name,
|
||||||
|
'info'=>$crewtypeObj->getInfo(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$iActionInfo['crewtype'] = $crewtypeMap;
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'gameConst' => get_class_vars('\sammo\GameConst'),
|
'gameConst' => get_class_vars('\sammo\GameConst'),
|
||||||
'gameUnitConst' => GameUnitConst::all(),
|
'gameUnitConst' => GameUnitConst::all(),
|
||||||
|
|||||||
@@ -0,0 +1,285 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Nation;
|
||||||
|
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\General;
|
||||||
|
use sammo\Session;
|
||||||
|
use sammo\Util;
|
||||||
|
use sammo\Validator;
|
||||||
|
|
||||||
|
use function sammo\calcLeadershipBonus;
|
||||||
|
use function sammo\checkLimit;
|
||||||
|
use function sammo\checkSecretPermission;
|
||||||
|
use function sammo\getBillByLevel;
|
||||||
|
use function sammo\getDedLevelText;
|
||||||
|
use function sammo\getGenChar;
|
||||||
|
use function sammo\getGeneralSpecialDomesticName;
|
||||||
|
use function sammo\getGeneralSpecialWarName;
|
||||||
|
use function sammo\getHonor;
|
||||||
|
use function sammo\getNationStaticInfo;
|
||||||
|
use function sammo\getOfficerLevelText;
|
||||||
|
use function sammo\increaseRefresh;
|
||||||
|
|
||||||
|
class GeneralList extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
private int $permission;
|
||||||
|
|
||||||
|
static $viewColumns = [
|
||||||
|
'no' => 0,
|
||||||
|
'name' => 0,
|
||||||
|
'nation' => 0,
|
||||||
|
'npc' => 0,
|
||||||
|
'injury' => 0,
|
||||||
|
'leadership' => 0,
|
||||||
|
'strength' => 0,
|
||||||
|
'intel' => 0,
|
||||||
|
'explevel' => 0,
|
||||||
|
'dedlevel' => 0,
|
||||||
|
'gold' => 0,
|
||||||
|
'rice' => 0,
|
||||||
|
'killturn' => 0,
|
||||||
|
'picture' => 0,
|
||||||
|
'imgsvr' => 0,
|
||||||
|
'age' => 0,
|
||||||
|
'special' => 0,
|
||||||
|
'special2' => 0,
|
||||||
|
'personal' => 0,
|
||||||
|
'belong' => 0,
|
||||||
|
'connect' => 0,
|
||||||
|
|
||||||
|
|
||||||
|
'city' => 1,
|
||||||
|
'experience' => 1,
|
||||||
|
'dedication' => 1,
|
||||||
|
|
||||||
|
'officer_level' => 2,
|
||||||
|
'officer_city' => 2,
|
||||||
|
'defence_train' => 2,
|
||||||
|
'troop' => 2,
|
||||||
|
'crewtype' => 2,
|
||||||
|
'crew' => 2,
|
||||||
|
'train' => 2,
|
||||||
|
'atmos' => 2,
|
||||||
|
'turntime' => 2,
|
||||||
|
'horse' => 2,
|
||||||
|
'weapon' => 2,
|
||||||
|
'book' => 2,
|
||||||
|
'item' => 2,
|
||||||
|
'recent_war' => 2,
|
||||||
|
|
||||||
|
'aux' => 2,
|
||||||
|
|
||||||
|
|
||||||
|
'owner_name' => 9,//안씀.
|
||||||
|
|
||||||
|
//RANK
|
||||||
|
'warnum' => 2,
|
||||||
|
'killnum' => 2,
|
||||||
|
'deathnum' => 2,
|
||||||
|
'killcrew' => 2,
|
||||||
|
'deathcrew' => 2,
|
||||||
|
'firenum' => 2,
|
||||||
|
];
|
||||||
|
|
||||||
|
static $columnRemap = [
|
||||||
|
'special' => 'specialDomestic',
|
||||||
|
'special2' => 'specialWar',
|
||||||
|
'aux' => null,
|
||||||
|
];
|
||||||
|
|
||||||
|
static $customViewColumns = [
|
||||||
|
'officerLevel' => 0,
|
||||||
|
'officerLevelText' => 0,
|
||||||
|
'lbonus' => 0,
|
||||||
|
'ownerName' => 0,
|
||||||
|
'honorText' => 0,
|
||||||
|
'dedLevelText' => 0,
|
||||||
|
'bill' => 0,
|
||||||
|
'reservedCommand' => 2,
|
||||||
|
|
||||||
|
'autorun_limit' => 2,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
//TODO: 장기적으로는 요청에 따라 반환해야...
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getOfficerLevel($rawGeneral)
|
||||||
|
{
|
||||||
|
$level = $rawGeneral['officer_level'];
|
||||||
|
if ($level >= 5) {
|
||||||
|
return $level;
|
||||||
|
}
|
||||||
|
if ($this->permission > 1) {
|
||||||
|
return $level;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
increaseRefresh("세력장수", 1);
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
|
||||||
|
$env = $gameStor->getValues(['year', 'month', 'turntime', 'turnterm', 'autorun_user', 'killturn']);
|
||||||
|
|
||||||
|
$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID());
|
||||||
|
$con = checkLimit($me['con']);
|
||||||
|
if ($con >= 2) {
|
||||||
|
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
|
||||||
|
}
|
||||||
|
|
||||||
|
$nationID = $me['nation'];
|
||||||
|
$this->permission = checkSecretPermission($me, true);
|
||||||
|
|
||||||
|
$nationArr = getNationStaticInfo($nationID);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), 1);
|
||||||
|
|
||||||
|
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i ORDER BY turntime ASC', Util::formatListOfBackticks($queryColumns), $nationID), 'no');
|
||||||
|
|
||||||
|
$reservedCommand = [];
|
||||||
|
if ($this->permission >= 2) {
|
||||||
|
$nonNPCGeneralIDList = [];
|
||||||
|
foreach ($rawGeneralList as $rawGeneral) {
|
||||||
|
if ($rawGeneral['npc'] < 2) {
|
||||||
|
$nonNPCGeneralIDList[] = $rawGeneral['no'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rawTurnList = $db->query(
|
||||||
|
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
|
||||||
|
$nonNPCGeneralIDList
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($rawTurnList as $rawTurn) {
|
||||||
|
[
|
||||||
|
'general_id' => $generalID,
|
||||||
|
'action' => $action,
|
||||||
|
'arg' => $arg,
|
||||||
|
'brief' => $brief,
|
||||||
|
] = $rawTurn;
|
||||||
|
if (!key_exists($generalID, $reservedCommand)) {
|
||||||
|
$reservedCommand[$generalID] = [];
|
||||||
|
}
|
||||||
|
$reservedCommand[$generalID][] = [
|
||||||
|
'action' => $action,
|
||||||
|
'arg' => $arg,
|
||||||
|
'brief' => $brief
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rankList = [];
|
||||||
|
if ($rankColumns) {
|
||||||
|
$rawRankList = $db->query('SELECT general_id, `type`, `value` FROM rank_data WHERE nation_id = %i AND `type` IN %ls', $nationID, $rankColumns);
|
||||||
|
foreach ($rawRankList as $rawRank) {
|
||||||
|
[
|
||||||
|
'general_id' => $generalID,
|
||||||
|
'type' => $type,
|
||||||
|
'value' => $value
|
||||||
|
] = $rawRank;
|
||||||
|
|
||||||
|
if (!key_exists($generalID, $rankList)) {
|
||||||
|
$rankList[$generalID] = [];
|
||||||
|
}
|
||||||
|
$rankList[$generalID][$type] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$getRankVar = fn ($key) => (fn ($rawGeneral) => (($rankList[$rawGeneral['no']] ?? [])[$key] ?? 0));
|
||||||
|
|
||||||
|
$specialViewFilter = [
|
||||||
|
'officerLevel' => fn ($rawGeneral) => $this->getOfficerLevel($rawGeneral),
|
||||||
|
'officerLevelText' => fn ($rawGeneral) => getOfficerLevelText($this->getOfficerLevel($rawGeneral), $nationArr['level']),
|
||||||
|
'lbonus' => fn ($rawGeneral) => calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']),
|
||||||
|
'ownerName' => fn ($rawGeneral) => ($rawGeneral['npc'] != 1) ? null : $rawGeneral['owner_name'],
|
||||||
|
'honorText' => fn ($rawGeneral) => getHonor($rawGeneral['experience']),
|
||||||
|
'dedLevelText' => fn ($rawGeneral) => getDedLevelText($rawGeneral['dedlevel']),
|
||||||
|
//'0000-00-00 11:23';
|
||||||
|
'turntime' => fn ($rawGeneral) => substr($rawGeneral['turntime'], 0, 19),
|
||||||
|
'recent_war' => fn ($rawGeneral) => substr($rawGeneral['recent_war'], 0, 19),
|
||||||
|
'bill' => fn ($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']),
|
||||||
|
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
|
||||||
|
'autorun_limit' => fn ($rawGeneral) => ($rawGeneral['aux'] ?? [])['autorun_limit'] ?? 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($rankColumns as $rankKey) {
|
||||||
|
$specialViewFilter[$rankKey] = $getRankVar($rankKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$resultColumns = [];
|
||||||
|
foreach (static::$viewColumns as $column => $reqPermission) {
|
||||||
|
if ($reqPermission > $this->permission) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key_exists($column, static::$columnRemap)) {
|
||||||
|
$newColumn = static::$columnRemap[$column];
|
||||||
|
if($newColumn !== null){
|
||||||
|
$resultColumns[$newColumn] = $column;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$resultColumns[$column] = $column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (static::$customViewColumns as $column => $reqPermission) {
|
||||||
|
if ($reqPermission > $this->permission) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$resultColumns[$column] = $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
$generalList = [];
|
||||||
|
foreach ($rawGeneralList as $rawGeneral) {
|
||||||
|
//General 생성?
|
||||||
|
if (key_exists('aux', $rawGeneral)) {
|
||||||
|
$rawGeneral['aux'] = \sammo\JSON::decode($rawGeneral['aux']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = [];
|
||||||
|
foreach ($resultColumns as $column) {
|
||||||
|
if (key_exists($column, $specialViewFilter)) {
|
||||||
|
$value = $specialViewFilter[$column]($rawGeneral);
|
||||||
|
} else {
|
||||||
|
$value = $rawGeneral[$column];
|
||||||
|
}
|
||||||
|
$item[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$generalList[] = $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->permission >= 2){
|
||||||
|
$troops = $db->queryAllLists('SELECT troop_leader,name FROM troop WHERE nation = %i', $nationID);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$troops = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'result' => true,
|
||||||
|
'permission' => $this->permission,
|
||||||
|
'column' => array_keys($resultColumns),
|
||||||
|
'list' => $generalList,
|
||||||
|
'troops' => $troops,
|
||||||
|
'env' => $env,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
@import '@scss/common/bootstrap5.scss';
|
||||||
|
@import "@scss/game_bg.scss";
|
||||||
|
@import "@scss/util.scss";
|
||||||
|
|
||||||
|
#container{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@include media-1000px {
|
||||||
|
#container {
|
||||||
|
width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-500px {
|
||||||
|
#container {
|
||||||
|
position: relative;
|
||||||
|
width: 500px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<?=$btnBegin??''?><a href='b_tournament.php' target='_blank' class='open-window <?=$btnClassForTournament??""?>'>토 너 먼 트</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_tournament.php' target='_blank' class='open-window <?=$btnClassForTournament??""?>'>토 너 먼 트</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_myKingdomInfo.php' class='commandButton <?=$btnClass??""?> <?= $meLevel >= 1 ? '' : 'disabled' ?>'>세력 정보</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_myKingdomInfo.php' class='commandButton <?=$btnClass??""?> <?= $meLevel >= 1 ? '' : 'disabled' ?>'>세력 정보</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_myCityInfo.php' class='commandButton <?=$btnClass??""?> <?= ($meLevel >= 1 && $nationLevel >= 1) ? '' : 'disabled' ?>'>세력 도시</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_myCityInfo.php' class='commandButton <?=$btnClass??""?> <?= ($meLevel >= 1 && $nationLevel >= 1) ? '' : 'disabled' ?>'>세력 도시</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href='b_myGenInfo.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='b_diplomacy.php' class='commandButton <?=$btnClass??""?>'>중원 정보</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href='b_diplomacy.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='b_battleCenter.php' target='_blank' class='open-window commandButton <?=$btnClass??""?> <?= $showSecret ? '' : 'disabled' ?>'>감 찰 부</a><?=$btnEnd??''?>
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<template>
|
||||||
|
<BContainer id="container" :toast="{ root: true }" class="pageNationGeneral bg0">
|
||||||
|
<TopBackBar :title="title" :reloadable="true" @reload="reload" :teleport-zone="toolbarID" />
|
||||||
|
<!-- eslint-disable-next-line vue/max-attributes-per-line -->
|
||||||
|
<GeneralList
|
||||||
|
v-if="asyncReady"
|
||||||
|
:list="generalList"
|
||||||
|
:troops="troopList"
|
||||||
|
:env="envVal"
|
||||||
|
:toolbarID="toolbarID"
|
||||||
|
role="pageNationGeneral"
|
||||||
|
:height="'fill'"
|
||||||
|
:availableGeneralClick="true"
|
||||||
|
@generalClick="openBattleCenter"
|
||||||
|
/>
|
||||||
|
<!--<BottomBar />-->
|
||||||
|
</BContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
/*declare const staticValues: {
|
||||||
|
serverNick: string,
|
||||||
|
mapName: string,
|
||||||
|
unitSet: string,
|
||||||
|
};*/
|
||||||
|
</script>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import TopBackBar from "@/components/TopBackBar.vue";
|
||||||
|
//import BottomBar from "@/components/BottomBar.vue";
|
||||||
|
import { BContainer } from "bootstrap-vue-3";
|
||||||
|
import { onMounted, provide, ref } from "vue";
|
||||||
|
import { SammoAPI } from "./SammoAPI";
|
||||||
|
import { merge2DArrToObjectArr } from "./util/merge2DArrToObjectArr";
|
||||||
|
import type { GeneralListItem, GeneralListResponse } from "./defs/API/Nation";
|
||||||
|
import GeneralList from "./components/GeneralList.vue";
|
||||||
|
import { type GameConstStore, getGameConstStore } from "./GameConstStore";
|
||||||
|
|
||||||
|
const generalList = ref<GeneralListItem[]>([]);
|
||||||
|
const troopList = ref<Record<number, string>>({});
|
||||||
|
const envVal = ref<GeneralListResponse["env"]>({
|
||||||
|
year: 1,
|
||||||
|
month: 1,
|
||||||
|
turnterm: 1,
|
||||||
|
turntime: "2022-02-22 22:22:22.22222",
|
||||||
|
killturn: 80,
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolbarID = "toolbar-id";
|
||||||
|
|
||||||
|
const gameConstStore = ref<GameConstStore>();
|
||||||
|
provide("gameConstStore", gameConstStore);
|
||||||
|
|
||||||
|
const asyncReady = ref(false);
|
||||||
|
|
||||||
|
const title = "세력 장수";
|
||||||
|
|
||||||
|
const storeP = getGameConstStore().then((store) => {
|
||||||
|
gameConstStore.value = store;
|
||||||
|
});
|
||||||
|
|
||||||
|
void Promise.all([storeP]).then(() => {
|
||||||
|
asyncReady.value = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function reload() {
|
||||||
|
try {
|
||||||
|
const { column, list, permission, troops, env } = await SammoAPI.Nation.GeneralList();
|
||||||
|
troopList.value = {};
|
||||||
|
//XXX: 로직상 똑같은데....
|
||||||
|
if (permission == 0) {
|
||||||
|
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||||
|
generalList.value = rawGeneralList.map((v) => {
|
||||||
|
return { permission, st0: true, st1: false, st2: false, ...v };
|
||||||
|
});
|
||||||
|
} else if (permission == 1) {
|
||||||
|
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||||
|
generalList.value = rawGeneralList.map((v) => {
|
||||||
|
return { permission, st0: true, st1: true, st2: false, ...v };
|
||||||
|
});
|
||||||
|
} else if ([2, 3, 4].includes(permission)) {
|
||||||
|
const rawGeneralList = merge2DArrToObjectArr(column, list);
|
||||||
|
generalList.value = rawGeneralList.map((v) => {
|
||||||
|
return { permission, st0: true, st1: true, st2: true, ...v };
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const [troopLeader, troopName] of troops) {
|
||||||
|
troopList.value[troopLeader] = troopName;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw `?? ${permission}`;
|
||||||
|
}
|
||||||
|
envVal.value = env;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openBattleCenter(generalID: number){
|
||||||
|
window.open(`b_battleCenter.php?gen=${generalID}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await reload();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageNationGeneral {
|
||||||
|
display: grid;
|
||||||
|
//grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+6
-1
@@ -9,10 +9,11 @@ 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 } from "./defs/API/InheritAction";
|
import type { inheritBuffType } from "./defs/API/InheritAction";
|
||||||
import type { SetBlockWarResponse } from "./defs/API/Nation";
|
import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse } from "./defs/API/Nation";
|
||||||
import type { UploadImageResponse } from "./defs/API/Misc";
|
import type { UploadImageResponse } from "./defs/API/Misc";
|
||||||
import type { JoinArgs } from "./defs/API/General";
|
import type { JoinArgs } from "./defs/API/General";
|
||||||
import type { GetConstResponse } from "./defs/API/Global";
|
import type { GetConstResponse } from "./defs/API/Global";
|
||||||
|
import type { GeneralListResponse } from "./defs";
|
||||||
|
|
||||||
const apiRealPath = {
|
const apiRealPath = {
|
||||||
Betting: {
|
Betting: {
|
||||||
@@ -49,6 +50,9 @@ const apiRealPath = {
|
|||||||
Join: POST as APICallT<JoinArgs>,
|
Join: POST as APICallT<JoinArgs>,
|
||||||
},
|
},
|
||||||
Global: {
|
Global: {
|
||||||
|
GeneralList: GET as APICallT<{
|
||||||
|
with_token?: boolean
|
||||||
|
}, GeneralListResponse>,
|
||||||
GetConst: GET as APICallT<undefined, GetConstResponse>,
|
GetConst: GET as APICallT<undefined, GetConstResponse>,
|
||||||
},
|
},
|
||||||
InheritAction: {
|
InheritAction: {
|
||||||
@@ -92,6 +96,7 @@ const apiRealPath = {
|
|||||||
}[], ReserveBulkCommandResponse>,
|
}[], ReserveBulkCommandResponse>,
|
||||||
},
|
},
|
||||||
Nation: {
|
Nation: {
|
||||||
|
GeneralList: GET as APICallT<undefined, NationGeneralListResponse>,
|
||||||
SetNotice: PUT as APICallT<{
|
SetNotice: PUT as APICallT<{
|
||||||
msg: string,
|
msg: string,
|
||||||
}>,
|
}>,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"v_main": "v_main.ts",
|
"v_main": "v_main.ts",
|
||||||
"v_nationStratFinan": "v_nationStratFinan.ts",
|
"v_nationStratFinan": "v_nationStratFinan.ts",
|
||||||
"v_processing": "v_processing.ts",
|
"v_processing": "v_processing.ts",
|
||||||
"v_nationBetting": "v_nationBetting.ts"
|
"v_nationBetting": "v_nationBetting.ts",
|
||||||
|
"v_nationGeneral": "v_nationGeneral.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,1234 @@
|
|||||||
|
<template>
|
||||||
|
<Teleport v-if="toolbarID" :to="`#${toolbarID}`">
|
||||||
|
<BButtonGroup class="d-flex general-list-toolbar">
|
||||||
|
<BDropdown class="w-50" menuClass="view-mode-list" variant="primary" text="보기 모드">
|
||||||
|
<BDropdownItem @click="setDisplaySetting([true, 'normal'], defaultDisplaySetting.normal)">기본</BDropdownItem>
|
||||||
|
<BDropdownItem @click="setDisplaySetting([true, 'war'], defaultDisplaySetting.war)">전투</BDropdownItem>
|
||||||
|
<BDropdownDivider />
|
||||||
|
<BDropdownItem @click="storeDisplaySetting"><i class="bi bi-bookmark-plus-fill" /> 보관하기</BDropdownItem>
|
||||||
|
<BDropdownDivider />
|
||||||
|
<BDropdownItem
|
||||||
|
v-for="[key, setting] of displaySettings.entries()"
|
||||||
|
:key="key"
|
||||||
|
@click="setDisplaySetting([false, key], setting)"
|
||||||
|
><div class="row gx-0">
|
||||||
|
<div class="col-9 text-wrap">
|
||||||
|
<span class="align-middle">{{ key }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="d-grid"><BButton size="sm" @click="deleteDisplaySetting(key)">삭제</BButton></div>
|
||||||
|
</div>
|
||||||
|
</div></BDropdownItem
|
||||||
|
>
|
||||||
|
</BDropdown>
|
||||||
|
<BDropdown class="w-50" variant="info" text="열 선택" menuClass="column-menu" right>
|
||||||
|
<template v-for="[colID, col, depth] of getColumnList()" :key="[colID, depth]">
|
||||||
|
<BDropdownItem v-if="col instanceof ProvidedColumnGroup" disabled>
|
||||||
|
<span :style="{ marginLeft: depth ? `${12 * depth}px` : undefined }">
|
||||||
|
{{ col.getColGroupDef()?.headerName }}</span
|
||||||
|
></BDropdownItem
|
||||||
|
>
|
||||||
|
<BDropdownItem v-else>
|
||||||
|
<div :style="{ marginLeft: depth ? `${12 * depth}px` : undefined }" class="form-check" @click.stop="1">
|
||||||
|
<input
|
||||||
|
:id="`column-type-${colID}`"
|
||||||
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
:checked="col.isVisible()"
|
||||||
|
@change.stop="toggleColumn(colID, col)"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
class="form-check-label"
|
||||||
|
:for="`column-type-${colID}`"
|
||||||
|
:style="{
|
||||||
|
textDecoration: validColumns.has(colID) ? undefined : 'line-through',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ col.getColDef().headerName }}
|
||||||
|
</label>
|
||||||
|
</div></BDropdownItem
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<BDropdownDivider />
|
||||||
|
</BDropdown>
|
||||||
|
</BButtonGroup>
|
||||||
|
</Teleport>
|
||||||
|
<div
|
||||||
|
class="component-general-list"
|
||||||
|
:style="{
|
||||||
|
height: props.height === 'fill' ? '100%' : props.height === 'static' ? undefined : `${props.height}px`,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<AgGridVue
|
||||||
|
style="width: 100%; height: 100%"
|
||||||
|
class="ag-theme-balham-dark"
|
||||||
|
:getRowId="getRowId"
|
||||||
|
:getRowHeight="getRowHeight"
|
||||||
|
:columnDefs="columnDefs"
|
||||||
|
:rowData="list"
|
||||||
|
:defaultColDef="defaultColDef"
|
||||||
|
:suppressColumnMoveAnimation="suppressColumnMoveAnimation"
|
||||||
|
@grid-ready="onGridReady"
|
||||||
|
@cell-clicked="onCellClicked"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts"></script>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { GeneralListItem, GeneralListItemP2, GeneralListResponse } from "@/defs/API/Nation";
|
||||||
|
import { getIconPath } from "@/util/getIconPath";
|
||||||
|
import { inject, ref, watch, type PropType, type Ref, type StyleValue } from "vue";
|
||||||
|
import { AgGridVue } from "ag-grid-vue3";
|
||||||
|
import type {
|
||||||
|
Column,
|
||||||
|
CellClassParams,
|
||||||
|
CellStyle,
|
||||||
|
ColDef,
|
||||||
|
ColGroupDef,
|
||||||
|
ColumnApi,
|
||||||
|
GetRowIdParams,
|
||||||
|
GridApi,
|
||||||
|
GridReadyEvent,
|
||||||
|
RowNode,
|
||||||
|
CellClickedEvent,
|
||||||
|
} from "ag-grid-community";
|
||||||
|
import { ProvidedColumnGroup } from "ag-grid-community";
|
||||||
|
import { getNpcColor } from "@/common_legacy";
|
||||||
|
import type { BaseWithValueColDefParams, ValueGetterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
||||||
|
import type { GameConstStore } from "@/GameConstStore";
|
||||||
|
import { unwrap } from "@/util/unwrap";
|
||||||
|
import SimpleTooltipCell from "@/gridCellRenderer/SimpleTooltipCell.vue";
|
||||||
|
import GridTooltipCell, { type GridCellInfo } from "@/gridCellRenderer/GridTooltipCell.vue";
|
||||||
|
import { formatConnectScore } from "@/utilGame/formatConnectScore";
|
||||||
|
import { convertSearch초성 } from "@/util/convertSearch초성";
|
||||||
|
import { isString } from "lodash";
|
||||||
|
import { formatDefenceTrain } from "@/utilGame/formatDefenceTrain";
|
||||||
|
import { BDropdownItem, BDropdownDivider, BButtonGroup, BDropdown, BButton } from "bootstrap-vue-3";
|
||||||
|
import { unwrap_err } from "@/util/unwrap_err";
|
||||||
|
import { RuntimeError } from "@/util/RuntimeError";
|
||||||
|
import { defaultDisplaySetting, type GridDisplaySetting } from "@/defs/gridDefs";
|
||||||
|
const props = defineProps({
|
||||||
|
list: {
|
||||||
|
type: Array as PropType<GeneralListItem[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
troops: {
|
||||||
|
type: Object as PropType<Record<number, string>>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String as PropType<"static" | "fill" | number | `${number}px` | `${number}%`>,
|
||||||
|
required: false,
|
||||||
|
default: "static",
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
type: Object as PropType<GeneralListResponse["env"]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
toolbarID: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: "generic",
|
||||||
|
},
|
||||||
|
availableGeneralClick: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "generalClick", generalID: number): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const suppressColumnMoveAnimation = ref(true);
|
||||||
|
const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
|
||||||
|
|
||||||
|
const validColumns = ref(new Set<string>());
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.list,
|
||||||
|
(newValue) => {
|
||||||
|
const newValidColumns = new Set<string>(["icon"]);
|
||||||
|
if (newValue.length > 0) {
|
||||||
|
for (const key of Object.keys(newValue[0])) {
|
||||||
|
newValidColumns.add(key);
|
||||||
|
}
|
||||||
|
validColumns.value = newValidColumns;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
gridApi.value?.redrawRows();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => props.height,
|
||||||
|
(val) => {
|
||||||
|
if (val === "static") {
|
||||||
|
gridApi.value?.setDomLayout("autoHeight");
|
||||||
|
} else {
|
||||||
|
gridApi.value?.setDomLayout("normal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const generalByID = ref(new Map<number, GeneralListItem>());
|
||||||
|
function refineGeneralList(list: GeneralListItem[]) {
|
||||||
|
const map = new Map<number, GeneralListItem>();
|
||||||
|
for (const general of list) {
|
||||||
|
map.set(general.no, general);
|
||||||
|
}
|
||||||
|
generalByID.value = map;
|
||||||
|
}
|
||||||
|
refineGeneralList(props.list);
|
||||||
|
watch(() => props.list, refineGeneralList);
|
||||||
|
const gridApi = ref<GridApi>();
|
||||||
|
const columnApi = ref<ColumnApi>();
|
||||||
|
const rowHeight = ref(68);
|
||||||
|
function getRowId(params: GetRowIdParams): string {
|
||||||
|
const genID = (params.data as GeneralListItem).no;
|
||||||
|
return `${genID}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDisplaySetting(settingKey: SettingKeyType, setting: GridDisplaySetting) {
|
||||||
|
if (!columnApi.value) {
|
||||||
|
console.error("nyc?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
columnApi.value.applyColumnState({ state: setting.column, applyOrder: true });
|
||||||
|
columnApi.value.setColumnGroupState(setting.columnGroup);
|
||||||
|
currentSetting.value = settingKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const displaySettings = ref(new Map<string, GridDisplaySetting>());
|
||||||
|
const displaySettingVersion = 1; //추가되는 걸로 버전 올리지 말고, 사용할 수 없게 될때만 올리기
|
||||||
|
const displaySettingsKey = "GeneralListDisplaySetting";
|
||||||
|
|
||||||
|
function getLastUsedSettingsKey() {
|
||||||
|
const lastUsedSettingsKey = "LastUsedSettingsKey";
|
||||||
|
return `${lastUsedSettingsKey}_${props.role}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadDisplaySetting() {
|
||||||
|
const rawSettings = localStorage.getItem(displaySettingsKey);
|
||||||
|
if (!rawSettings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const settings: { version: number; settings: [string, GridDisplaySetting][] } = JSON.parse(rawSettings);
|
||||||
|
if (settings.version != displaySettingVersion) {
|
||||||
|
localStorage.removeItem(displaySettingsKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
displaySettings.value = new Map(settings.settings);
|
||||||
|
}
|
||||||
|
loadDisplaySetting();
|
||||||
|
|
||||||
|
type SettingKeyType = [true, keyof typeof defaultDisplaySetting] | [false, string];
|
||||||
|
const currentSetting = ref<SettingKeyType>([true, "normal"]);
|
||||||
|
function loadLastUsedSettings() {
|
||||||
|
const rawLastSettingKey = localStorage.getItem(getLastUsedSettingsKey());
|
||||||
|
if (!rawLastSettingKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const settingKey: SettingKeyType = JSON.parse(rawLastSettingKey);
|
||||||
|
const [isDefault, settingKeyName] = settingKey;
|
||||||
|
if (isDefault) {
|
||||||
|
if (!(settingKeyName in defaultDisplaySetting)) {
|
||||||
|
console.error(`${settingKeyName}은 이제 기본 지원 타입이 아닙니다.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!displaySettings.value.has(settingKeyName)) {
|
||||||
|
console.error(`${settingKeyName}는 저장되어있지 않습니다.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSetting.value = settingKey;
|
||||||
|
return settingKey;
|
||||||
|
}
|
||||||
|
watch(currentSetting, (newTypeKey) => {
|
||||||
|
localStorage.setItem(getLastUsedSettingsKey(), JSON.stringify(newTypeKey));
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
displaySettings,
|
||||||
|
(newSettings) => {
|
||||||
|
const settings = Array.from(newSettings.entries());
|
||||||
|
localStorage.setItem(
|
||||||
|
displaySettingsKey,
|
||||||
|
JSON.stringify({
|
||||||
|
version: displaySettingVersion,
|
||||||
|
settings,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
console.log("저장!", Array.from(newSettings.keys()));
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
function deleteDisplaySetting(key: string) {
|
||||||
|
if (!confirm(`${key} 설정을 지울까요?`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
displaySettings.value.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeDisplaySetting() {
|
||||||
|
if (!columnApi.value) {
|
||||||
|
console.error("nyc?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nickName = prompt("선택한 설정의 별명을 지어주세요", currentSetting.value[0] ? "" : currentSetting.value[1]);
|
||||||
|
if (!nickName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displaySettings.value.has(nickName)) {
|
||||||
|
if (!confirm("이미 있는 이름입니다. 덮어쓸까요?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setting: GridDisplaySetting = {
|
||||||
|
column: columnApi.value.getColumnState(),
|
||||||
|
columnGroup: columnApi.value.getColumnGroupState(),
|
||||||
|
};
|
||||||
|
|
||||||
|
displaySettings.value.set(nickName, setting);
|
||||||
|
currentSetting.value = [false, nickName];
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridReady(params: GridReadyEvent) {
|
||||||
|
gridApi.value = params.api;
|
||||||
|
columnApi.value = params.columnApi;
|
||||||
|
if (props.height === "static") {
|
||||||
|
params.api.setDomLayout("autoHeight");
|
||||||
|
} else {
|
||||||
|
params.api.setDomLayout("normal");
|
||||||
|
}
|
||||||
|
loadLastUsedSettings();
|
||||||
|
if (currentSetting.value[0]) {
|
||||||
|
setDisplaySetting(currentSetting.value, defaultDisplaySetting[currentSetting.value[1]]);
|
||||||
|
} else {
|
||||||
|
setDisplaySetting(currentSetting.value, unwrap(displaySettings.value.get(currentSetting.value[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
suppressColumnMoveAnimation.value = false;
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCellClicked(event: CellClickedEvent) {
|
||||||
|
const colID = event.column.getColId();
|
||||||
|
if (colID === "icon" || colID === "name") {
|
||||||
|
const generalItem = event.data as GeneralListItem;
|
||||||
|
emit("generalClick", generalItem.no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRowHeight(): number {
|
||||||
|
return rowHeight.value;
|
||||||
|
}
|
||||||
|
type headerType =
|
||||||
|
| keyof Omit<GeneralListItemP2, "no" | "imgsvr" | "picture" | "lbonus" | "permission" | "st0" | "st1" | "st2">
|
||||||
|
| "stat"
|
||||||
|
| "icon"
|
||||||
|
| "goldRice"
|
||||||
|
| "expDedLv"
|
||||||
|
| "crewtypeAndCrew"
|
||||||
|
| "trainAtmos"
|
||||||
|
| "specials"
|
||||||
|
| "reservedCommandShort"
|
||||||
|
| "killturnAndConnect"
|
||||||
|
| "years"
|
||||||
|
| "warResults";
|
||||||
|
interface GenValueParams extends BaseWithValueColDefParams {
|
||||||
|
data: GeneralListItem;
|
||||||
|
}
|
||||||
|
interface GenValueGetterParams extends ValueGetterParams {
|
||||||
|
data: GeneralListItem;
|
||||||
|
}
|
||||||
|
interface GenRowNode extends RowNode {
|
||||||
|
data: GeneralListItem;
|
||||||
|
}
|
||||||
|
interface GenColDef extends ColDef {
|
||||||
|
colId: headerType;
|
||||||
|
field?: headerType;
|
||||||
|
headerName: string;
|
||||||
|
valueFormatter?: string | ((params: GenValueParams) => string);
|
||||||
|
filterValueGetter?: string | ((params: GenValueGetterParams) => unknown);
|
||||||
|
valueGetter?: string | ((params: GenValueGetterParams) => unknown);
|
||||||
|
}
|
||||||
|
interface GenColGroupDef extends ColGroupDef {
|
||||||
|
headerName: string;
|
||||||
|
children: GenColDef[]; //1단만 할꺼다!
|
||||||
|
groupId: headerType;
|
||||||
|
}
|
||||||
|
interface GenCellClassParams extends CellClassParams {
|
||||||
|
data: GeneralListItem;
|
||||||
|
}
|
||||||
|
function getColumnList(): [headerType, ProvidedColumnGroup | Column, number?][] {
|
||||||
|
const result: [headerType, ProvidedColumnGroup | Column, number?][] = [];
|
||||||
|
if (!columnApi.value) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (const [rawColKey, rawColDef] of Object.entries(columnRawDefs.value)) {
|
||||||
|
if (rawColKey === "name") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!("children" in rawColDef)) {
|
||||||
|
const col = unwrap_err(columnApi.value.getColumn(rawColDef.colId), RuntimeError, `no col: ${rawColDef.colId}`);
|
||||||
|
result.push([rawColDef.colId, col]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const colGroup = unwrap_err(
|
||||||
|
columnApi.value.getProvidedColumnGroup(rawColDef.groupId),
|
||||||
|
RuntimeError,
|
||||||
|
`no colGroup: ${rawColDef.groupId}`
|
||||||
|
);
|
||||||
|
result.push([rawColDef.groupId, colGroup]);
|
||||||
|
for (const subColDef of rawColDef.children) {
|
||||||
|
const subColId = subColDef.colId;
|
||||||
|
if (rawColDef.groupId == subColId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const col = unwrap_err(columnApi.value.getColumn(subColId), RuntimeError, `no subCol: ${subColDef.colId}`);
|
||||||
|
result.push([subColId, col, 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function naiveCheClassNameFilter(value: string): string {
|
||||||
|
if (!value) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
const text = value.split("_").pop() ?? "None";
|
||||||
|
if (text === "None") {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
function numberFormatter(unit?: string) {
|
||||||
|
if (unit) {
|
||||||
|
return (value: GenValueParams): string => {
|
||||||
|
if (value.value == null) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const valueText = (value.value as number).toLocaleString();
|
||||||
|
return `${valueText} ${unit}`;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (value: GenValueParams): string => {
|
||||||
|
return (value.value as number).toLocaleString();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function extractTroopInfo(value: GeneralListItem): [string, GeneralListItemP2] | undefined {
|
||||||
|
if (!value.st2) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const troopID = value.troop;
|
||||||
|
if (!(troopID in props.troops)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const troopName = props.troops[troopID];
|
||||||
|
const troopLeader = generalByID.value.get(troopID) as GeneralListItemP2 | undefined;
|
||||||
|
if (troopLeader === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return [troopName, troopLeader];
|
||||||
|
}
|
||||||
|
function toggleColumn(colID: headerType, col: Column) {
|
||||||
|
const newState = !col.isVisible();
|
||||||
|
const target: string[] = [colID];
|
||||||
|
const parent = col.getParent();
|
||||||
|
if (newState) {
|
||||||
|
for (const child of (parent.getChildren() ?? []) as Column[]) {
|
||||||
|
if (parent.getGroupId() == child.getColDef().colId) {
|
||||||
|
target.push(child.getColId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let stillVisible = false;
|
||||||
|
let header: string | null = null;
|
||||||
|
for (const child of (parent.getChildren() ?? []) as Column[]) {
|
||||||
|
if (child.getColId() == colID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parent.getGroupId() == child.getColDef().colId) {
|
||||||
|
header = child.getColId();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stillVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!stillVisible && header) {
|
||||||
|
target.push(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
columnApi.value?.setColumnsVisible(target, newState);
|
||||||
|
}
|
||||||
|
const defaultCellClass = ["cell-middle"];
|
||||||
|
const centerCellClass = [...defaultCellClass, "cell-center"];
|
||||||
|
const rightAlignClass = [...defaultCellClass, "cell-right"];
|
||||||
|
const sortableNumber: Omit<GenColDef, "colId" | "headerName"> = {
|
||||||
|
sortable: true,
|
||||||
|
comparator: (a, b) => a - b,
|
||||||
|
sortingOrder: ["desc", "asc", null],
|
||||||
|
filter: "number",
|
||||||
|
cellClass: rightAlignClass,
|
||||||
|
};
|
||||||
|
const defaultColDef = ref<ColDef>({
|
||||||
|
resizable: true,
|
||||||
|
headerClass: "default-cell-header",
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
floatingFilter: true,
|
||||||
|
width: 80,
|
||||||
|
});
|
||||||
|
const columnRawDefs = ref<Partial<Record<headerType, GenColDef | GenColGroupDef>>>({
|
||||||
|
icon: {
|
||||||
|
colId: "icon",
|
||||||
|
headerName: "아이콘",
|
||||||
|
width: 64 + 16,
|
||||||
|
suppressSizeToFit: true,
|
||||||
|
resizable: false,
|
||||||
|
cellRenderer: (obj: GenValueParams) => {
|
||||||
|
const { data: gen } = obj;
|
||||||
|
return `<img src="${getIconPath(gen.imgsvr, gen.picture)}" width="64">`;
|
||||||
|
},
|
||||||
|
pinned: "left",
|
||||||
|
cellClass: [props.availableGeneralClick ? "clickable-cell" : "", ...defaultCellClass],
|
||||||
|
lockPosition: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
headerName: "장수명",
|
||||||
|
colId: "name",
|
||||||
|
field: "name",
|
||||||
|
pinned: "left",
|
||||||
|
sortable: true,
|
||||||
|
width: 120,
|
||||||
|
sortingOrder: ["asc", "desc", null],
|
||||||
|
lockPosition: true,
|
||||||
|
cellStyle: (val: GenCellClassParams) => {
|
||||||
|
const gen = val.data;
|
||||||
|
const style: StyleValue = {
|
||||||
|
color: getNpcColor(gen.npc),
|
||||||
|
};
|
||||||
|
return style as CellStyle;
|
||||||
|
},
|
||||||
|
filterValueGetter: ({ data }) => convertSearch초성(data.name),
|
||||||
|
cellClass: [props.availableGeneralClick ? "clickable-cell" : "", ...defaultCellClass],
|
||||||
|
filter: true,
|
||||||
|
hide: false,
|
||||||
|
lockVisible: true,
|
||||||
|
},
|
||||||
|
//npc: { headerName: "NPC", colId: "npc", field: "npc" },
|
||||||
|
stat: {
|
||||||
|
groupId: "stat",
|
||||||
|
openByDefault: false,
|
||||||
|
headerName: "능력치",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "stat",
|
||||||
|
headerName: "통|무|지",
|
||||||
|
width: 88,
|
||||||
|
cellRenderer: (obj: GenValueParams) => {
|
||||||
|
const gen = obj.data;
|
||||||
|
return `${gen.leadership}|${gen.strength}|${gen.intel}`;
|
||||||
|
},
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "leadership",
|
||||||
|
headerName: "통솔",
|
||||||
|
field: "leadership",
|
||||||
|
...sortableNumber,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
type: "numericColumn",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "strength",
|
||||||
|
headerName: "무력",
|
||||||
|
field: "strength",
|
||||||
|
...sortableNumber,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "intel",
|
||||||
|
headerName: "지력",
|
||||||
|
field: "intel",
|
||||||
|
...sortableNumber,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
officerLevel: {
|
||||||
|
headerName: "관직",
|
||||||
|
colId: "officerLevel",
|
||||||
|
field: "officerLevelText",
|
||||||
|
sortable: true,
|
||||||
|
comparator: (a, b, c, d) => c.data.officerLevel - d.data.officerLevel,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
if (data.officerLevel >= 5) {
|
||||||
|
return `<span style="color:cyan;">${data.officerLevelText}</span>`;
|
||||||
|
}
|
||||||
|
if (data.st2 && 2 <= data.officerLevel && data.officerLevel <= 4) {
|
||||||
|
const cityName = gameConstStore.value.cityConst[data.officer_city].name;
|
||||||
|
return `${cityName}<br>${data.officerLevelText}`;
|
||||||
|
}
|
||||||
|
return data.officerLevelText;
|
||||||
|
},
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
if (data.st2 && 2 <= data.officerLevel && data.officerLevel <= 4) {
|
||||||
|
const cityName = gameConstStore.value.cityConst[data.officer_city].name;
|
||||||
|
return convertSearch초성(`${cityName} ${data.officerLevelText}`);
|
||||||
|
}
|
||||||
|
return convertSearch초성(data.officerLevelText);
|
||||||
|
},
|
||||||
|
filter: true,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
width: 70,
|
||||||
|
},
|
||||||
|
expDedLv: {
|
||||||
|
headerName: "명성/계급",
|
||||||
|
groupId: "expDedLv",
|
||||||
|
width: 70,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "expDedLv",
|
||||||
|
headerName: "",
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
width: 60,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `Lv ${data.explevel}<br>${data.dedLevelText}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "explevel",
|
||||||
|
headerName: "명성",
|
||||||
|
field: "explevel",
|
||||||
|
width: 60,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `Lv ${data.explevel}<br>(${data.honorText})`;
|
||||||
|
},
|
||||||
|
...sortableNumber,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "dedlevel",
|
||||||
|
headerName: "계급",
|
||||||
|
field: "dedLevelText",
|
||||||
|
width: 70,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.dedLevelText}<br>(${data.bill.toLocaleString()})`;
|
||||||
|
},
|
||||||
|
...sortableNumber,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
goldRice: {
|
||||||
|
headerName: "자금",
|
||||||
|
groupId: "goldRice",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "goldRice",
|
||||||
|
headerName: "금/쌀",
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.gold.toLocaleString()} 금<br>${data.rice.toLocaleString()} 쌀`;
|
||||||
|
},
|
||||||
|
width: 80,
|
||||||
|
cellClass: rightAlignClass,
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
sortable: true,
|
||||||
|
sortingOrder: ["desc", "asc", null],
|
||||||
|
comparator(_a, _b, { data: lhs }: GenRowNode, { data: rhs }: GenRowNode) {
|
||||||
|
const lhsAmount = lhs.gold + lhs.rice;
|
||||||
|
const rhsAmount = rhs.gold + rhs.rice;
|
||||||
|
return lhsAmount - rhsAmount;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "gold",
|
||||||
|
headerName: "금",
|
||||||
|
field: "gold",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter("금"),
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "rice",
|
||||||
|
headerName: "쌀",
|
||||||
|
field: "rice",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter("쌀"),
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
colId: "city",
|
||||||
|
headerName: "도시",
|
||||||
|
field: "city",
|
||||||
|
valueGetter: ({ data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
return gameConstStore.value.cityConst[data.city].name;
|
||||||
|
},
|
||||||
|
filter: true,
|
||||||
|
sortable: true,
|
||||||
|
width: 60,
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return convertSearch초성(gameConstStore.value.cityConst[data.city].name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
troop: {
|
||||||
|
colId: "troop",
|
||||||
|
headerName: "부대",
|
||||||
|
field: "troop",
|
||||||
|
valueGetter: ({ data }: GenValueGetterParams) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const troopInfo = extractTroopInfo(data);
|
||||||
|
if (troopInfo === undefined) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
const [troopName, troopLeader] = troopInfo;
|
||||||
|
const cityName = gameConstStore.value.cityConst[troopLeader.city].name;
|
||||||
|
return [troopName, cityName];
|
||||||
|
},
|
||||||
|
cellRenderer: ({ value }: { value: [string, string] | string }) => {
|
||||||
|
if (isString(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const [troopName, cityName] = value;
|
||||||
|
return `${troopName}<br>[${cityName}]`;
|
||||||
|
},
|
||||||
|
width: 90,
|
||||||
|
sortable: true,
|
||||||
|
comparator: (valX, valB, { data: lhs }: GenRowNode, { data: rhs }: GenRowNode) => {
|
||||||
|
const troopInfoLhs = extractTroopInfo(lhs);
|
||||||
|
const troopInfoRhs = extractTroopInfo(rhs);
|
||||||
|
console.log(troopInfoLhs, troopInfoRhs);
|
||||||
|
if (troopInfoLhs === troopInfoRhs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (troopInfoLhs === undefined) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (troopInfoRhs === undefined) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return troopInfoLhs[0].localeCompare(troopInfoRhs[0]);
|
||||||
|
},
|
||||||
|
filter: true,
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
const troopInfo = extractTroopInfo(data);
|
||||||
|
if (troopInfo === undefined) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
const [troopName, troopLeader] = troopInfo;
|
||||||
|
const cityName = gameConstStore.value.cityConst[troopLeader.city].name;
|
||||||
|
return convertSearch초성(`${troopName}$${cityName}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
crewtypeAndCrew: {
|
||||||
|
groupId: "crewtypeAndCrew",
|
||||||
|
headerName: "보유 병력",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "crewtypeAndCrew",
|
||||||
|
headerName: "병종",
|
||||||
|
cellRenderer: GridTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
cells: ((): GridCellInfo[][] => {
|
||||||
|
return [
|
||||||
|
[{ target: "crewtype", iActionMap: gameConstStore.value.iActionInfo.crewtype }],
|
||||||
|
[{ target: "crew", converter: (value) => [`${value.crew.toLocaleString()}명`, undefined] }],
|
||||||
|
];
|
||||||
|
})(),
|
||||||
|
},
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crewtype",
|
||||||
|
headerName: "병종",
|
||||||
|
field: "crewtype",
|
||||||
|
cellRenderer: SimpleTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
iActionMap: gameConstStore.value.iActionInfo.crewtype,
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
filter: true,
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const name = gameConstStore.value.iActionInfo.crewtype[data.crewtype].name;
|
||||||
|
return convertSearch초성(name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crew",
|
||||||
|
headerName: "병력",
|
||||||
|
field: "crew",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter("명"),
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
trainAtmos: {
|
||||||
|
groupId: "trainAtmos",
|
||||||
|
headerName: "훈/사",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "trainAtmos",
|
||||||
|
headerName: "훈/사",
|
||||||
|
width: 60,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
return `${data.train}<br>${data.atmos}`;
|
||||||
|
},
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "train",
|
||||||
|
headerName: "훈련",
|
||||||
|
field: "train",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter(),
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "atmos",
|
||||||
|
headerName: "사기",
|
||||||
|
field: "atmos",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter(),
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "defence_train",
|
||||||
|
headerName: "수비",
|
||||||
|
field: "defence_train",
|
||||||
|
sortable: true,
|
||||||
|
sortingOrder: ["desc", "asc", null],
|
||||||
|
valueFormatter: ({ value }) => formatDefenceTrain(value as number),
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
specials: {
|
||||||
|
groupId: "specials",
|
||||||
|
headerName: "특성",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "specials",
|
||||||
|
headerName: "요약",
|
||||||
|
cellRenderer: GridTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
cells: ((): GridCellInfo[][] => {
|
||||||
|
return [
|
||||||
|
[{ target: "personal", iActionMap: gameConstStore.value.iActionInfo.personality }],
|
||||||
|
[
|
||||||
|
{ target: "specialDomestic", iActionMap: gameConstStore.value.iActionInfo.specialDomestic },
|
||||||
|
{ target: "specialWar", iActionMap: gameConstStore.value.iActionInfo.specialWar },
|
||||||
|
],
|
||||||
|
];
|
||||||
|
})(),
|
||||||
|
},
|
||||||
|
width: 80,
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "personal",
|
||||||
|
headerName: "성격",
|
||||||
|
field: "personal",
|
||||||
|
cellRenderer: SimpleTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
iActionMap: gameConstStore.value.iActionInfo.personality,
|
||||||
|
},
|
||||||
|
width: 60,
|
||||||
|
sortable: true,
|
||||||
|
filter: true,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
const name = gameConstStore.value.iActionInfo.personality[data.personal].name;
|
||||||
|
return convertSearch초성(name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialDomestic",
|
||||||
|
headerName: "내특",
|
||||||
|
field: "specialDomestic",
|
||||||
|
cellRenderer: SimpleTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
iActionMap: gameConstStore.value.iActionInfo.specialDomestic,
|
||||||
|
},
|
||||||
|
width: 60,
|
||||||
|
sortable: true,
|
||||||
|
filter: true,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
const name = gameConstStore.value.iActionInfo.specialDomestic[data.specialDomestic].name;
|
||||||
|
return convertSearch초성(name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialWar",
|
||||||
|
headerName: "전특",
|
||||||
|
field: "specialWar",
|
||||||
|
cellRenderer: SimpleTooltipCell,
|
||||||
|
cellRendererParams: {
|
||||||
|
iActionMap: gameConstStore.value.iActionInfo.specialWar,
|
||||||
|
},
|
||||||
|
width: 60,
|
||||||
|
sortable: true,
|
||||||
|
filter: true,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
filterValueGetter: ({ data }) => {
|
||||||
|
const name = gameConstStore.value.iActionInfo.specialWar[data.specialWar].name;
|
||||||
|
return convertSearch초성(name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
reservedCommandShort: {
|
||||||
|
groupId: "reservedCommandShort",
|
||||||
|
headerName: "명령",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "reservedCommandShort",
|
||||||
|
headerName: "단축",
|
||||||
|
width: 70,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
if (data.npc >= 2) {
|
||||||
|
return "NPC 장수";
|
||||||
|
}
|
||||||
|
if (!data.reservedCommand) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
const commandList = data.reservedCommand;
|
||||||
|
if (!commandList) {
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
return commandList
|
||||||
|
.map(({ action }) => {
|
||||||
|
if (action !== "휴식" || data.npc >= 2) {
|
||||||
|
return naiveCheClassNameFilter(action);
|
||||||
|
}
|
||||||
|
const limitMinutes = props.env.autorun_user?.limit_minutes ?? 0;
|
||||||
|
if (!limitMinutes) {
|
||||||
|
return naiveCheClassNameFilter(action);
|
||||||
|
}
|
||||||
|
if (data.killturn + limitMinutes > props.env.killturn) {
|
||||||
|
return "자율행동";
|
||||||
|
}
|
||||||
|
return naiveCheClassNameFilter(action);
|
||||||
|
})
|
||||||
|
.join("<br>");
|
||||||
|
},
|
||||||
|
cellStyle: {
|
||||||
|
lineHeight: "1em",
|
||||||
|
fontSize: "0.85em",
|
||||||
|
},
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "reservedCommand",
|
||||||
|
headerName: "전체",
|
||||||
|
width: 120,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
if (data.npc >= 2) {
|
||||||
|
return "NPC 장수";
|
||||||
|
}
|
||||||
|
const commandList = data.reservedCommand;
|
||||||
|
if (!commandList) {
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
return commandList
|
||||||
|
.map(({ action, brief }) => {
|
||||||
|
if (action !== "휴식" || data.npc >= 2) {
|
||||||
|
return brief;
|
||||||
|
}
|
||||||
|
const limitMinutes = props.env.autorun_user?.limit_minutes ?? 0;
|
||||||
|
if (!limitMinutes) {
|
||||||
|
return brief;
|
||||||
|
}
|
||||||
|
if (data.killturn + limitMinutes > props.env.killturn) {
|
||||||
|
return "자율 행동";
|
||||||
|
}
|
||||||
|
return brief;
|
||||||
|
})
|
||||||
|
.join("<br>");
|
||||||
|
},
|
||||||
|
cellStyle: {
|
||||||
|
lineHeight: "1em",
|
||||||
|
fontSize: "0.85em",
|
||||||
|
},
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
turntime: {
|
||||||
|
colId: "turntime",
|
||||||
|
headerName: "턴",
|
||||||
|
field: "turntime",
|
||||||
|
width: 60,
|
||||||
|
valueFormatter: ({ value, data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const turntime = value as string;
|
||||||
|
return turntime.substring(14, 19);
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
},
|
||||||
|
recent_war: {
|
||||||
|
colId: "recent_war",
|
||||||
|
headerName: "최근전투",
|
||||||
|
field: "recent_war",
|
||||||
|
width: 60,
|
||||||
|
valueFormatter: ({ value, data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const turntime = value as string;
|
||||||
|
return turntime.substring(14, 19);
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
},
|
||||||
|
years: {
|
||||||
|
groupId: "years",
|
||||||
|
headerName: "연도",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "years",
|
||||||
|
headerName: "요약",
|
||||||
|
width: 60,
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.age}세<br>${data.belong}년`;
|
||||||
|
},
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "age",
|
||||||
|
headerName: "연령",
|
||||||
|
field: "age",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: (v: GenValueParams) => `${v.value}세`,
|
||||||
|
width: 60,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "belong",
|
||||||
|
headerName: "사관",
|
||||||
|
field: "belong",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: (v: GenValueParams) => `${v.value}년`,
|
||||||
|
width: 60,
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
killturnAndConnect: {
|
||||||
|
groupId: "killturnAndConnect",
|
||||||
|
headerName: "기타",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "killturnAndConnect",
|
||||||
|
headerName: "삭/벌",
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.killturn.toLocaleString()}턴<br>${data.connect.toLocaleString()}점`;
|
||||||
|
},
|
||||||
|
cellClass: rightAlignClass,
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
width: 70,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killturn",
|
||||||
|
headerName: "삭턴",
|
||||||
|
field: "killturn",
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.killturn.toLocaleString()}턴`;
|
||||||
|
},
|
||||||
|
...sortableNumber,
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "connect",
|
||||||
|
headerName: "벌점",
|
||||||
|
field: "connect",
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
return `${data.connect.toLocaleString()}점<br>(${formatConnectScore(data.connect)})`;
|
||||||
|
},
|
||||||
|
...sortableNumber,
|
||||||
|
width: 70,
|
||||||
|
columnGroupShow: "open",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
warResults: {
|
||||||
|
groupId: "warResults",
|
||||||
|
headerName: "전과",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
colId: "warResults",
|
||||||
|
headerName: "요약",
|
||||||
|
cellRenderer: ({ data }: GenValueParams) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const killRatePercent = Math.round((data.killcrew / Math.max(1, data.deathcrew)) * 100);
|
||||||
|
return `${data.warnum.toLocaleString()}전 ${data.killnum.toLocaleString()}승<br>살상: ${killRatePercent}%`;
|
||||||
|
},
|
||||||
|
cellClass: centerCellClass,
|
||||||
|
columnGroupShow: "closed",
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "warnum",
|
||||||
|
headerName: "전투",
|
||||||
|
field: "warnum",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter("전"),
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killnum",
|
||||||
|
headerName: "승리",
|
||||||
|
field: "killnum",
|
||||||
|
...sortableNumber,
|
||||||
|
valueFormatter: numberFormatter("승"),
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killcrew",
|
||||||
|
headerName: "살상률",
|
||||||
|
field: "killcrew",
|
||||||
|
...sortableNumber,
|
||||||
|
valueGetter: ({ data }) => {
|
||||||
|
if (!data.st2) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
const killRatePercent = Math.round((data.killcrew / Math.max(1, data.deathcrew)) * 100);
|
||||||
|
return killRatePercent
|
||||||
|
},
|
||||||
|
valueFormatter: numberFormatter("%"),
|
||||||
|
columnGroupShow: "open",
|
||||||
|
width: 60,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const columnDefs = ref([...Object.values(columnRawDefs.value)]);
|
||||||
|
watch(columnRawDefs, (val) => {
|
||||||
|
columnDefs.value = [...Object.values(val)];
|
||||||
|
gridApi.value?.refreshCells();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.g-tr {
|
||||||
|
border-bottom: solid gray 1px;
|
||||||
|
}
|
||||||
|
.g-thead-tr {
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.view-mode-list) {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss">
|
||||||
|
.component-general-list {
|
||||||
|
.clickable-cell:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ag-root-wrapper .cell-middle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.ag-root-wrapper {
|
||||||
|
font-family: "Pretendard", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic";
|
||||||
|
font-size: 14px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.ag-root {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.ag-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.cell-center {
|
||||||
|
justify-content: space-around;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.cell-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.cell-sp .col {
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
.ag-header-cell,
|
||||||
|
.ag-header-group-cell,
|
||||||
|
.ag-cell {
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
.ag-header-cell-label,
|
||||||
|
.ag-header-group-cell-label {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.ag-ltr .ag-floating-filter-button {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
.ag-rtl .ag-floating-filter-button {
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.general-list-toolbar {
|
||||||
|
.column-menu {
|
||||||
|
column-count: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bg0 back_bar">
|
<div :class="['bg0', 'back_bar', teleportZone?'back_bar_teleport':undefined]">
|
||||||
<button type="button" class="btn btn-sammo-base2 back_btn" @click="back">돌아가기</button
|
<button type="button" class="btn btn-sammo-base2 back_btn" @click="back">돌아가기</button
|
||||||
><button v-if="reloadable" type="button" class="btn btn-sammo-base2 reload_btn" @click="reload">갱신</button>
|
><button v-if="reloadable" type="button" class="btn btn-sammo-base2 reload_btn" @click="reload">갱신</button>
|
||||||
<div v-else />
|
<div v-else />
|
||||||
<h2 class="title">
|
<h2 class="title">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</h2>
|
</h2>
|
||||||
<div> </div>
|
<div v-if="teleportZone" :id="teleportZone" class="teleport-zone"></div>
|
||||||
<b-button
|
<template v-else>
|
||||||
v-if="toggleSearch !== undefined"
|
<div> </div>
|
||||||
class="btn-toggle-zoom"
|
<b-button
|
||||||
:variant="toggleSearch ? 'info' : 'secondary'"
|
v-if="toggleSearch !== undefined"
|
||||||
:pressed="toggleSearch"
|
class="btn-toggle-zoom"
|
||||||
@click="toggleSearch = !toggleSearch"
|
:variant="toggleSearch ? 'info' : 'secondary'"
|
||||||
>
|
:pressed="toggleSearch"
|
||||||
{{ toggleSearch ? "검색 켜짐" : "검색 꺼짐" }}
|
@click="toggleSearch = !toggleSearch"
|
||||||
</b-button>
|
>
|
||||||
|
{{ toggleSearch ? "검색 켜짐" : "검색 꺼짐" }}
|
||||||
|
</b-button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -41,6 +44,11 @@ const props = defineProps({
|
|||||||
default: undefined,
|
default: undefined,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
teleportZone: {
|
||||||
|
type: String,
|
||||||
|
default: undefined,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["update:searchable", "reload"]);
|
const emit = defineEmits(["update:searchable", "reload"]);
|
||||||
@@ -72,16 +80,24 @@ function reload() {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 80px 80px 1fr 80px 80px;
|
grid-template-columns: 90px 90px 1fr 90px 90px;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 24pt;
|
height: 24pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.back_bar.back_bar_teleport {
|
||||||
|
grid-template-columns: 90px 90px 1fr 180px;
|
||||||
|
}
|
||||||
|
|
||||||
.reload_btn {
|
.reload_btn {
|
||||||
height: 24pt;
|
height: 24pt;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.teleport-zone{
|
||||||
|
height: 24pt;
|
||||||
|
}
|
||||||
|
|
||||||
.back_btn {
|
.back_btn {
|
||||||
height: 24pt;
|
height: 24pt;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
@@ -89,6 +105,7 @@ function reload() {
|
|||||||
|
|
||||||
.btn-toggle-zoom {
|
.btn-toggle-zoom {
|
||||||
height: 24pt;
|
height: 24pt;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|||||||
+115
-3
@@ -1,5 +1,117 @@
|
|||||||
import type { ValidResponse } from "@/defs";
|
import type { ValuesOf, TurnObj } from "@/defs";
|
||||||
|
import type { GameObjClassKey } from "@/defs/GameObj";
|
||||||
|
import type { ValidResponse } from "@/SammoAPI";
|
||||||
|
|
||||||
export type SetBlockWarResponse = ValidResponse & {
|
export type SetBlockWarResponse = ValidResponse & {
|
||||||
availableCnt: number;
|
availableCnt: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
officerLevel: number, //권한에따라 태수,군사,시종 노출 여부가 다름
|
||||||
|
officerLevelText: string,
|
||||||
|
lbonus: number,
|
||||||
|
ownerName: string | null, //NPC 출력용에 따라 결과가 다름
|
||||||
|
honorText: string,
|
||||||
|
dedLevelText: string,
|
||||||
|
bill: number,
|
||||||
|
reservedCommand: TurnObj[] | null,
|
||||||
|
|
||||||
|
autorun_limit: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GeneralListItemP1 = {
|
||||||
|
city: number,
|
||||||
|
experience: number,
|
||||||
|
dedication: number,
|
||||||
|
} & GeneralListItemP0;
|
||||||
|
|
||||||
|
export type GeneralListItemP2 = GeneralListItemP1 & {
|
||||||
|
officer_level: number,
|
||||||
|
officer_city: number,
|
||||||
|
defence_train: number,
|
||||||
|
troop: 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 });
|
||||||
|
|
||||||
|
type ResponseEnv = {
|
||||||
|
year: number,
|
||||||
|
month: number,
|
||||||
|
turntime: string,
|
||||||
|
turnterm: number,
|
||||||
|
killturn: number,
|
||||||
|
autorun_user?: {
|
||||||
|
limit_minutes: number,
|
||||||
|
options: Record<string, number>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RawGeneralListP0 = ValidResponse & {
|
||||||
|
permission: 0,
|
||||||
|
column: (keyof GeneralListItemP0)[],
|
||||||
|
list: ValuesOf<GeneralListItemP0>[][],
|
||||||
|
troops?: null,
|
||||||
|
env: ResponseEnv,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RawGeneralListP1 = ValidResponse & {
|
||||||
|
permission: 1,
|
||||||
|
column: (keyof GeneralListItemP1)[],
|
||||||
|
list: ValuesOf<GeneralListItemP1>[][],
|
||||||
|
troops?: null,
|
||||||
|
env: ResponseEnv,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RawGeneralListP2 = ValidResponse & {
|
||||||
|
permission: 2 | 3 | 4,
|
||||||
|
column: (keyof GeneralListItemP2)[],
|
||||||
|
list: ValuesOf<GeneralListItemP2>[][],
|
||||||
|
troops: [number, string][],
|
||||||
|
env: ResponseEnv,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2;
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ export type GameCityDefault = {
|
|||||||
path: Record<CityID, string>;
|
path: Record<CityID, string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GameIActionCategory = "nationType" | "specialDomestic" | "specialWar" | "personality" | "item";
|
export type GameIActionCategory = "nationType" | "specialDomestic" | "specialWar" | "personality" | "item" | "crewtype";
|
||||||
|
|
||||||
export type GameIActionInfo = {
|
export type GameIActionInfo = {
|
||||||
value: string;
|
value: string;
|
||||||
|
|||||||
@@ -0,0 +1,635 @@
|
|||||||
|
import type { ColumnState } from "ag-grid-community";
|
||||||
|
|
||||||
|
export type GridDisplaySetting = {
|
||||||
|
column: ColumnState[];
|
||||||
|
columnGroup: {
|
||||||
|
groupId: string;
|
||||||
|
open: boolean;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
export const defaultDisplaySetting: Record<"war" | "normal", GridDisplaySetting> = {
|
||||||
|
war: {
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
colId: "icon",
|
||||||
|
width: 80,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "name",
|
||||||
|
width: 126,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "stat_1",
|
||||||
|
width: 88,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "troop",
|
||||||
|
width: 90,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "leadership",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "strength",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "intel",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "officerLevel",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "expDedLv_1",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "explevel",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "dedlevel",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "goldRice_1",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "gold",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "rice",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "city",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crewtypeAndCrew_1",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crewtype",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crew",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "trainAtmos_1",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "train",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "atmos",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "defence_train",
|
||||||
|
width: 50,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specials_1",
|
||||||
|
width: 80,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "personal",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialDomestic",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialWar",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "reservedCommandShort_1",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "reservedCommand",
|
||||||
|
width: 120,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "turntime",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: "asc",
|
||||||
|
sortIndex: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "recent_war",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "years_1",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "age",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "belong",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killturnAndConnect_1",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killturn",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "connect",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "warResults_1",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "warnum",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killnum",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killcrew",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columnGroup: [
|
||||||
|
{
|
||||||
|
groupId: "0",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "1",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "stat",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "2",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "expDedLv",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "goldRice",
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "3",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "4",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "crewtypeAndCrew",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "trainAtmos",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "specials",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "reservedCommandShort",
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "5",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "6",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "years",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "killturnAndConnect",
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "warResults",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
normal: {
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
colId: "icon",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
pinned: "left",
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "name",
|
||||||
|
width: 126,
|
||||||
|
hide: false,
|
||||||
|
pinned: "left",
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "officerLevel",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "expDedLv_1",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "dedlevel",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "explevel",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "stat_1",
|
||||||
|
width: 88,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "leadership",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "strength",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "intel",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "troop",
|
||||||
|
width: 90,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "goldRice_1",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "gold",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "rice",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "city",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crewtypeAndCrew_1",
|
||||||
|
width: 80,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crewtype",
|
||||||
|
width: 80,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "crew",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "trainAtmos_1",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "train",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "atmos",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "defence_train",
|
||||||
|
width: 50,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specials_1",
|
||||||
|
width: 80,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "personal",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialDomestic",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "specialWar",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "reservedCommandShort_1",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "reservedCommand",
|
||||||
|
width: 120,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "turntime",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "recent_war",
|
||||||
|
width: 60,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "years_1",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "age",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "belong",
|
||||||
|
width: 60,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killturnAndConnect_1",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killturn",
|
||||||
|
width: 70,
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "connect",
|
||||||
|
width: 70,
|
||||||
|
hide: false,
|
||||||
|
sort: "desc",
|
||||||
|
sortIndex: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "warResults_1",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "warnum",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killnum",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: "killcrew",
|
||||||
|
hide: true,
|
||||||
|
sort: null,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
columnGroup: [
|
||||||
|
{
|
||||||
|
groupId: "0",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "1",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "stat",
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "2",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "expDedLv",
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "goldRice",
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "3",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "4",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "crewtypeAndCrew",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "trainAtmos",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "specials",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "reservedCommandShort",
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "5",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "6",
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "years",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "killturnAndConnect",
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: "warResults",
|
||||||
|
open: false
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
+40
-12
@@ -1,5 +1,6 @@
|
|||||||
import type { Args } from "@/processing/args";
|
import type { Args } from "@/processing/args";
|
||||||
import type { ValidResponse, InvalidResponse } from "@/util/callSammoAPI";
|
import type { ValidResponse, InvalidResponse } from "@/util/callSammoAPI";
|
||||||
|
import type { GameObjClassKey } from "./GameObj";
|
||||||
|
|
||||||
export type { ValidResponse, InvalidResponse };
|
export type { ValidResponse, InvalidResponse };
|
||||||
export type BasicGeneralListResponse = {
|
export type BasicGeneralListResponse = {
|
||||||
@@ -15,21 +16,48 @@ export type BasicGeneralListResponse = {
|
|||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type PublicGeneralItem = {
|
||||||
|
no: number,
|
||||||
|
picture: string,
|
||||||
|
imgsvr: 0 | 1,
|
||||||
|
npc: number,
|
||||||
|
age: number,
|
||||||
|
nation: string,
|
||||||
|
specialDomestic: GameObjClassKey,
|
||||||
|
specialWar: GameObjClassKey,
|
||||||
|
personal: GameObjClassKey,
|
||||||
|
name: string,
|
||||||
|
ownerName: string | null,
|
||||||
|
injury: number,
|
||||||
|
leadership: number,
|
||||||
|
lbonus: number,
|
||||||
|
strength: number,
|
||||||
|
intel: number,
|
||||||
|
explevel: number,
|
||||||
|
experienceStr: string,
|
||||||
|
dedicationStr: string,
|
||||||
|
officerLevelStr: string,
|
||||||
|
killturn: number,
|
||||||
|
connect: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type GeneralListResponse = {
|
export type GeneralListResponse = {
|
||||||
result: true,
|
result: true,
|
||||||
list: [
|
list: [
|
||||||
number,
|
PublicGeneralItem['no'],
|
||||||
string, 0 | 1,
|
PublicGeneralItem['picture'], PublicGeneralItem['imgsvr'],
|
||||||
number, number, string,
|
PublicGeneralItem['npc'], PublicGeneralItem['age'], PublicGeneralItem['nation'],
|
||||||
string, string, string,
|
PublicGeneralItem['specialDomestic'], PublicGeneralItem['specialWar'], PublicGeneralItem['personal'],
|
||||||
string, string | null,
|
PublicGeneralItem['name'], PublicGeneralItem['ownerName'],
|
||||||
number,
|
PublicGeneralItem['injury'],
|
||||||
number, number, number, number,
|
PublicGeneralItem['leadership'], PublicGeneralItem['lbonus'], PublicGeneralItem['strength'], PublicGeneralItem['intel'],
|
||||||
number,
|
PublicGeneralItem['explevel'],
|
||||||
string, string, string,
|
PublicGeneralItem['experienceStr'], PublicGeneralItem['dedicationStr'], PublicGeneralItem['officerLevelStr'],
|
||||||
number, number
|
PublicGeneralItem['killturn'], PublicGeneralItem['connect']
|
||||||
][],
|
][],
|
||||||
token: Record<number, number>,
|
token?: Record<number, number>,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
export type NationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||||
@@ -200,4 +228,4 @@ export const diplomacyStateInfo: Record<diplomacyState, diplomacyInfo> = {
|
|||||||
1: { name: '선포중', color: 'magenta' },
|
1: { name: '선포중', color: 'magenta' },
|
||||||
2: { name: '통상' },
|
2: { name: '통상' },
|
||||||
7: { name: '불가침', color: 'green' },
|
7: { name: '불가침', color: 'green' },
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-for="(rowValue, rowIdx) in props.params.cells" :key="rowIdx" class="row gx-1 m-0 cell-sp">
|
||||||
|
<template v-for="colValue of rowValue" :key="colValue.target">
|
||||||
|
<div v-if="params.data[colValue.target] == null">?</div>
|
||||||
|
<div
|
||||||
|
v-else-if="colValue.iActionMap"
|
||||||
|
v-b-tooltip.hover
|
||||||
|
class="col"
|
||||||
|
:title="colValue.iActionMap[params.data[colValue.target] as string ].info??''"
|
||||||
|
>
|
||||||
|
{{ colValue.iActionMap[params.data[colValue.target] as string ].name }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="colValue.converter"
|
||||||
|
v-b-tooltip.hover
|
||||||
|
class="col"
|
||||||
|
:title="colValue.converter(params.data)[1] ?? ''"
|
||||||
|
>
|
||||||
|
{{ colValue.converter(params.data)[0] }}
|
||||||
|
</div>
|
||||||
|
<div v-else v-b-tooltip.hover class="col" :title="colValue.info ?? ''">
|
||||||
|
{{params.data[colValue.target] as string}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { GeneralListItemP2 } from "@/defs/API/Nation";
|
||||||
|
import type { GameIActionInfo } from "@/defs/GameObj";
|
||||||
|
import type { CellClassParams } from "ag-grid-community";
|
||||||
|
|
||||||
|
//제일 큰 타입 기준
|
||||||
|
export type GridCellInfo = {
|
||||||
|
iActionMap?: Record<string, GameIActionInfo>;
|
||||||
|
info?: string;
|
||||||
|
converter?: (value: GeneralListItemP2) => [string, string?];
|
||||||
|
target: keyof GeneralListItemP2;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { PropType } from "vue";
|
||||||
|
interface GenCellClassParams extends CellClassParams {
|
||||||
|
data: GeneralListItemP2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
params: {
|
||||||
|
type: Object as PropType<
|
||||||
|
GenCellClassParams & {
|
||||||
|
cells: GridCellInfo[][];
|
||||||
|
}
|
||||||
|
>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<span v-if="props.params.value == null">?</span>
|
||||||
|
<span v-else-if="params.iActionMap" v-b-tooltip.hover :title="params.iActionMap[props.params.value].info ?? ''">{{
|
||||||
|
params.iActionMap[props.params.value].name
|
||||||
|
}}</span>
|
||||||
|
<span v-else-if="params.info" v-b-tooltip.hover :title="params.info">{{ displayValue }}</span>
|
||||||
|
<span v-else>{{ displayValue }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { GameIActionInfo } from "@/defs/GameObj";
|
||||||
|
import type { ValueFormatterParams } from "ag-grid-community";
|
||||||
|
import { isNumber, isString } from "lodash";
|
||||||
|
import { ref, watch, type PropType } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
params: {
|
||||||
|
type: Object as PropType<
|
||||||
|
ValueFormatterParams & {
|
||||||
|
info?: string;
|
||||||
|
iActionMap?: Record<string, GameIActionInfo>;
|
||||||
|
}
|
||||||
|
>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function convertValue(value: unknown): string {
|
||||||
|
if (isString(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (isNumber(value)) {
|
||||||
|
return value.toLocaleString();
|
||||||
|
}
|
||||||
|
return `${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayValue = ref<string>(convertValue(props.params.value));
|
||||||
|
watch(
|
||||||
|
() => props.params,
|
||||||
|
(newParams) => {
|
||||||
|
displayValue.value = convertValue(newParams.value);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
+28
-51
@@ -3,12 +3,14 @@ import { errUnknown } from '@/common_legacy';
|
|||||||
import { getIconPath } from "@util/getIconPath";
|
import { getIconPath } from "@util/getIconPath";
|
||||||
import { TemplateEngine } from "@util/TemplateEngine";
|
import { TemplateEngine } from "@util/TemplateEngine";
|
||||||
import { getNpcColor } from '@/common_legacy';
|
import { getNpcColor } from '@/common_legacy';
|
||||||
import type { GeneralListResponse, InvalidResponse } from '@/defs';
|
import type { GeneralListResponse, InvalidResponse, PublicGeneralItem } from '@/defs';
|
||||||
import { convertFormData } from '@util/convertFormData';
|
import { convertFormData } from '@util/convertFormData';
|
||||||
import { unwrap_any } from '@util/unwrap_any';
|
import { unwrap_any } from '@util/unwrap_any';
|
||||||
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
|
||||||
import { Tooltip } from 'bootstrap';
|
import { Tooltip } from 'bootstrap';
|
||||||
import { trim } from 'lodash';
|
import { trim } from 'lodash';
|
||||||
|
import { SammoAPI } from './SammoAPI';
|
||||||
|
import { unwrap } from './util/unwrap';
|
||||||
|
|
||||||
setAxiosXMLHttpRequest();
|
setAxiosXMLHttpRequest();
|
||||||
|
|
||||||
@@ -40,29 +42,7 @@ type NPCPick = {
|
|||||||
personalText?: string,
|
personalText?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
type NPCPickPrintableR = {
|
type NPCPickPrintableR = PublicGeneralItem & {
|
||||||
no: number,
|
|
||||||
picture: string,
|
|
||||||
imgsvr: 0 | 1,
|
|
||||||
npc: number,
|
|
||||||
age: number,
|
|
||||||
nation: string,
|
|
||||||
special: string,
|
|
||||||
special2: string,
|
|
||||||
personal: string,
|
|
||||||
name: string,
|
|
||||||
ownerName: string | null,
|
|
||||||
injury: number,
|
|
||||||
leadership: number,
|
|
||||||
lbonus: number,
|
|
||||||
strength: number,
|
|
||||||
intel: number,
|
|
||||||
explevel: number,
|
|
||||||
experience: string,
|
|
||||||
dedication: string,
|
|
||||||
officerLevel: string,
|
|
||||||
killturn: number,
|
|
||||||
connect: number,
|
|
||||||
reserved: number,
|
reserved: number,
|
||||||
|
|
||||||
userCSS?: string,
|
userCSS?: string,
|
||||||
@@ -269,8 +249,8 @@ function printGenerals(value: NPCToken) {
|
|||||||
|
|
||||||
function printGeneralList(value: GeneralListResponse) {
|
function printGeneralList(value: GeneralListResponse) {
|
||||||
console.log(value);
|
console.log(value);
|
||||||
const tokenList = value.token;
|
const tokenList = unwrap(value.token);
|
||||||
const generalList:NPCPickPrintable[] = value.list.map((rawGeneral) => {
|
const generalList: NPCPickPrintable[] = value.list.map((rawGeneral) => {
|
||||||
const general: NPCPickPrintableR = {
|
const general: NPCPickPrintableR = {
|
||||||
no: rawGeneral[0],
|
no: rawGeneral[0],
|
||||||
picture: rawGeneral[1],
|
picture: rawGeneral[1],
|
||||||
@@ -278,8 +258,8 @@ function printGeneralList(value: GeneralListResponse) {
|
|||||||
npc: rawGeneral[3],
|
npc: rawGeneral[3],
|
||||||
age: rawGeneral[4],
|
age: rawGeneral[4],
|
||||||
nation: rawGeneral[5],
|
nation: rawGeneral[5],
|
||||||
special: rawGeneral[6],
|
specialDomestic: rawGeneral[6],
|
||||||
special2: rawGeneral[7],
|
specialWar: rawGeneral[7],
|
||||||
personal: rawGeneral[8],
|
personal: rawGeneral[8],
|
||||||
name: rawGeneral[9],
|
name: rawGeneral[9],
|
||||||
ownerName: rawGeneral[10],
|
ownerName: rawGeneral[10],
|
||||||
@@ -289,9 +269,9 @@ function printGeneralList(value: GeneralListResponse) {
|
|||||||
strength: rawGeneral[14],
|
strength: rawGeneral[14],
|
||||||
intel: rawGeneral[15],
|
intel: rawGeneral[15],
|
||||||
explevel: rawGeneral[16],
|
explevel: rawGeneral[16],
|
||||||
experience: rawGeneral[17],
|
experienceStr: rawGeneral[17],
|
||||||
dedication: rawGeneral[18],
|
dedicationStr: rawGeneral[18],
|
||||||
officerLevel: rawGeneral[19],
|
officerLevelStr: rawGeneral[19],
|
||||||
killturn: rawGeneral[20],
|
killturn: rawGeneral[20],
|
||||||
connect: rawGeneral[21],
|
connect: rawGeneral[21],
|
||||||
reserved: 0
|
reserved: 0
|
||||||
@@ -317,7 +297,7 @@ function printGeneralList(value: GeneralListResponse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (general.reserved == 1) {
|
if (general.reserved == 1) {
|
||||||
general.nameAux += `<br><small>(${tokenList[general.no]}회)</small>`;
|
general.nameAux += `<br><small>(${tokenList[general.no]}회)</small>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -325,13 +305,13 @@ function printGeneralList(value: GeneralListResponse) {
|
|||||||
general.iconPath = getIconPath(general.imgsvr, general.picture);
|
general.iconPath = getIconPath(general.imgsvr, general.picture);
|
||||||
|
|
||||||
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
|
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
|
||||||
text: general.special,
|
text: general.specialDomestic,
|
||||||
info: specialInfo[general.special]
|
info: specialInfo[general.specialDomestic]
|
||||||
});
|
});
|
||||||
|
|
||||||
general.specialWarWithTooltip = TemplateEngine(templateSpecial, {
|
general.specialWarWithTooltip = TemplateEngine(templateSpecial, {
|
||||||
text: general.special2,
|
text: general.specialWar,
|
||||||
info: specialInfo[general.special2]
|
info: specialInfo[general.specialWar]
|
||||||
});
|
});
|
||||||
|
|
||||||
general.personalWithTooltip = TemplateEngine(templateSpecial, {
|
general.personalWithTooltip = TemplateEngine(templateSpecial, {
|
||||||
@@ -369,7 +349,7 @@ function printGeneralList(value: GeneralListResponse) {
|
|||||||
_printGeneralList(true);
|
_printGeneralList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _printGeneralList(clear?:boolean) {
|
function _printGeneralList(clear?: boolean) {
|
||||||
const $generalTable = $('#general_list');
|
const $generalTable = $('#general_list');
|
||||||
if (clear) {
|
if (clear) {
|
||||||
$generalTable.empty();
|
$generalTable.empty();
|
||||||
@@ -438,23 +418,20 @@ $(function ($) {
|
|||||||
}, errUnknown);
|
}, errUnknown);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#btn_load_general_list').click(function () {
|
$('#btn_load_general_list').on('click', async function () {
|
||||||
$.post({
|
try {
|
||||||
url: 'j_get_general_list.php',
|
const result = await SammoAPI.Global.GeneralList({
|
||||||
dataType: 'json',
|
with_token: true,
|
||||||
data: {
|
});
|
||||||
with_token: true
|
|
||||||
}
|
|
||||||
}).then(function (result) {
|
|
||||||
if (!result.result) {
|
|
||||||
alert(result.reason);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
printGeneralList(result);
|
printGeneralList(result);
|
||||||
}, errUnknown);
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
alert(`실패했습니다: ${e}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#btn_print_more').click(function () {
|
$('#btn_print_more').on('click', function () {
|
||||||
_printGeneralList();
|
_printGeneralList();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
import type { ValuesOf } from "@/defs";
|
||||||
|
import { zip } from "lodash";
|
||||||
|
|
||||||
|
export function merge2DArrToObjectArr<T extends Record<string, unknown>>(column: (keyof T)[], list: ValuesOf<T>[][]): T[]{
|
||||||
|
const result: T[] = [];
|
||||||
|
for(const rawItem of list){
|
||||||
|
const item: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
if(column.length != rawItem.length){
|
||||||
|
throw `column과 item의 길이가 같지 않습니다: ${column.length} != ${list.length}, ${JSON.stringify(item)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const [key, value] of zip(column, rawItem)){
|
||||||
|
item[key as string] = value;
|
||||||
|
}
|
||||||
|
result.push(item as T);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import bs from 'binary-search';
|
||||||
|
|
||||||
|
const connectMap: [number, string][] = [
|
||||||
|
[0, '안함'],
|
||||||
|
[50, '무관심'],
|
||||||
|
[100, '보통'],
|
||||||
|
[400, '가끔'],
|
||||||
|
[200, '자주'],
|
||||||
|
[800, '열심'],
|
||||||
|
[1600, '중독'],
|
||||||
|
[3200, '폐인'],
|
||||||
|
[6400, '경고'],
|
||||||
|
[12800, '헐...'],
|
||||||
|
]
|
||||||
|
|
||||||
|
export function formatConnectScore(connect: number) {
|
||||||
|
const idx = bs(connectMap, connect, ([key], needle) => key - needle);
|
||||||
|
if (idx >= 0) {
|
||||||
|
return connectMap[idx][1] ?? '?';
|
||||||
|
}
|
||||||
|
return connectMap[-(idx + 1)][1] ?? '?';
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import bs from 'binary-search';
|
||||||
|
|
||||||
|
const defenceMap: [number,string][] = [
|
||||||
|
[0, "△"],
|
||||||
|
[60, "○"],
|
||||||
|
[80, "◎"],
|
||||||
|
[90, "☆"],
|
||||||
|
[999, "×"],
|
||||||
|
]
|
||||||
|
|
||||||
|
export function formatDefenceTrain(defenceTrain: number): string {
|
||||||
|
const idx = bs(defenceMap, defenceTrain, ([defenceKey], needle) => defenceKey - needle);
|
||||||
|
if(idx >= 0){
|
||||||
|
return defenceMap[idx][1]??'?';
|
||||||
|
}
|
||||||
|
return defenceMap[-(idx + 1)][1]??'?';
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import bs from 'binary-search';
|
||||||
|
|
||||||
|
export const DexLevelMap: [number, string, string][] = [
|
||||||
|
[0, 'navy', 'F-'],
|
||||||
|
[350, 'navy', 'F'],
|
||||||
|
[1375, 'navy', 'F+'],
|
||||||
|
[3500, 'skyblue', 'E-'],
|
||||||
|
[7125, 'skyblue', 'E'],
|
||||||
|
[12650, 'skyblue', 'E+'],
|
||||||
|
[20475, 'seagreen', 'D-'],
|
||||||
|
[31000, 'seagreen', 'D'],
|
||||||
|
[44625, 'seagreen', 'D+'],
|
||||||
|
[61750, 'teal', 'C-'],
|
||||||
|
[82775, 'teal', 'C'],
|
||||||
|
[108100, 'teal', 'C+'],
|
||||||
|
[138125, 'limegreen', 'B-'],
|
||||||
|
[173250, 'limegreen', 'B'],
|
||||||
|
[213875, 'limegreen', 'B+'],
|
||||||
|
[260400, 'darkorange', 'A-'],
|
||||||
|
[313225, 'darkorange', 'A'],
|
||||||
|
[372750, 'darkorange', 'A+'],
|
||||||
|
[439375, 'tomato', 'S-'],
|
||||||
|
[513500, 'tomato', 'S'],
|
||||||
|
[595525, 'tomato', 'S+'],
|
||||||
|
[685850, 'darkviolet', 'Z-'],
|
||||||
|
[784875, 'darkviolet', 'Z'],
|
||||||
|
[893000, 'darkviolet', 'Z+'],
|
||||||
|
[1010625, 'gold', 'EX-'],
|
||||||
|
[1138150, 'gold', 'EX'],
|
||||||
|
[1275975, 'white', 'EX+'],
|
||||||
|
];
|
||||||
|
|
||||||
|
export type DexInfo = {
|
||||||
|
level: number,
|
||||||
|
name: string,
|
||||||
|
color: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDexLevel(dex: number): DexInfo {
|
||||||
|
const rawIdx = bs(DexLevelMap, dex, ([dexKey], needle) => dexKey - needle);
|
||||||
|
const level = rawIdx >= 0 ? rawIdx : -(rawIdx + 1);
|
||||||
|
|
||||||
|
const [, color, name] = DexLevelMap[level];
|
||||||
|
|
||||||
|
return {
|
||||||
|
level,
|
||||||
|
name,
|
||||||
|
color
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import bs from 'binary-search';
|
||||||
|
|
||||||
|
const hornorMap: [number, string][] = [
|
||||||
|
[0, '전무'],
|
||||||
|
[640, '무명'],
|
||||||
|
[2560, '신동'],
|
||||||
|
[5760, '약간'],
|
||||||
|
[10240, '평범'],
|
||||||
|
[16000, '지역적'],
|
||||||
|
[23040, '전국적'],
|
||||||
|
[31360, '세계적'],
|
||||||
|
[40960, '유명'],
|
||||||
|
[45000, '명사'],
|
||||||
|
[51840, '호걸'],
|
||||||
|
[55000, '효웅'],
|
||||||
|
[64000, '영웅'],
|
||||||
|
[77440, '구세주'],
|
||||||
|
]
|
||||||
|
|
||||||
|
export function formatHonor(experience: number): string {
|
||||||
|
const idx = bs(hornorMap, experience, ([experienceKey], needle) => experienceKey - needle);
|
||||||
|
if (idx >= 0) {
|
||||||
|
return hornorMap[idx][1] ?? '?';
|
||||||
|
}
|
||||||
|
return hornorMap[-(idx + 1)][1] ?? '?';
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
export const OfficerLevelMapDefault: Record<number, string> = {
|
||||||
|
12: '군주',
|
||||||
|
11: '참모',
|
||||||
|
10: '제1장군',
|
||||||
|
9: '제1모사',
|
||||||
|
8: '제2장군',
|
||||||
|
7: '제2모사',
|
||||||
|
6: '제3장군',
|
||||||
|
5: '제3모사',
|
||||||
|
4: '태수',
|
||||||
|
3: '군사',
|
||||||
|
2: '종사',
|
||||||
|
1: '일반',
|
||||||
|
0: '재야',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OfficerLevelMapByNationLevel: Record<number, Record<number, string>> = {
|
||||||
|
7: {
|
||||||
|
12: '황제',
|
||||||
|
11: '승상',
|
||||||
|
10: '표기장군',
|
||||||
|
9: '사공',
|
||||||
|
8: '거기장군',
|
||||||
|
7: '태위',
|
||||||
|
6: '위장군',
|
||||||
|
5: '사도'
|
||||||
|
},
|
||||||
|
|
||||||
|
6: {
|
||||||
|
12: '왕',
|
||||||
|
11: '광록훈',
|
||||||
|
10: '좌장군',
|
||||||
|
9: '상서령',
|
||||||
|
8: '우장군',
|
||||||
|
7: '중서령',
|
||||||
|
6: '전장군',
|
||||||
|
5: '비서령'
|
||||||
|
},
|
||||||
|
|
||||||
|
5: {
|
||||||
|
12: '공',
|
||||||
|
11: '광록대부',
|
||||||
|
10: '안국장군',
|
||||||
|
9: '집금오',
|
||||||
|
8: '파로장군',
|
||||||
|
7: '소부'
|
||||||
|
},
|
||||||
|
|
||||||
|
4: {
|
||||||
|
12: '주목',
|
||||||
|
11: '태사령',
|
||||||
|
10: '아문장군',
|
||||||
|
9: '낭중',
|
||||||
|
8: '호군',
|
||||||
|
7: '종사중랑'
|
||||||
|
},
|
||||||
|
|
||||||
|
3: {
|
||||||
|
12: '주자사',
|
||||||
|
11: '주부',
|
||||||
|
10: '편장군',
|
||||||
|
9: '간의대부'
|
||||||
|
},
|
||||||
|
|
||||||
|
2: {
|
||||||
|
12: '군벌',
|
||||||
|
11: '참모',
|
||||||
|
10: '비장군',
|
||||||
|
9: '부참모'
|
||||||
|
},
|
||||||
|
|
||||||
|
1: {
|
||||||
|
12: '영주',
|
||||||
|
11: '참모'
|
||||||
|
},
|
||||||
|
|
||||||
|
0: {
|
||||||
|
12: '두목',
|
||||||
|
11: '부두목'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
export function formatOfficerLevelText(officerLevel: number, nationLevel?: number) {
|
||||||
|
if (officerLevel < 5) {
|
||||||
|
return OfficerLevelMapDefault[officerLevel] ?? '???';
|
||||||
|
}
|
||||||
|
|
||||||
|
const nationMap = nationLevel === undefined
|
||||||
|
? OfficerLevelMapDefault
|
||||||
|
: (OfficerLevelMapByNationLevel[nationLevel] ?? OfficerLevelMapDefault);
|
||||||
|
|
||||||
|
return nationMap[officerLevel] ?? (OfficerLevelMapDefault[officerLevel] ?? '???');
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
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 { createApp } from 'vue'
|
||||||
|
import PageNationGeneral from '@/PageNationGeneral.vue';
|
||||||
|
import { BootstrapVue3, BToastPlugin } from 'bootstrap-vue-3';
|
||||||
|
import { auto500px } from './util/auto500px';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto500px();
|
||||||
|
createApp(PageNationGeneral).use(BootstrapVue3).use(BToastPlugin).mount('#app');
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?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');
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!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,
|
||||||
|
]
|
||||||
|
], 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_nationGeneral', true) ?>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Generated
+41
@@ -37,11 +37,14 @@
|
|||||||
"@typescript-eslint/parser": "^5.14.0",
|
"@typescript-eslint/parser": "^5.14.0",
|
||||||
"@vue/compiler-sfc": "^3.2.31",
|
"@vue/compiler-sfc": "^3.2.31",
|
||||||
"@vue/eslint-config-typescript": "^10.0.0",
|
"@vue/eslint-config-typescript": "^10.0.0",
|
||||||
|
"ag-grid-community": "^27.1.0",
|
||||||
|
"ag-grid-vue3": "^27.1.0",
|
||||||
"async-validator": "^4.0.7",
|
"async-validator": "^4.0.7",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-preset-modern-browsers": "^15.0.2",
|
"babel-preset-modern-browsers": "^15.0.2",
|
||||||
|
"binary-search": "^1.3.6",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
"bootstrap-vue-3": "=0.1.8",
|
"bootstrap-vue-3": "=0.1.8",
|
||||||
"bootswatch": "^5.1.3",
|
"bootswatch": "^5.1.3",
|
||||||
@@ -3066,6 +3069,20 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ag-grid-community": {
|
||||||
|
"version": "27.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-27.1.0.tgz",
|
||||||
|
"integrity": "sha512-SWzIJTNa7C6Vinizelcoc1FAJQRt1pDn+A8XHQDO2GTQT+VjBnPL8fg94fLJy0EEvqaN5IhDybNS0nD07SKIQw=="
|
||||||
|
},
|
||||||
|
"node_modules/ag-grid-vue3": {
|
||||||
|
"version": "27.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-27.1.0.tgz",
|
||||||
|
"integrity": "sha512-3kZCK4UiFc/jCGvMy7zXjNG130GLuLboqoo4jzdLnD9PNR4hzqYjKVnCFHAQVi9Zj3hRBAWDwEU18MHukZuwKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ag-grid-community": "~27.1.0",
|
||||||
|
"vue": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@@ -3437,6 +3454,11 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/binary-search": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
|
||||||
|
},
|
||||||
"node_modules/boolbase": {
|
"node_modules/boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
@@ -12796,6 +12818,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz",
|
||||||
"integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w=="
|
"integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w=="
|
||||||
},
|
},
|
||||||
|
"ag-grid-community": {
|
||||||
|
"version": "27.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-27.1.0.tgz",
|
||||||
|
"integrity": "sha512-SWzIJTNa7C6Vinizelcoc1FAJQRt1pDn+A8XHQDO2GTQT+VjBnPL8fg94fLJy0EEvqaN5IhDybNS0nD07SKIQw=="
|
||||||
|
},
|
||||||
|
"ag-grid-vue3": {
|
||||||
|
"version": "27.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-27.1.0.tgz",
|
||||||
|
"integrity": "sha512-3kZCK4UiFc/jCGvMy7zXjNG130GLuLboqoo4jzdLnD9PNR4hzqYjKVnCFHAQVi9Zj3hRBAWDwEU18MHukZuwKA==",
|
||||||
|
"requires": {
|
||||||
|
"ag-grid-community": "~27.1.0",
|
||||||
|
"vue": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@@ -13062,6 +13098,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||||
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
|
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
|
||||||
},
|
},
|
||||||
|
"binary-search": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
|
||||||
|
},
|
||||||
"boolbase": {
|
"boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
|
|||||||
@@ -50,11 +50,14 @@
|
|||||||
"@typescript-eslint/parser": "^5.14.0",
|
"@typescript-eslint/parser": "^5.14.0",
|
||||||
"@vue/compiler-sfc": "^3.2.31",
|
"@vue/compiler-sfc": "^3.2.31",
|
||||||
"@vue/eslint-config-typescript": "^10.0.0",
|
"@vue/eslint-config-typescript": "^10.0.0",
|
||||||
|
"ag-grid-community": "^27.1.0",
|
||||||
|
"ag-grid-vue3": "^27.1.0",
|
||||||
"async-validator": "^4.0.7",
|
"async-validator": "^4.0.7",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-preset-modern-browsers": "^15.0.2",
|
"babel-preset-modern-browsers": "^15.0.2",
|
||||||
|
"binary-search": "^1.3.6",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
"bootstrap-vue-3": "=0.1.8",
|
"bootstrap-vue-3": "=0.1.8",
|
||||||
"bootswatch": "^5.1.3",
|
"bootswatch": "^5.1.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user