fix: 전용 장수 아이콘 뒤 기본 이미지 중첩 제거
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue';
|
||||
import { useDefaultGeneralIcon } from '../../utils/generalIcon';
|
||||
|
||||
type SelectionMetric = {
|
||||
label: string;
|
||||
@@ -12,7 +13,7 @@ type SelectionItem = {
|
||||
subtitle: string;
|
||||
searchText: string;
|
||||
accent?: 'current' | 'assigned' | 'available';
|
||||
iconBackground?: string;
|
||||
iconUrl?: string;
|
||||
badges?: string[];
|
||||
stats?: SelectionMetric[];
|
||||
details?: SelectionMetric[];
|
||||
@@ -168,11 +169,13 @@ onBeforeUnmount(() => {
|
||||
:aria-pressed="selectedId === item.id"
|
||||
@click="select(item.id)"
|
||||
>
|
||||
<span
|
||||
v-if="item.iconBackground"
|
||||
<img
|
||||
v-if="item.iconUrl"
|
||||
class="personnel-picker-portrait"
|
||||
:style="{ backgroundImage: item.iconBackground }"
|
||||
:src="item.iconUrl"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
@error="useDefaultGeneralIcon"
|
||||
/>
|
||||
<span v-else class="personnel-picker-city-icon" aria-hidden="true">城</span>
|
||||
|
||||
@@ -366,9 +369,7 @@ small {
|
||||
background-color: #0b0c0a;
|
||||
}
|
||||
.personnel-picker-portrait {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
object-fit: cover;
|
||||
}
|
||||
.personnel-picker-city-icon,
|
||||
.vacancy-icon {
|
||||
|
||||
@@ -43,11 +43,6 @@ export const resolveGeneralIconUrl = (
|
||||
return `${trimTrailingSlashes(baseUrl)}/${encodedPicture}`;
|
||||
};
|
||||
|
||||
export const resolveGeneralIconBackgroundImage = (source: GeneralIconSource, options?: GeneralIconOptions): string => {
|
||||
const resolved = resolveGeneralIconUrl(source, options);
|
||||
return `url(${JSON.stringify(resolved)}), url(${JSON.stringify(DEFAULT_GENERAL_ICON_URL)})`;
|
||||
};
|
||||
|
||||
export const resolveMessageGeneralIconUrl = (
|
||||
icon: string | null | undefined,
|
||||
userIconBaseUrl = configuredUserIconPublicUrl()
|
||||
|
||||
@@ -8,7 +8,7 @@ import { JosaUtil } from '@sammo-ts/common/util/JosaUtil';
|
||||
import PermissionMultiSelect from '../components/personnel/PermissionMultiSelect.vue';
|
||||
import PersonnelSelectionDialog from '../components/personnel/PersonnelSelectionDialog.vue';
|
||||
import { useGameFeedback } from '../composables/useGameFeedback';
|
||||
import { resolveGeneralIconBackgroundImage } from '../utils/generalIcon';
|
||||
import { resolveGeneralIconUrl, useDefaultGeneralIcon } from '../utils/generalIcon';
|
||||
import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
|
||||
import { trpc } from '../utils/trpc';
|
||||
import { cityLevelMap, formatOfficerLevelText, getNationChiefLevel, regionMap } from '../utils/nationFormat';
|
||||
@@ -25,7 +25,7 @@ type SelectionDialogItem = {
|
||||
subtitle: string;
|
||||
searchText: string;
|
||||
accent: 'current' | 'assigned' | 'available';
|
||||
iconBackground?: string;
|
||||
iconUrl?: string;
|
||||
badges: string[];
|
||||
stats?: Array<{ label: string; value: string }>;
|
||||
details: Array<{ label: string; value: string }>;
|
||||
@@ -77,7 +77,7 @@ const chiefAssignments = computed(() => data.value?.chiefAssignments ?? {});
|
||||
const cityNameMap = computed(() => new Map((data.value?.cityAssignments ?? []).map((city) => [city.id, city.name])));
|
||||
const generalMap = computed(() => new Map((data.value?.generals ?? []).map((general) => [general.id, general])));
|
||||
|
||||
const imageBackground = (general: GeneralEntry | undefined): string => resolveGeneralIconBackgroundImage(general ?? {});
|
||||
const imageUrl = (general: GeneralEntry | undefined): string => resolveGeneralIconUrl(general ?? {});
|
||||
const officerLocked = (value: number, level: number): boolean => (value & (1 << level)) !== 0;
|
||||
const chiefLocked = (level: number): boolean => officerLocked(data.value?.nation.chiefSet ?? 0, level);
|
||||
const cityOfficerLocked = (city: PersonnelResponse['cityAssignments'][number], level: number): boolean =>
|
||||
@@ -197,7 +197,7 @@ const generalSelectionItem = (general: GeneralEntry, currentGeneralId: number):
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
accent: isCurrent ? 'current' : isAssigned ? 'assigned' : 'available',
|
||||
iconBackground: imageBackground(general),
|
||||
iconUrl: imageUrl(general),
|
||||
badges,
|
||||
stats: [
|
||||
{ label: '통솔', value: general.stats.leadership.toLocaleString('ko-KR') },
|
||||
@@ -355,10 +355,12 @@ onMounted(() => void loadPersonnel());
|
||||
<span class="chief-entry-role">{{
|
||||
formatOfficerLevelText(level, nationLevel)
|
||||
}}</span>
|
||||
<span
|
||||
<img
|
||||
class="general-icon"
|
||||
:style="{ backgroundImage: imageBackground(chiefAssignments[level]) }"
|
||||
:src="imageUrl(chiefAssignments[level])"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
@error="useDefaultGeneralIcon"
|
||||
/>
|
||||
<span class="chief-entry-copy">
|
||||
<strong>{{ chiefAssignments[level]?.name ?? '공석' }}</strong>
|
||||
@@ -736,9 +738,7 @@ select {
|
||||
grid-area: icon;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 64px 64px;
|
||||
object-fit: fill;
|
||||
}
|
||||
.chief-entry-copy {
|
||||
display: grid;
|
||||
@@ -943,7 +943,6 @@ select {
|
||||
.general-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background-size: 48px 48px;
|
||||
}
|
||||
.chief-entry-copy strong {
|
||||
font-size: var(--sammo-font-size-personnel-mobile-name);
|
||||
|
||||
Reference in New Issue
Block a user