vue: Board(WIP)

This commit is contained in:
2021-09-05 03:59:00 +09:00
parent 4efb380a61
commit 1c985e227f
12 changed files with 472 additions and 190 deletions
-134
View File
@@ -1,134 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$me = General::createGeneralObjFromDB($generalID);
$pointHelpText = [
'sum' => '다음 플레이에서 사용할 수 있는 총 포인트입니다.',
'new' => '이번 플레이에서 얻은 총 포인트입니다.',
'previous' => '이전에 물려받은 포인트입니다.',
'lived_month' => '살아남은 기간입니다. (1개월 단위)',
'max_belong' => '가장 오래 임관했던 국가의 연도입니다.',
'max_domestic_critical' => '성공한 내정 중 최대 연속값입니다.',
'snipe_combat' => '유리한 상성을 가지고 전투했습니다.',
'combat' => '전투 횟수입니다.',
'sabotage' => '계략 성공 횟수입니다.',
'unifier' => '천통에 기여한 포인트입니다. <br>각 국의 군주, 천통 수뇌, 천통 군주가 받습니다.',
'dex' => '총 숙련도합입니다.',
'tournament' => '토너먼트 입상 포인트입니다.',
'betting' => '성공적인 베팅을 했습니다. <br>수익율과 베팅 성공 횟수를 따릅니다.',
];
$items = [];
foreach(array_keys(General::INHERITANCE_KEY) as $key){
$items[$key] = $me->getInheritancePoint($key)??0;
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= UniqueConst::$serverName ?>: 유산 관리</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::preloadCSS('dist_css/inheritPoint.css') ?>
<?= WebUtil::preloadJS('dist_js/inheritPoint.js') ?>
<?= WebUtil::printCSS('../e_lib/bootstrap.min.css') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('../css/config.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
<?= WebUtil::printCSS('dist_css/inheritPoint.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('dist_js/vendors.js') ?>
<?= WebUtil::printJS('dist_js/common.js') ?>
<script>
var items = <?=Json::encode($items)?>;
var helpText = <?=Json::encode($pointHelpText)?>;
</script>
</head>
<body>
<table style='width:1000px;margin:auto;' class='tb_layout bg0'>
<tr>
<td style='text-align:left;'>유산 관리<br><?= backButton() ?></td>
</tr>
</table>
<div id="container" class="tb_layout bg0" style="width:1000px;margin:auto;border:solid 1px #888888;">
<div id='inheritance_list'>
<div id="inherit_sum" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>총 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_sum_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div id="inherit_previous" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>기존 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_previous_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div id="inherit_new" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>신규 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_new_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div style="width:100%; padding:0 10px"><hr style="border-top:1px solid #888888;"></div>
<?php foreach (General::INHERITANCE_KEY as $key => [$type, $multiplier, $name]) : ?>
<?php if ($key == 'previous') {
continue;
} ?>
<div id="inherit_<?= $key ?>" class='inherit_item inherit_template_item'>
<div class="row">
<label id="inherit_<?= $key ?>_head" class='inherit_head col-sm-6 col-form-label'><?= $name ?></label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_<?= $key ?>_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<div id="app"></div>
<?= WebUtil::printJS('dist_js/inheritPoint.js') ?>
</body>
</html>
+2 -2
View File
@@ -1,7 +1,7 @@
<div class='buttonPlate bg2'>
<div>
<a href='t_board.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>회 의 실</button></a>
<a href='t_board.php?isSecret=true'><button type="button" class='commandButton' <?=$permission>=2?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>기 밀 실</button></a>
<a href='v_board.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>회 의 실</button></a>
<a href='v_board.php?isSecret=true'><button type="button" class='commandButton' <?=$permission>=2?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>기 밀 실</button></a>
<a href='b_troop.php'><button type="button" class='commandButton' <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>부대 편성</button></a>
<a href='t_diplomacy.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>외 교 부</button></a>
<a href='b_myBossInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>인 사 부</button></a>
+200
View File
@@ -0,0 +1,200 @@
<template>
<top-back-bar :title="title" />
<table id="newArticle" class="bg0">
<thead>
<tr>
<td colspan="2" class="newArticleHeader bg2"> 게시물 작성</td>
</tr>
</thead>
<tbody>
<tr>
<th class="bg1" style="width: 66px">
<span class="articleTitle">제목</span>
</th>
<td>
<input
class="titleInput"
type="text"
maxlength="250"
placeholder="제목"
/>
</td>
</tr>
<tr>
<th class="bg1">내용</th>
<td class="boardArticle">
<textarea class="contentInput autosize" placeholder="내용"></textarea>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button type="button" id="submitArticle">등록</button>
</td>
</tr>
</tfoot>
</table>
<div id="board">
<!--<suspense>
<template #default>-->
<board-article
v-for="article in articles"
:key="article.no"
:article="article"
/>
<!--</template>
<template #fallback>
<span>불러오는 중입니다...</span>
</template>
</suspense>-->
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, reactive, toRef } from "vue";
import "../scss/bootstrap5.scss";
import "../scss/inheritPoint.scss";
import "../scss/game_bg.scss";
import TopBackBar from "./components/TopBackBar.vue";
import BoardArticle from "./components/BoardArticle.vue";
import _, { isArray } from "lodash";
import { ref } from "vue";
import axios from "axios";
import { convertFormData } from "./util/convertFormData";
import { InvalidResponse } from "./defs";
import { delay } from "./util/delay";
declare const isSecretBoard: boolean;
export type BoardResponse = {
result: true;
articles: Record<number, BoardArticleItem>;
};
export type BoardArticleItem = {
no: number;
nation_no: number;
is_secret?: boolean;
date: string;
general_no: number;
author: string;
author_icon: string;
title: string;
text: string;
comment: BoardCommentItem[];
};
export type BoardCommentItem = {
no: number;
nation_no: number;
is_secret?: boolean;
date: string;
document_no: number;
general_no: number;
author: string;
text: string;
};
export default defineComponent({
name: "Board",
components: {
TopBackBar,
BoardArticle,
},
async setup() {
let boardResponse: BoardResponse;
try {
const response = await axios({
url: "j_board_get_articles.php",
responseType: "json",
method: "post",
data: convertFormData({
isSecret: isSecretBoard,
}),
});
const result: InvalidResponse | BoardResponse = response.data;
if (!result.result) {
throw result.reason;
}
boardResponse = result;
} catch (e) {
console.error(e);
alert(`에러: ${e}`);
return;
}
//const articles = reactive();
console.log(boardResponse);
const articles:BoardResponse['articles'] = isArray(boardResponse.articles)?{}:boardResponse;
return {
title: isSecretBoard ? "기밀실" : "회의실",
articles,
};
},
});
</script>
<style>
#newArticle {
width: 1000px;
margin: 0 auto;
}
.titleInput {
width: 100%;
color: white;
background-color: transparent;
border: none;
margin: 1px 5px;
}
.contentInput {
width: 100%;
min-height: 3em;
color: white;
background-color: transparent;
border: none;
padding: 1px 5px;
}
.articleFrame {
width: 1000px;
margin: 20px auto;
}
.commentText {
width: 100%;
}
.authorName,
.comment .author {
width: 110px;
font-size: 85%;
}
.date {
width: 125px;
font-size: 85%;
}
.text {
text-align: left;
padding: 1px 5px;
}
.submitComment {
width: 100%;
}
.commentText {
color: white;
background-color: transparent;
border: none;
padding: 1px 5px;
}
</style>
+72
View File
@@ -0,0 +1,72 @@
<template>
<table class="articleFrame bg0">
<thead>
<tr class="bg1">
<th class="authorName"></th>
<th class="articleTitle"></th>
<th class="date"></th>
</tr>
</thead>
<tbody>
<tr>
<td><img class="authorIcon generalIcon" width="64" height="64" /></td>
<td class="text" colspan="2"></td>
</tr>
</tbody>
<tbody class="commentList">
<board-comment
v-for="comment in article.comment"
:key="comment.no"
:comment="comment"
/>
</tbody>
<tfoot>
<tr>
<td class="bg2 inputCommentHeader">댓글 달기</td>
<td>
<input
class="commentText"
type="text"
maxlength="250"
placeholder="새 댓글 내용"
:value="newCommentText"
/>
</td>
<td><button type="button" class="submitComment">등록</button></td>
</tr>
</tfoot>
</table>
</template>
<script lang="ts">
import { BoardArticleItem } from "board.vue";
import BoardComment from "./BoardComment.vue";
import { defineComponent, PropType } from "vue";
export default defineComponent({
name: "BoardArticle",
components: {
BoardComment,
},
data() {
return {
newCommentText: "",
};
},
props: {
article: {
type: Object as PropType<BoardArticleItem>,
required: true,
},
},
methods: {
submitComment() {
console.log(this.newCommentText);
},
},
/*
setup(props) {
toRef(props, "article");
},
*/
});
</script>
+22
View File
@@ -0,0 +1,22 @@
<template>
<tr class="comment">
<th class="author">{{ comment.author }}</th>
<td class="text">{{ comment.text }}</td>
<td class="date">{{ comment.date }}</td>
<!-- 삭제도 나중에 추가? -->
</tr>
</template>
<script lang="ts">
import { BoardCommentItem } from "board.vue";
import { defineComponent, PropType } from "vue";
export default defineComponent({
name: "BoardComment",
props: {
comment: {
type: Object as PropType<BoardCommentItem>,
required: true,
},
},
});
</script>
+51
View File
@@ -0,0 +1,51 @@
<template>
<table style="width: 1000px; margin: auto" class="tb_layout bg0">
<tr>
<td style="text-align: left">
{{title}}<br /><button
type="button"
class="btn btn-primary"
@click="back"
>돌아가기</button><br />
</td>
</tr>
</table>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import "../../scss/game_bg.scss";
export default defineComponent({
name: "TopBackBar",
methods: {
back(){
if(this.type === 'normal'){
location.href = './';
}
else if(this.type == 'chief'){
location.href = 'b_chiefcenter.php';
}
else{
//TODO: window.close하려면 부모창이 있어야함!
window.close();
}
}
},
props: {
title: {
type: String,
required: true,
},
type: {
type: String as PropType<"normal"|"chief"|"close">,
default: "normal",
required: false,
},
},
});
</script>
<style>
</style>
+6 -13
View File
@@ -2,12 +2,12 @@
import axios from 'axios';
import $ from 'jquery';
import { trim } from 'lodash';
import { escapeHtml } from "./legacy/escapeHtml";
import { nl2br } from "./util/nl2br";
import { InvalidResponse } from './defs';
import { convertFormData } from './util/convertFormData';
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
import { unwrap_any } from './util/unwrap_any';
import { escapeHtml } from "./escapeHtml";
import { nl2br } from "../util/nl2br";
import { InvalidResponse } from '../defs';
import { convertFormData } from '../util/convertFormData';
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
import { unwrap_any } from '../util/unwrap_any';
declare const isSecretBoard: boolean;
@@ -212,13 +212,6 @@ async function loadArticles() {
alert(`에러: ${e}`);
return;
}
return $.post({
url: 'j_board_get_articles.php',
dataType: 'json',
data: {
isSecret: isSecretBoard, //첫 버전이니까 전체 다 불러오자
}
});
}
function resizeTextarea($obj: JQuery<HTMLElement>) {
+7
View File
@@ -0,0 +1,7 @@
export function delay(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
}
+6
View File
@@ -0,0 +1,6 @@
import { createApp } from 'vue'
import Board from './Board.vue';
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
setAxiosXMLHttpRequest();
createApp(Board).mount('#app')
+60
View File
@@ -0,0 +1,60 @@
<?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');
$isSecretBoard = Util::getReq('isSecret', 'bool', false);
//increaseRefresh("회의실", 1);
$me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, turntime, belong, penalty FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$permission = checkSecretPermission($me);
if ($permission < 0) {
echo '국가에 소속되어있지 않습니다.';
die();
} else if ($isSecretBoard && $permission < 2) {
echo "권한이 부족합니다. 수뇌부가 아닙니다.";
die();
}
$boardName = $isSecretBoard ? '기밀실' : '회의실';
?>
<!DOCTYPE html>
<html>
<head>
<title><?= UniqueConst::$serverName ?>: <?= $boardName ?></title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('dist_css/common_vue.css') ?>
<?= ""??WebUtil::printCSS('dist_css/v_board.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('dist_js/vendors_vue.js') ?>
<?= WebUtil::printJS('dist_js/v_board.js', true) ?>
<?= WebUtil::printStaticValues([
'isSecretBoard' => $isSecretBoard,
]) ?>
</head>
<body>
<div id="app"></div>
</body>
</html>
+2 -2
View File
@@ -45,9 +45,9 @@
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./hwe/ts", /* Base directory to resolve non-absolute module names. */
//"baseUrl": "./hwe/ts", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
//"rootDirs": [] /* List of root folders whose combined content represents the structure of the project at runtime. */
"rootDirs": ["./hwe/ts"], /* List of root folders whose combined content represents the structure of the project at runtime. */
//"typeRoots": ["./typings"], /* List of folders to include type definitions from. */
//"types": ["ts/common_path.d.ts"], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+44 -39
View File
@@ -8,6 +8,7 @@ const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
module.exports = (env, argv) => {
const target = env.target ?? 'hwe';
const mode = argv.mode ?? 'production';
const tsDir = resolve(__dirname, `${target}/ts/`);
const ingame_vue = {
name: 'ingame_vue',
resolve: {
@@ -18,7 +19,9 @@ module.exports = (env, argv) => {
},
mode,
entry: {
v_inheritPoint: resolve(__dirname, `${target}/ts/v_inheritPoint.ts`)
v_inheritPoint: `${tsDir}/v_inheritPoint.ts`,
v_board: `${tsDir}/v_board.ts`
},
output: {
filename: '[name].js',
@@ -31,7 +34,16 @@ module.exports = (env, argv) => {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors_vue',
priority: -10,
chunks: 'all',
reuseExistingChunk: true,
},
default: {
name: 'common_vue',
minChunks: 2,
priority: -20,
chunks: 'all',
reuseExistingChunk: true,
},
},
}
@@ -156,37 +168,33 @@ module.exports = (env, argv) => {
name: 'ingame',
resolve: {
extensions: [".js", ".ts", ".tsx"],
alias: {
'@': resolve(__dirname, `${target}/ts`)
}
},
mode,
entry: {
chiefCenter: '@/chiefCenter.ts',
inheritPoint: '@/legacy/inheritPoint.ts',
common: '@/common_deprecated.ts',
troop: '@/troop.ts',
map: '@/map.ts',
install_db: '@/install_db.ts',
install: '@/install.ts',
battle_simulator: '@/battle_simulator.ts',
recent_map: '@/recent_map.ts',
processing: '@/processing.ts',
select_npc: '@/select_npc.ts',
betting: '@/betting.ts',
board: '@/board.ts',
bossInfo: '@/bossInfo.ts',
myPage: '@/myPage.ts',
extExpandCity: '@/extExpandCity.ts',
main: '@/main.ts',
dipcenter: '@/dipcenter.ts',
diplomacy: '@/diplomacy.ts',
currentCity: '@/currentCity.ts',
hallOfFame: '@/hallOfFame.ts',
history: '@/history.ts',
join: '@/join.ts',
select_general_from_pool: '@/select_general_from_pool.ts',
extKingdoms: '@/extKingdoms.ts',
chiefCenter: `${tsDir}/chiefCenter.ts`,
common: `${tsDir}/common_deprecated.ts`,
troop: `${tsDir}/troop.ts`,
map: `${tsDir}/map.ts`,
install_db: `${tsDir}/install_db.ts`,
install: `${tsDir}/install.ts`,
battle_simulator: `${tsDir}/battle_simulator.ts`,
recent_map: `${tsDir}/recent_map.ts`,
processing: `${tsDir}/processing.ts`,
select_npc: `${tsDir}/select_npc.ts`,
betting: `${tsDir}/betting.ts`,
board: `${tsDir}/legacy/board.ts`,
bossInfo: `${tsDir}/bossInfo.ts`,
myPage: `${tsDir}/myPage.ts`,
extExpandCity: `${tsDir}/extExpandCity.ts`,
main: `${tsDir}/main.ts`,
dipcenter: `${tsDir}/dipcenter.ts`,
diplomacy: `${tsDir}/diplomacy.ts`,
currentCity: `${tsDir}/currentCity.ts`,
hallOfFame: `${tsDir}/hallOfFame.ts`,
history: `${tsDir}/history.ts`,
join: `${tsDir}/join.ts`,
select_general_from_pool: `${tsDir}/select_general_from_pool.ts`,
extKingdoms: `${tsDir}/extKingdoms.ts`,
},
output: {
filename: '[name].js',
@@ -244,19 +252,16 @@ module.exports = (env, argv) => {
name: 'gateway',
resolve: {
extensions: [".js", ".ts", ".tsx"],
alias: {
'@': resolve(__dirname, `${target}/ts/gateway`)
}
},
mode,
entry: {
'common': '@/common_deprecated.ts',
'entrance': '@/entrance.ts',
'user_info': '@/user_info.ts',
'admin_member': '@/admin_member.ts',
'join': '@/join.ts',
'login': '@/login.ts',
'install': '@/install.ts',
common: `${tsDir}/gateway/common_deprecated.ts`,
entrance: `${tsDir}/gateway/entrance.ts`,
user_info: `${tsDir}/gateway/user_info.ts`,
admin_member: `${tsDir}/gateway/admin_member.ts`,
join: `${tsDir}/gateway/join.ts`,
login: `${tsDir}/gateway/login.ts`,
install: `${tsDir}/gateway/install.ts`,
},
output: {
filename: '[name].js',