릴리스: v1.3.59 관리자 템플릿 요청 중복 방지 및 신규 템플릿 연결 흐름 정리
This commit is contained in:
@@ -30,6 +30,19 @@ export function useAdminGameManager({
|
||||
success,
|
||||
error,
|
||||
}) {
|
||||
function normalizeDraftSrc(src) {
|
||||
if (typeof src !== 'string') return ''
|
||||
const raw = src.trim()
|
||||
if (!raw) return ''
|
||||
if (raw.startsWith('/uploads/')) return raw
|
||||
try {
|
||||
const url = new URL(raw)
|
||||
return url.pathname || raw
|
||||
} catch (e) {
|
||||
return raw
|
||||
}
|
||||
}
|
||||
|
||||
function requestItemFilename(item = {}) {
|
||||
const src = typeof item.src === 'string' ? item.src : ''
|
||||
return src.split('/').pop() || item.file?.name || 'item'
|
||||
@@ -51,9 +64,10 @@ export function useAdminGameManager({
|
||||
animation: 160,
|
||||
draggable: '[data-game-item-id]',
|
||||
forceFallback: true,
|
||||
fallbackOnBody: true,
|
||||
fallbackOnBody: false,
|
||||
filter: '[data-no-drag]',
|
||||
preventOnFilter: false,
|
||||
fallbackClass: 'thumbCard--dragging',
|
||||
ghostClass: 'ghost',
|
||||
chosenClass: 'chosen',
|
||||
onEnd: (evt) => {
|
||||
@@ -72,6 +86,7 @@ export function useAdminGameManager({
|
||||
function mergeRequestItemsIntoDrafts(request) {
|
||||
const requestId = request?.id
|
||||
if (!requestId) return
|
||||
const existingGameSrcs = new Set((selectedGame.value?.items || []).map((item) => normalizeDraftSrc(item?.src)).filter(Boolean))
|
||||
const existingKeys = new Set(uploadItemDrafts.value.map((draft) => `${draft.kind}:${draft.requestId || ''}:${draft.itemId || draft.file?.name || ''}`))
|
||||
const nextRequestDrafts = (request.items || [])
|
||||
.filter((item) => item?.src)
|
||||
@@ -84,6 +99,7 @@ export function useAdminGameManager({
|
||||
sourceName: requestItemFilename(item),
|
||||
src: item.src,
|
||||
}))
|
||||
.filter((draft) => !existingGameSrcs.has(normalizeDraftSrc(draft.src)))
|
||||
.filter((draft) => !existingKeys.has(`${draft.kind}:${draft.requestId}:${draft.itemId}`))
|
||||
|
||||
if (nextRequestDrafts.length) {
|
||||
@@ -148,6 +164,24 @@ export function useAdminGameManager({
|
||||
if (!res.ok) throw new Error('failed')
|
||||
|
||||
const data = await res.json()
|
||||
if (activeTemplateRequest.value?.type === 'create' && activeTemplateRequest.value?.id) {
|
||||
const linkData = await api.linkAdminTemplateRequestGame(activeTemplateRequest.value.id, {
|
||||
gameId: data.game.id,
|
||||
})
|
||||
activeTemplateRequest.value = {
|
||||
...activeTemplateRequest.value,
|
||||
targetGameId: linkData.request?.targetGameId || data.game.id,
|
||||
targetGameName: linkData.request?.targetGameName || data.game.name || newGameName.value.trim(),
|
||||
}
|
||||
const requestIndex = templateRequests.value.findIndex((entry) => entry.id === activeTemplateRequest.value.id)
|
||||
if (requestIndex >= 0) {
|
||||
templateRequests.value.splice(requestIndex, 1, {
|
||||
...templateRequests.value[requestIndex],
|
||||
targetGameId: linkData.request?.targetGameId || data.game.id,
|
||||
targetGameName: linkData.request?.targetGameName || data.game.name || newGameName.value.trim(),
|
||||
})
|
||||
}
|
||||
}
|
||||
await refreshGames()
|
||||
selectedGameId.value = data.game.id
|
||||
if (customItemModalOpen.value) customItemModalTargetGameId.value = data.game.id
|
||||
@@ -238,15 +272,16 @@ export function useAdminGameManager({
|
||||
const requestIds = [...new Set(requestDrafts.map((entry) => entry.requestId).filter(Boolean))]
|
||||
for (const requestId of requestIds) {
|
||||
const draftsForRequest = requestDrafts.filter((entry) => entry.requestId === requestId)
|
||||
await api.promoteAdminTemplateRequestItems(requestId, {
|
||||
const result = await api.promoteAdminTemplateRequestItems(requestId, {
|
||||
gameId: selectedGameId.value,
|
||||
itemIds: draftsForRequest.map((entry) => entry.itemId).filter(Boolean),
|
||||
itemSrcs: draftsForRequest.map((entry) => entry.src).filter(Boolean),
|
||||
itemLabels: draftsForRequest.reduce((acc, entry) => {
|
||||
if (entry.itemId) acc[entry.itemId] = entry.label.trim()
|
||||
return acc
|
||||
}, {}),
|
||||
})
|
||||
uploadCount += draftsForRequest.length
|
||||
uploadCount += Array.isArray(result?.items) ? result.items.length : 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +289,21 @@ export function useAdminGameManager({
|
||||
await loadGame()
|
||||
success.value = `게임 기본 아이템 ${uploadCount}개 추가를 완료했어요.`
|
||||
} catch (e) {
|
||||
error.value = '아이템 추가 실패(관리자 권한/파일 크기 확인)'
|
||||
const apiError = e?.data?.error || ''
|
||||
if (apiError === 'no_items_selected') {
|
||||
error.value = '추가할 요청 아이템이 없어요.'
|
||||
return
|
||||
}
|
||||
if (apiError === 'promote_items_failed') {
|
||||
const detail = e?.data?.detail ? ` (${e.data.detail})` : ''
|
||||
error.value = `요청 아이템을 게임 기본 아이템으로 옮기지 못했어요.${detail}`
|
||||
return
|
||||
}
|
||||
if (apiError === 'game_not_found') {
|
||||
error.value = '선택한 게임을 찾지 못했어요.'
|
||||
return
|
||||
}
|
||||
error.value = '아이템 추가에 실패했어요.'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user