feat: 사령부에서 다른 수뇌의 턴을 '복사하기' 기능

This commit is contained in:
2022-03-26 23:09:19 +09:00
parent 47a20cf550
commit c7bd18f307
6 changed files with 167 additions and 85 deletions
+9 -4
View File
@@ -31,11 +31,16 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
line-height: 30px; line-height: 30px;
} }
.time_pad.inverted{
background-color: gray;
color: white;
}
.turn_pad { .turn_pad {
line-height: 30px; line-height: 30px;
} }
.row:nth-child(odd) .turn_pad { .row:nth-of-type(odd) .turn_pad {
background-color: $modcolor2; background-color: $modcolor2;
} }
} }
@@ -83,7 +88,7 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
} }
.commandBox .controlPad { .commandBox .controlPad {
.turn_pad:nth-child(2n) { .turn_pad:nth-of-type(even) {
background-color: $modcolor2; background-color: $modcolor2;
} }
} }
@@ -130,7 +135,7 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
.commandBox .controlPad { .commandBox .controlPad {
margin-top: 10px; margin-top: 10px;
.turn_pad:nth-child(even) { .turn_pad:nth-of-type(even) {
background-color: $modcolor2; background-color: $modcolor2;
} }
} }
@@ -144,7 +149,7 @@ $modcolor2: color.adjust($nbase2color, $lightness: -5%);
overflow: hidden; overflow: hidden;
.turn_pad:nth-child(even) { .turn_pad:nth-of-type(even) {
background-color: $modcolor2; background-color: $modcolor2;
} }
} }
+150 -68
View File
@@ -1,88 +1,170 @@
<template> <template>
<div :class="['subRows', 'chiefCommand']" :style="style"> <div style="position:relative">
<div class="bg1 center row gx-0" style="font-size: 1.2em"> <DragSelect
<div class="col-5 align-self-center text-end"> :class="['subRows', 'chiefCommand']"
{{ officer ? `${officer.officerLevelText} : ` : "" }} :style="style"
:disabled="!props.officer || !isEditMode"
attribute="turnIdx"
@dragStart="dragStart()"
@dragDone="dragDone(...$event)"
v-slot="{ selected }"
>
<div class="bg1 center row gx-0" style="font-size: 1.2em">
<div
class="col-5 align-self-center text-end"
>{{ officer ? `${officer.officerLevelText} : ` : "" }}</div>
<div
class="col-7 align-self-center"
:style="{
color: getNpcColor(officer?.npcType ?? 0),
}"
>{{ officer?.name }}</div>
</div> </div>
<div <div :turnIdx="vidx" class="row c-bg2 gx-0" v-for="vidx in maxTurn" :key="vidx">
class="col-7 align-self-center" <div
:style="{ :class="['col-2', 'time_pad', 'f_tnum', ((isDragToggle || isCopyButtonShown) && selected.has(vidx.toString())) ? 'inverted' : undefined]"
color: getNpcColor(officer?.npcType ?? 0), >{{ turnTimes[vidx - 1] }}</div>
}" <div class="center" v-if="!officer || (!officer.turn) || !(vidx - 1 in officer.turn)"></div>
> <div
{{ officer?.name }} v-else
class="tableCell align-self-center col-10 center turn_pad"
:style="{
fontSize:
mb_strwidth(officer.turn[vidx - 1].brief) > 28
? `${28 / mb_strwidth(officer.turn[vidx - 1].brief)}em`
: undefined,
}"
>{{ officer.turn[vidx - 1].brief }}</div>
</div> </div>
</div> </DragSelect>
<div class="row c-bg2 gx-0" v-for="vidx in maxTurn" :key="vidx"> <BButton
<div class="col-2 time_pad f_tnum"> ref="btnCopy"
{{ turnTimes[vidx - 1] }} :style="{
</div> position: 'absolute',
<div display: isCopyButtonShown ? 'block' : 'none',
class="center" top: `${btnPos * 30 + 25}px`,
v-if="!officer || (!officer.turn) || !(vidx - 1 in officer.turn)" right: '10px',
></div> }"
<div @blur="isCopyButtonShown = false"
v-else @click="tryCopy()"
class="tableCell align-self-center col-10 center turn_pad" >복사하기</BButton>
:style="{
fontSize:
mb_strwidth(officer.turn[vidx - 1].brief) > 28
? `${28 / mb_strwidth(officer.turn[vidx - 1].brief)}em`
: undefined,
}"
>
{{ officer.turn[vidx - 1].brief }}
</div>
</div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { getNpcColor } from "@/common_legacy"; import { getNpcColor } from "@/common_legacy";
import type { ChiefResponse } from "@/defs"; import type { ChiefResponse } from "@/defs";
import { formatTime } from "@/util/formatTime"; import { formatTime } from "@/util/formatTime";
import { mb_strwidth } from "@/util/mb_strwidth"; import { mb_strwidth } from "@/util/mb_strwidth";
import { parseTime } from "@/util/parseTime"; import { parseTime } from "@/util/parseTime";
import type { StoredActionsHelper } from "@/util/StoredActionsHelper";
import addMinutes from "date-fns/esm/addMinutes/index"; import addMinutes from "date-fns/esm/addMinutes/index";
import { range } from "lodash"; import { range } from "lodash";
import { defineComponent, type PropType } from "vue"; import { defineProps, inject, onMounted, ref, type PropType } from "vue";
import VueTypes from "vue-types"; import VueTypes from "vue-types";
import DragSelect from "@/components/DragSelect.vue";
import { BButton } from "bootstrap-vue-3";
import { QueryActionHelper } from "@/util/QueryActionHelper";
export default defineComponent({
props: { const props = defineProps({
style: VueTypes.object.isRequired, style: VueTypes.object.isRequired,
officer: { officer: {
type: Object as PropType<ChiefResponse["chiefList"][0]>, type: Object as PropType<ChiefResponse["chiefList"][0]>,
},
turnTerm: VueTypes.integer.isRequired,
maxTurn: VueTypes.integer.isRequired,
},
methods: {
getNpcColor,
mb_strwidth,
}, },
turnTerm: VueTypes.integer.isRequired,
maxTurn: VueTypes.integer.isRequired,
})
data() { const btnPos = ref(0);
const turnTimes: string[] = []; const btnCopy = ref<InstanceType<typeof BButton> | null>(null);
if (!this.officer || !this.officer.turnTime) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const _ of range(this.maxTurn)) {
turnTimes.push("\xa0");
}
} else {
const baseTurnTime = parseTime(this.officer.turnTime);
for (const idx of range(this.officer.turn.length)) {
turnTimes.push(
formatTime(
addMinutes(baseTurnTime, idx * this.turnTerm),
this.turnTerm >= 5 ? "HH:mm" : "mm:ss"
)
);
}
}
const storedActionsHelper = inject<StoredActionsHelper>('storedNationActionsHelper');
const isEditMode = (storedActionsHelper?.isEditMode) ?? ref(false);
const isDragToggle = ref(false);
const isCopyButtonShown = ref(false);
const queryActionHelper = new QueryActionHelper(props.maxTurn);
const selectedTurnList = queryActionHelper.selectedTurnList;
onMounted(() => {
if (props.officer === undefined) {
return;
}
queryActionHelper.reservedCommandList.value = props.officer.turn.map(rawTurn => {
return { return {
turnTimes, ...rawTurn,
}; time: '',
}, }
});
console.log(queryActionHelper.reservedCommandList.value);
}); });
function dragStart() {
isDragToggle.value = true;
}
function eqSet<T>(as: Set<T>, bs: Set<T>) {
if (as.size !== bs.size) return false;
for (var a of as) if (!bs.has(a)) return false;
return true;
}
function dragDone(...rawSelectedTurn: string[]) {
if (rawSelectedTurn.length === 0) {
return;
}
const newSelectedTurnList = new Set<number>();
let maxPos = -1;
for (const rawIdx of rawSelectedTurn) {
const idx = parseInt(rawIdx) - 1;
newSelectedTurnList.add(idx);
maxPos = Math.max(maxPos, idx);
}
btnPos.value = maxPos;
isDragToggle.value = false;
if (newSelectedTurnList.size == 1 && eqSet(selectedTurnList.value, newSelectedTurnList)) {
isCopyButtonShown.value = false;
return;
}
selectedTurnList.value = newSelectedTurnList;
isCopyButtonShown.value = true;
setTimeout(() => {
(btnCopy.value?.$el as HTMLButtonElement).focus();
}, 0);
}
function tryCopy() {
const actions = queryActionHelper.extractQueryActions();
isCopyButtonShown.value = false;
if (!storedActionsHelper) {
return;
}
storedActionsHelper.clipboard.value = [...actions];
}
const turnTimes = ref<string[]>([]);
if (!props.officer || !props.officer.turnTime) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const _ of range(props.maxTurn)) {
turnTimes.value.push("\xa0");
}
} else {
const baseTurnTime = parseTime(props.officer.turnTime);
for (const idx of range(props.officer.turn.length)) {
turnTimes.value.push(
formatTime(
addMinutes(baseTurnTime, idx * props.turnTerm),
props.turnTerm >= 5 ? "HH:mm" : "mm:ss"
)
);
}
}
</script> </script>
+4 -4
View File
@@ -38,9 +38,6 @@
/> />
<ChiefReservedCommand <ChiefReservedCommand
v-else v-else
:serverNick="serverNick"
:mapName="mapName"
:unitSet="unitSet"
:key="idx" :key="idx"
:targetIsMe="targetIsMe" :targetIsMe="targetIsMe"
:year="year" :year="year"
@@ -113,7 +110,7 @@ import "@scss/common/bootstrap5.scss";
import "@scss/game_bg.scss"; import "@scss/game_bg.scss";
import "../../css/config.css"; import "../../css/config.css";
import { computed, defineProps, reactive, ref, toRefs, watch } from "vue"; import { computed, defineProps, provide, reactive, ref, toRefs, watch } from "vue";
import ChiefReservedCommand from "@/components/ChiefReservedCommand.vue"; import ChiefReservedCommand from "@/components/ChiefReservedCommand.vue";
import TopBackBar from "@/components/TopBackBar.vue"; import TopBackBar from "@/components/TopBackBar.vue";
import BottomBar from "@/components/BottomBar.vue"; import BottomBar from "@/components/BottomBar.vue";
@@ -126,6 +123,7 @@ import BottomItem from "@/ChiefCenter/BottomItem.vue";
import type { ChiefResponse, OptionalFull } from "./defs"; import type { ChiefResponse, OptionalFull } from "./defs";
import { SammoAPI } from "./SammoAPI"; import { SammoAPI } from "./SammoAPI";
import { unwrap } from "@/util/unwrap"; import { unwrap } from "@/util/unwrap";
import { StoredActionsHelper } from "./util/StoredActionsHelper";
const { const {
serverNick, serverNick,
@@ -236,6 +234,8 @@ const subTableGridRows = computed(() => {
void reloadTable(); void reloadTable();
const storedActionsHelper = new StoredActionsHelper(staticValues.serverNick, 'nation', staticValues.mapName, staticValues.unitSet);
provide('storedNationActionsHelper', storedActionsHelper);
</script> </script>
<style lang="scss"> <style lang="scss">
+3 -7
View File
@@ -289,7 +289,7 @@ toggleTurn(...$event);
<script lang="ts" setup> <script lang="ts" setup>
import addMinutes from "date-fns/esm/addMinutes"; import addMinutes from "date-fns/esm/addMinutes";
import { stringifyUrl } from "query-string"; import { stringifyUrl } from "query-string";
import { defineProps, defineEmits, defineExpose, onMounted, ref, watch, type PropType } from "vue"; import { defineProps, defineEmits, defineExpose, onMounted, ref, watch, type PropType, inject } from "vue";
import { formatTime } from "@util/formatTime"; import { formatTime } from "@util/formatTime";
import { joinYearMonth } from "@util/joinYearMonth"; import { joinYearMonth } from "@util/joinYearMonth";
import { mb_strwidth } from "@util/mb_strwidth"; import { mb_strwidth } from "@util/mb_strwidth";
@@ -303,7 +303,7 @@ import { SammoAPI } from "@/SammoAPI";
import type { ChiefResponse, CommandItem, TurnObj } from "@/defs"; import type { ChiefResponse, CommandItem, TurnObj } from "@/defs";
import { QueryActionHelper } from "@/util/QueryActionHelper"; import { QueryActionHelper } from "@/util/QueryActionHelper";
import type { Args } from "@/processing/args"; import type { Args } from "@/processing/args";
import { StoredActionsHelper } from "@/util/StoredActionsHelper"; import type { StoredActionsHelper } from "@/util/StoredActionsHelper";
import { getNpcColor } from "@/common_legacy"; import { getNpcColor } from "@/common_legacy";
import { BButton, BDropdownItem, BDropdownText, BButtonGroup, BDropdownDivider, BDropdown } from "bootstrap-vue-3"; import { BButton, BDropdownItem, BDropdownText, BButtonGroup, BDropdownDivider, BDropdown } from "bootstrap-vue-3";
import addMilliseconds from "date-fns/addMilliseconds"; import addMilliseconds from "date-fns/addMilliseconds";
@@ -319,10 +319,6 @@ type TurnObjWithTime = TurnObj & {
}; };
const props = defineProps({ const props = defineProps({
serverNick: VueTypes.string.isRequired,
mapName: VueTypes.string.isRequired,
unitSet: VueTypes.string.isRequired,
maxTurn: VueTypes.integer.isRequired, maxTurn: VueTypes.integer.isRequired,
maxPushTurn: VueTypes.integer.isRequired, maxPushTurn: VueTypes.integer.isRequired,
date: VueTypes.string.isRequired, date: VueTypes.string.isRequired,
@@ -613,7 +609,7 @@ function chooseCommand(val?: string) {
const emptyTurnObj: TurnObj = { action: '휴식', brief: '휴식', arg: {} }; const emptyTurnObj: TurnObj = { action: '휴식', brief: '휴식', arg: {} };
const storedActionsHelper = new StoredActionsHelper(props.serverNick, 'nation', props.mapName, props.unitSet); const storedActionsHelper = inject('storedNationActionsHelper') as StoredActionsHelper;
const recentActions = storedActionsHelper.recentActions; const recentActions = storedActionsHelper.recentActions;
const storedActions = storedActionsHelper.storedActions; const storedActions = storedActionsHelper.storedActions;
+1 -1
View File
@@ -156,7 +156,7 @@ export default defineComponent({
document.addEventListener("touchmove", touchMove); document.addEventListener("touchmove", touchMove);
box.style.top = start.y + "px"; box.style.top = start.y + "px";
box.style.left = start.x + "px"; box.style.left = start.x + "px";
uContainer.prepend(box); uContainer.append(box);
intersection(); intersection();
isMine = true; isMine = true;
emit("dragStart"); emit("dragStart");
-1
View File
@@ -31,7 +31,6 @@ export class StoredActionsHelper {
this.clipboard.value = JSON.parse(rawClipboard); this.clipboard.value = JSON.parse(rawClipboard);
} }
watch(this.clipboard, (newValue) => { watch(this.clipboard, (newValue) => {
console.log(newValue);
localStorage.setItem(this.clipboardKey, JSON.stringify(newValue)); localStorage.setItem(this.clipboardKey, JSON.stringify(newValue));
}); });