feat: 기능 완성
This commit is contained in:
@@ -3,20 +3,28 @@
|
|||||||
<div class="col alert alert-dark m-0 p-1 center">
|
<div class="col alert alert-dark m-0 p-1 center">
|
||||||
<h4 class="m-0">명령 목록</h4>
|
<h4 class="m-0">명령 목록</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="row gx-0 commandSelectFormAnchor">
|
<div class="commandSelectFormAnchor">
|
||||||
<div class="col-3 d-grid">
|
<div v-if="isEditMode" class="row gx-0">
|
||||||
<BButton variant="primary">편집</BButton>
|
<div class="col-3 d-grid">
|
||||||
</div>
|
<BButton variant="warning" @click="isEditMode = !isEditMode">취소</BButton>
|
||||||
<div class="col-6 d-grid">
|
</div>
|
||||||
<BButton variant="light" @click="toggleForm($event)" :style="{color: 'black'}">{{ selectedCommand.simpleName }} ▾</BButton>
|
<div class="col-6 d-grid">
|
||||||
</div>
|
<BButton
|
||||||
<div class="col-3 d-grid">
|
variant="light"
|
||||||
<BButton @click="reserveCommand()" variant="primary">실행</BButton>
|
@click="toggleForm($event)"
|
||||||
|
:style="{ color: 'black' }"
|
||||||
|
>{{ selectedCommand.simpleName }} ▾</BButton>
|
||||||
|
</div>
|
||||||
|
<div class="col-3 d-grid">
|
||||||
|
<BButton @click="reserveCommand()" variant="primary">실행</BButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row gx-1">
|
<div class="row gx-1">
|
||||||
<div class="col d-grid">
|
<div class="col d-grid">
|
||||||
<BDropdown left text="턴 선택">
|
<BButton v-if="!isEditMode" variant="secondary" @click="isEditMode = !isEditMode">고급 모드</BButton>
|
||||||
|
<BDropdown v-else left text="턴 선택">
|
||||||
<BDropdownItem @click="selectTurn()">해제</BDropdownItem>
|
<BDropdownItem @click="selectTurn()">해제</BDropdownItem>
|
||||||
<BDropdownItem @click="selectAll(true)">모든턴</BDropdownItem>
|
<BDropdownItem @click="selectAll(true)">모든턴</BDropdownItem>
|
||||||
<BDropdownItem @click="selectStep(0, 2)">홀수턴</BDropdownItem>
|
<BDropdownItem @click="selectStep(0, 2)">홀수턴</BDropdownItem>
|
||||||
@@ -57,9 +65,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="commandTable">
|
<div :style="{ position: 'relative' }">
|
||||||
|
<div
|
||||||
|
class="commandQuickReserveFormAnchor bg-dark"
|
||||||
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
top: `${29.4 * currentQuickReserveTarget + 30}px`,
|
||||||
|
width: '100%',
|
||||||
|
zIndex: 9,
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div :class="{
|
||||||
|
commandTable: true,
|
||||||
|
isEditMode,
|
||||||
|
}">
|
||||||
<DragSelect
|
<DragSelect
|
||||||
:style="rowGridStyle"
|
:style="rowGridStyle"
|
||||||
|
:disabled="!isEditMode"
|
||||||
attribute="turnIdx"
|
attribute="turnIdx"
|
||||||
@dragStart="isDragToggle = true"
|
@dragStart="isDragToggle = true"
|
||||||
@dragDone="
|
@dragDone="
|
||||||
@@ -78,6 +101,7 @@ toggleTurn(...$event);
|
|||||||
class="idx_pad center d-grid"
|
class="idx_pad center d-grid"
|
||||||
>
|
>
|
||||||
<BButton
|
<BButton
|
||||||
|
v-if="isEditMode"
|
||||||
size="sm"
|
size="sm"
|
||||||
:variant="
|
:variant="
|
||||||
(isDragToggle && selected.has(`${turnIdx}`)) ? 'light' :
|
(isDragToggle && selected.has(`${turnIdx}`)) ? 'light' :
|
||||||
@@ -88,11 +112,13 @@ toggleTurn(...$event);
|
|||||||
: 'primary'
|
: 'primary'
|
||||||
"
|
"
|
||||||
>{{ turnIdx + 1 }}</BButton>
|
>{{ turnIdx + 1 }}</BButton>
|
||||||
|
<div v-else class="plain-center">{{ turnIdx + 1 }}</div>
|
||||||
</div>
|
</div>
|
||||||
</DragSelect>
|
</DragSelect>
|
||||||
<DragSelect
|
<DragSelect
|
||||||
:style="rowGridStyle"
|
:style="rowGridStyle"
|
||||||
attribute="turnIdx"
|
attribute="turnIdx"
|
||||||
|
:disabled="!isEditMode"
|
||||||
@dragStart="isDragSingle = true"
|
@dragStart="isDragSingle = true"
|
||||||
@dragDone="
|
@dragDone="
|
||||||
isDragSingle = false;
|
isDragSingle = false;
|
||||||
@@ -158,10 +184,27 @@ selectTurn(...$event);
|
|||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="!isEditMode" :style="rowGridStyle">
|
||||||
|
<div
|
||||||
|
v-for="(turnObj, turnIdx) in reservedCommandList.slice(
|
||||||
|
0,
|
||||||
|
viewMaxTurn
|
||||||
|
)"
|
||||||
|
:key="turnIdx"
|
||||||
|
class="action_pad d-grid"
|
||||||
|
>
|
||||||
|
<BButton
|
||||||
|
:variant="(turnIdx % 2 == 0) ? 'secondary' : 'dark'"
|
||||||
|
size="sm"
|
||||||
|
class="simple_action_btn bi bi-pencil"
|
||||||
|
@click="toggleQuickReserveForm(turnIdx)"
|
||||||
|
></BButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row gx-1">
|
<div class="row gx-1">
|
||||||
<div class="col d-grid">
|
<div class="col d-grid">
|
||||||
<BDropdown right split text="당기기" @click="pullGeneralCommandSingle">
|
<BDropdown text="당기기">
|
||||||
<BDropdownItem
|
<BDropdownItem
|
||||||
v-for="turnIdx in maxPushTurn"
|
v-for="turnIdx in maxPushTurn"
|
||||||
:key="turnIdx"
|
:key="turnIdx"
|
||||||
@@ -170,7 +213,7 @@ selectTurn(...$event);
|
|||||||
</BDropdown>
|
</BDropdown>
|
||||||
</div>
|
</div>
|
||||||
<div class="col d-grid">
|
<div class="col d-grid">
|
||||||
<BDropdown right split text="미루기" @click="pushGeneralCommandSingle">
|
<BDropdown text="미루기">
|
||||||
<BDropdownItem
|
<BDropdownItem
|
||||||
v-for="turnIdx in maxPushTurn"
|
v-for="turnIdx in maxPushTurn"
|
||||||
:key="turnIdx"
|
:key="turnIdx"
|
||||||
@@ -193,6 +236,13 @@ selectTurn(...$event);
|
|||||||
ref="commandSelectForm"
|
ref="commandSelectForm"
|
||||||
@on-close="chooseCommand($event)"
|
@on-close="chooseCommand($event)"
|
||||||
/>
|
/>
|
||||||
|
<CommandSelectForm
|
||||||
|
:commandList="commandList"
|
||||||
|
anchor=".commandQuickReserveFormAnchor"
|
||||||
|
ref="commandQuickReserveForm"
|
||||||
|
@on-close="chooseQuickReserveCommand($event)"
|
||||||
|
:hideClose="false"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -276,11 +326,11 @@ for (const commandCategories of commandList) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleForm($event: Event): void{
|
function toggleForm($event: Event): void {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
|
|
||||||
const form = commandSelectForm.value;
|
const form = commandSelectForm.value;
|
||||||
if(!form){
|
if (!form) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
form.toggle();
|
form.toggle();
|
||||||
@@ -323,6 +373,7 @@ const emptyTurn: TurnObjWithTime[] = Array.from<TurnObjWithTime>({
|
|||||||
const prevTurnList = ref(new Set([0]));
|
const prevTurnList = ref(new Set([0]));
|
||||||
const turnList = ref(new Set<number>());
|
const turnList = ref(new Set<number>());
|
||||||
const reservedCommandList = ref(emptyTurn);
|
const reservedCommandList = ref(emptyTurn);
|
||||||
|
const isEditMode = ref(false);
|
||||||
|
|
||||||
const flippedMaxTurn = 15;
|
const flippedMaxTurn = 15;
|
||||||
const viewMaxTurn = ref(flippedMaxTurn);
|
const viewMaxTurn = ref(flippedMaxTurn);
|
||||||
@@ -431,6 +482,7 @@ async function pushGeneralCommand(amount: number) {
|
|||||||
await reloadCommandList();
|
await reloadCommandList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
function pushGeneralCommandSingle(e: Event) {
|
function pushGeneralCommandSingle(e: Event) {
|
||||||
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
|
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
|
||||||
if (isDropdownChildren(e)) {
|
if (isDropdownChildren(e)) {
|
||||||
@@ -446,6 +498,7 @@ function pullGeneralCommandSingle(e: Event) {
|
|||||||
}
|
}
|
||||||
void pushGeneralCommand(-1);
|
void pushGeneralCommand(-1);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
async function reloadCommandList() {
|
async function reloadCommandList() {
|
||||||
let result: ReservedCommandResponse;
|
let result: ReservedCommandResponse;
|
||||||
@@ -561,10 +614,42 @@ function chooseCommand(val?: string) {
|
|||||||
selectedCommand.value = invCommandMap[val];
|
selectedCommand.value = invCommandMap[val];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const commandQuickReserveForm = ref<InstanceType<typeof CommandSelectForm> | null>(null);
|
||||||
|
|
||||||
|
const currentQuickReserveTarget = ref(-1);
|
||||||
|
function chooseQuickReserveCommand(val?: string) {
|
||||||
|
if (!val) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedCommand.value = invCommandMap[val];
|
||||||
|
turnList.value.clear();
|
||||||
|
turnList.value.add(currentQuickReserveTarget.value);
|
||||||
|
void reserveCommand();
|
||||||
|
}
|
||||||
|
function toggleQuickReserveForm(turnIdx: number) {
|
||||||
|
if (turnIdx == currentQuickReserveTarget.value) {
|
||||||
|
commandQuickReserveForm.value?.toggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentQuickReserveTarget.value = turnIdx;
|
||||||
|
commandQuickReserveForm.value?.show();
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
void reloadCommandList();
|
void reloadCommandList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
watch(isEditMode, newEditMode => {
|
||||||
|
if (newEditMode) {
|
||||||
|
commandQuickReserveForm.value?.close();
|
||||||
|
currentQuickReserveTarget.value = -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
commandSelectForm.value?.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@@ -576,9 +661,19 @@ onMounted(() => {
|
|||||||
|
|
||||||
.commandPad {
|
.commandPad {
|
||||||
background-color: $gray-900;
|
background-color: $gray-900;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.commandTable {
|
.commandTable {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:
|
||||||
|
minmax(20px, 0.8fr) minmax(75px, 2.4fr) minmax(40px, 0.9fr)
|
||||||
|
4.8fr minmax(28px, 0.8fr);
|
||||||
|
//30, 70, 37.65, 160
|
||||||
|
}
|
||||||
|
|
||||||
|
.commandTable.isEditMode {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(30px, 1fr) minmax(75px, 2.5fr) minmax(40px, 1fr) 5fr;
|
grid-template-columns: minmax(30px, 1fr) minmax(75px, 2.5fr) minmax(40px, 1fr) 5fr;
|
||||||
@@ -628,11 +723,16 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.month_pad:hover {
|
.isEditMode .month_pad:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plain-center {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plain-center,
|
||||||
.month_pad,
|
.month_pad,
|
||||||
.time_pad,
|
.time_pad,
|
||||||
.turn_pad {
|
.turn_pad {
|
||||||
|
|||||||
@@ -22,7 +22,17 @@
|
|||||||
@click="close(commandItem.value)"
|
@click="close(commandItem.value)"
|
||||||
>
|
>
|
||||||
<div class="commandItem">
|
<div class="commandItem">
|
||||||
<p class="center my-0">{{ commandItem.simpleName }}</p>
|
<p :class="['center', 'my-0', commandItem.possible ? '' : 'commandImpossible']">
|
||||||
|
{{ commandItem.simpleName }}
|
||||||
|
<span
|
||||||
|
class="compensatePositive"
|
||||||
|
v-if="commandItem.compensation > 0"
|
||||||
|
>▲</span>
|
||||||
|
<span
|
||||||
|
class="compensateNegative"
|
||||||
|
v-else-if="commandItem.compensation < 0"
|
||||||
|
>▼</span>
|
||||||
|
</p>
|
||||||
<small class="center" :style="{ display: 'block' }">
|
<small class="center" :style="{ display: 'block' }">
|
||||||
{{
|
{{
|
||||||
commandItem.title.startsWith(commandItem.simpleName)
|
commandItem.title.startsWith(commandItem.simpleName)
|
||||||
@@ -33,11 +43,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<div class="commandBottom row mt-1 mb-1">
|
<div v-if="!hideClose" class="commandBottom row mt-1 mb-1">
|
||||||
<div class="offset-8 col-4 d-grid">
|
<div class="offset-8 col-4 d-grid">
|
||||||
<BButton @click="close()">닫기</BButton>
|
<BButton @click="close()">닫기</BButton>
|
||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
@@ -86,6 +96,11 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: '.commandSelectFormAnchor',
|
default: '.commandSelectFormAnchor',
|
||||||
|
},
|
||||||
|
hideClose: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="container"
|
ref="container"
|
||||||
style="
|
:style="{
|
||||||
position: relative;
|
position: 'relative',
|
||||||
user-select: none;
|
userSelect: disabled ? undefined : 'none',
|
||||||
overflow: hidden;
|
overflow: 'hidden',
|
||||||
touch-action: none;
|
touchAction: disabled ? undefined : 'none',
|
||||||
|
}
|
||||||
"
|
"
|
||||||
|
:class="{ disabledDrag: disabled }"
|
||||||
>
|
>
|
||||||
<slot :selected="intersected" />
|
<slot :selected="intersected" />
|
||||||
</div>
|
</div>
|
||||||
@@ -58,6 +60,11 @@ export default defineComponent({
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => ref(new Set()),
|
default: () => ref(new Set()),
|
||||||
},
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue", "dragDone", "dragStart"],
|
emits: ["update:modelValue", "dragDone", "dragStart"],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
@@ -138,6 +145,9 @@ export default defineComponent({
|
|||||||
|
|
||||||
let isMine = false;
|
let isMine = false;
|
||||||
function startDrag(e: MouseEvent | Touch) {
|
function startDrag(e: MouseEvent | Touch) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
containerRect = uContainer.getBoundingClientRect();
|
containerRect = uContainer.getBoundingClientRect();
|
||||||
children = uContainer.children;
|
children = uContainer.children;
|
||||||
start = getCoords(e);
|
start = getCoords(e);
|
||||||
@@ -152,6 +162,9 @@ export default defineComponent({
|
|||||||
emit("dragStart");
|
emit("dragStart");
|
||||||
}
|
}
|
||||||
function drag(e: MouseEvent | Touch) {
|
function drag(e: MouseEvent | Touch) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
end = getCoords(e);
|
end = getCoords(e);
|
||||||
const dimensions = getDimensions(start, end);
|
const dimensions = getDimensions(start, end);
|
||||||
if (end.x < start.x) {
|
if (end.x < start.x) {
|
||||||
@@ -165,6 +178,9 @@ export default defineComponent({
|
|||||||
intersection();
|
intersection();
|
||||||
}
|
}
|
||||||
function endDrag() {
|
function endDrag() {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
start = { x: 0, y: 0 };
|
start = { x: 0, y: 0 };
|
||||||
end = { x: 0, y: 0 };
|
end = { x: 0, y: 0 };
|
||||||
box.style.width = "0";
|
box.style.width = "0";
|
||||||
@@ -172,16 +188,34 @@ export default defineComponent({
|
|||||||
document.removeEventListener("mousemove", drag);
|
document.removeEventListener("mousemove", drag);
|
||||||
document.removeEventListener("touchmove", touchMove);
|
document.removeEventListener("touchmove", touchMove);
|
||||||
box.remove();
|
box.remove();
|
||||||
if(isMine){
|
if (isMine) {
|
||||||
emit("dragDone", intersected.value);
|
emit("dragDone", intersected.value);
|
||||||
}
|
}
|
||||||
isMine = false;
|
isMine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uContainer.addEventListener("mousedown", startDrag);
|
watch(() => props.disabled, disabledNext => {
|
||||||
uContainer.addEventListener("touchstart", touchStart);
|
if (disabledNext) {
|
||||||
document.addEventListener("mouseup", endDrag);
|
uContainer.removeEventListener("mousedown", startDrag);
|
||||||
document.addEventListener("touchend", endDrag);
|
uContainer.removeEventListener("touchstart", touchStart);
|
||||||
|
document.removeEventListener("mouseup", endDrag);
|
||||||
|
document.removeEventListener("touchend", endDrag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uContainer.addEventListener("mousedown", startDrag);
|
||||||
|
uContainer.addEventListener("touchstart", touchStart);
|
||||||
|
document.addEventListener("mouseup", endDrag);
|
||||||
|
document.addEventListener("touchend", endDrag);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!props.disabled) {
|
||||||
|
uContainer.addEventListener("mousedown", startDrag);
|
||||||
|
uContainer.addEventListener("touchstart", touchStart);
|
||||||
|
document.addEventListener("mouseup", endDrag);
|
||||||
|
document.addEventListener("touchend", endDrag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
uContainer.removeEventListener("mousedown", startDrag);
|
uContainer.removeEventListener("mousedown", startDrag);
|
||||||
|
|||||||
Reference in New Issue
Block a user