|
|
|
@@ -44,9 +44,17 @@ |
|
|
|
<div |
|
|
|
v-for="item in list" |
|
|
|
:key="item.id" |
|
|
|
class="group cursor-pointer overflow-hidden rounded-2xl bg-[var(--c-ffffff)] shadow-[0_10px_28px_var(--sh-34-68-112-60)] transition-shadow hover:shadow-[0_14px_34px_var(--sh-34-68-112-120)]" |
|
|
|
class="group relative cursor-pointer overflow-hidden rounded-2xl bg-[var(--c-ffffff)] shadow-[0_10px_28px_var(--sh-34-68-112-60)] transition-shadow hover:shadow-[0_14px_34px_var(--sh-34-68-112-120)]" |
|
|
|
@click="openWork(item)" |
|
|
|
> |
|
|
|
<button |
|
|
|
type="button" |
|
|
|
class="absolute right-3 top-3 z-10 flex size-8 items-center justify-center rounded-full bg-white/90 text-[var(--c-f04438)] opacity-0 shadow-[0_8px_20px_var(--sh-15-23-42-160)] backdrop-blur transition-opacity hover:bg-[var(--c-fff1f0)] group-hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--c-f04438)]" |
|
|
|
aria-label="删除作品" |
|
|
|
@click.stop="deleteWork(item)" |
|
|
|
> |
|
|
|
<UIcon name="i-lucide-trash-2" class="size-4" /> |
|
|
|
</button> |
|
|
|
<!-- AI 取名卡片 --> |
|
|
|
<div |
|
|
|
v-if="item.work_type === 'ainame'" |
|
|
|
@@ -148,7 +156,7 @@ |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 作品详情弹窗 --> |
|
|
|
<WorkDetailModal v-model="detailOpen" :work="currentWork" /> |
|
|
|
<WorkDetailModal v-model="detailOpen" :work="currentWork" @deleted="handleDeleted" /> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@@ -263,6 +271,55 @@ function openWork(item) { |
|
|
|
detailOpen.value = true |
|
|
|
} |
|
|
|
|
|
|
|
function resolveWorkId(item = {}) { |
|
|
|
return item.photo_open_id || item.chat_open_id || item.id || '' |
|
|
|
} |
|
|
|
|
|
|
|
function getDeleteRequest(item = {}) { |
|
|
|
const id = resolveWorkId(item) |
|
|
|
if (!id) return null |
|
|
|
if (item.work_type === 'photo') return { path: '/idphoto/del', body: { photo_open_id: id } } |
|
|
|
if (item.work_type === 'oldphoto') return { path: '/oldphoto/del', body: { photo_open_id: id } } |
|
|
|
if (item.work_type === 'portrait') return { path: '/portrait/del', body: { photo_open_id: id } } |
|
|
|
if (item.work_type === 'ainame') return { path: '/ainame/del', body: { chat_open_id: id } } |
|
|
|
if (item.work_type === 'anime') return { path: '/anime/del', body: { chat_open_id: id } } |
|
|
|
return { path: '/chat/del', body: { chat_open_id: id } } |
|
|
|
} |
|
|
|
|
|
|
|
function removeDeletedFromList(item = {}) { |
|
|
|
const id = String(resolveWorkId(item)) |
|
|
|
if (!id) return |
|
|
|
const deleted = list.value.find(row => String(resolveWorkId(row)) === id) |
|
|
|
list.value = list.value.filter(row => String(resolveWorkId(row)) !== id) |
|
|
|
if (deleted) { |
|
|
|
total.value = Math.max(0, total.value - 1) |
|
|
|
const type = deleted.work_type || 'all' |
|
|
|
counts.value = { |
|
|
|
...counts.value, |
|
|
|
all: Math.max(0, Number(counts.value.all || 0) - 1), |
|
|
|
[type]: Math.max(0, Number(counts.value[type] || 0) - 1), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async function deleteWork(item) { |
|
|
|
const req = getDeleteRequest(item) |
|
|
|
if (!req) return |
|
|
|
if (!window.confirm('确认删除该作品记录?删除后将不再展示。')) return |
|
|
|
try { |
|
|
|
await post(req.path, req.body) |
|
|
|
removeDeletedFromList(item) |
|
|
|
toast.add({ title: '删除成功', color: 'success' }) |
|
|
|
} catch (e) { |
|
|
|
toast.add({ title: e.message || '删除失败', color: 'error' }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function handleDeleted(item) { |
|
|
|
removeDeletedFromList(item) |
|
|
|
fetchList(true, true) |
|
|
|
} |
|
|
|
|
|
|
|
function statusClass(item) { |
|
|
|
const status = Number(item.status) |
|
|
|
if (status === 0) return 'bg-[var(--c-fff5e8)] text-[var(--c-ff8a00)]' |
|
|
|
|