feat: 路由动态权限控制、图片广场优化
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
@click="handleCardClick(task)"
|
||||
@use-prompt="$emit('use-prompt', $event)"
|
||||
@use-reference="$emit('use-reference', $event)"
|
||||
@publish="handlePublish($event)"
|
||||
@publish="openPublishDialog(task)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
>
|
||||
<div v-if="currentTask" class="flex flex-col md:flex-row gap-6 h-[600px]">
|
||||
<!-- Left Image -->
|
||||
<div class="flex-1 bg-black/5 rounded-lg flex items-center justify-center overflow-hidden relative">
|
||||
<div class="flex-1 bg-black/5 rounded-lg flex items-center justify-center overflow-hidden relative group">
|
||||
<el-image
|
||||
v-if="currentTask.storeUrl"
|
||||
:src="currentTask.storeUrl"
|
||||
@@ -66,6 +66,11 @@
|
||||
<span class="text-sm opacity-80">{{ currentTask.errorInfo || '未知错误' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Download Button Overlay -->
|
||||
<div v-if="currentTask.storeUrl" class="absolute bottom-4 right-4 opacity-0 group-hover:opacity-100 transition-opacity z-10">
|
||||
<el-button circle type="primary" :icon="Download" @click="downloadImage(currentTask.storeUrl)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Info -->
|
||||
@@ -127,7 +132,7 @@
|
||||
type="success"
|
||||
class="w-full"
|
||||
:icon="Share"
|
||||
@click="handlePublish(currentTask)"
|
||||
@click="openPublishDialog(currentTask)"
|
||||
>
|
||||
发布到广场
|
||||
</el-button>
|
||||
@@ -139,18 +144,64 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- Publish Dialog -->
|
||||
<el-dialog
|
||||
v-model="publishDialogVisible"
|
||||
title="发布到广场"
|
||||
width="500px"
|
||||
append-to-body
|
||||
align-center
|
||||
>
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="标签 (回车添加)">
|
||||
<div class="flex gap-2 flex-wrap w-full p-2 border border-gray-200 rounded-md min-h-[40px]">
|
||||
<el-tag
|
||||
v-for="tag in publishTags"
|
||||
:key="tag"
|
||||
closable
|
||||
:disable-transitions="false"
|
||||
@close="handleCloseTag(tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
v-if="inputVisible"
|
||||
ref="InputRef"
|
||||
v-model="inputValue"
|
||||
class="w-24"
|
||||
size="small"
|
||||
@keyup.enter="handleInputConfirm"
|
||||
@blur="handleInputConfirm"
|
||||
/>
|
||||
<el-button v-else class="button-new-tag" size="small" @click="showInput">
|
||||
+ New Tag
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="publishDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmPublish" :loading="publishing">
|
||||
发布
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, nextTick } from 'vue';
|
||||
import { getMyTasks, publishImage } from '@/api/aiImage';
|
||||
import type { TaskItem } from '@/api/aiImage/types';
|
||||
import TaskCard from './TaskCard.vue';
|
||||
import { format } from 'date-fns';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import type { InputInstance } from 'element-plus';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Picture, Loading, MagicStick, CopyDocument, Share } from '@element-plus/icons-vue';
|
||||
import { Picture, Loading, MagicStick, CopyDocument, Share, CircleCloseFilled, Download } from '@element-plus/icons-vue';
|
||||
|
||||
const emit = defineEmits(['use-prompt', 'use-reference']);
|
||||
|
||||
@@ -162,6 +213,15 @@ const noMore = ref(false);
|
||||
const dialogVisible = ref(false);
|
||||
const currentTask = ref<TaskItem | null>(null);
|
||||
|
||||
// Publish Dialog State
|
||||
const publishDialogVisible = ref(false);
|
||||
const publishing = ref(false);
|
||||
const publishTags = ref<string[]>([]);
|
||||
const inputValue = ref('');
|
||||
const inputVisible = ref(false);
|
||||
const InputRef = ref<InputInstance>();
|
||||
const taskToPublish = ref<TaskItem | null>(null);
|
||||
|
||||
const { copy } = useClipboard();
|
||||
|
||||
const disabled = computed(() => loading.value || noMore.value);
|
||||
@@ -230,23 +290,71 @@ const copyPrompt = async (text: string) => {
|
||||
ElMessage.success('提示词已复制');
|
||||
};
|
||||
|
||||
const handlePublish = async (task: TaskItem) => {
|
||||
const openPublishDialog = (task: TaskItem) => {
|
||||
taskToPublish.value = task;
|
||||
publishTags.value = [];
|
||||
inputValue.value = '';
|
||||
inputVisible.value = false;
|
||||
publishDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleCloseTag = (tag: string) => {
|
||||
publishTags.value.splice(publishTags.value.indexOf(tag), 1);
|
||||
};
|
||||
|
||||
const showInput = () => {
|
||||
inputVisible.value = true;
|
||||
nextTick(() => {
|
||||
InputRef.value!.input!.focus();
|
||||
});
|
||||
};
|
||||
|
||||
const handleInputConfirm = () => {
|
||||
if (inputValue.value) {
|
||||
if (!publishTags.value.includes(inputValue.value)) {
|
||||
publishTags.value.push(inputValue.value);
|
||||
}
|
||||
}
|
||||
inputVisible.value = false;
|
||||
inputValue.value = '';
|
||||
};
|
||||
|
||||
const confirmPublish = async () => {
|
||||
if (!taskToPublish.value) return;
|
||||
|
||||
publishing.value = true;
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要发布这张图片到广场吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'info',
|
||||
});
|
||||
|
||||
await publishImage({
|
||||
taskId: task.id,
|
||||
categories: []
|
||||
taskId: taskToPublish.value.id,
|
||||
categories: publishTags.value
|
||||
});
|
||||
|
||||
ElMessage.success('发布成功');
|
||||
task.publishStatus = 'Published';
|
||||
taskToPublish.value.publishStatus = 'Published';
|
||||
publishDialogVisible.value = false;
|
||||
} catch (e) {
|
||||
// Cancelled or error
|
||||
console.error(e);
|
||||
ElMessage.error('发布失败');
|
||||
} finally {
|
||||
publishing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const downloadImage = async (url: string) => {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
const blobUrl = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = blobUrl;
|
||||
link.download = `image-${Date.now()}.png`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
} catch (e) {
|
||||
console.error('Download failed', e);
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user