feat: 绘画页面对接腾讯混元文生图
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import type {PropType} from "vue";
|
||||
import type {PropType} from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
ratios: {
|
||||
@@ -8,13 +8,25 @@ const props = defineProps({
|
||||
label?: string,
|
||||
value: string | number
|
||||
}[]>,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const selected = ref<string | number>('')
|
||||
|
||||
onMounted(() => {
|
||||
if (props.modelValue) {
|
||||
handle_select(props.modelValue)
|
||||
} else {
|
||||
handle_select(props.ratios[0].value)
|
||||
}
|
||||
})
|
||||
|
||||
const handle_select = (value: string | number) => {
|
||||
selected.value = value
|
||||
emit('update:modelValue', value)
|
||||
@@ -24,7 +36,7 @@ const getRatio = (ratio: string) => {
|
||||
const [w, h] = ratio.split(/[:\/]/).map(Number)
|
||||
return {
|
||||
w: w,
|
||||
h: h
|
||||
h: h,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,12 +45,12 @@ const getShapeSize = (r: { w: number, h: number }, size: number) => {
|
||||
if (r.w > r.h) {
|
||||
return {
|
||||
w: size,
|
||||
h: size / ratio
|
||||
h: size / ratio,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
w: size * ratio,
|
||||
h: size
|
||||
h: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,17 +59,19 @@ const getShapeSize = (r: { w: number, h: number }, size: number) => {
|
||||
<template>
|
||||
<div class="grid grid-cols-4 gap-2">
|
||||
<div v-for="(ratio, k) in ratios" :key="ratio.value" @click="handle_select(ratio.value)"
|
||||
class="w-full aspect-square bg-neutral-200/50 rounded-lg flex flex-col justify-around items-center cursor-pointer"
|
||||
:class="[ratio.value === selected && 'bg-sky-200/50']">
|
||||
<div class="bg-neutral-300/50 text-neutral-900 rounded flex justify-center items-center"
|
||||
:class="[ratio.value === selected && 'bg-sky-300/50']" :style="{
|
||||
width: getShapeSize(getRatio(ratio.ratio), 30).w * 2 + '%',
|
||||
height: getShapeSize(getRatio(ratio.ratio), 30).h * 2 + '%'
|
||||
class="w-full aspect-square bg-neutral-200/50 dark:bg-neutral-700/50 rounded-lg py-1.5 flex flex-col justify-between items-center cursor-pointer select-none"
|
||||
:class="[ratio.value === selected && 'bg-sky-200/50 dark:bg-sky-700/50']">
|
||||
<div class="bg-neutral-300/50 dark:bg-neutral-600/50 text-neutral-600 dark:text-neutral-300 rounded flex justify-center items-center"
|
||||
:class="[ratio.value === selected && 'bg-sky-300/50 dark:bg-sky-600/50']" :style="{
|
||||
width: getShapeSize(getRatio(ratio.ratio), 30).w * 1.1 + 'px',
|
||||
height: getShapeSize(getRatio(ratio.ratio), 30).h * 1.1 + 'px'
|
||||
}">
|
||||
<span class="text-xs font-thin">{{ ratio.ratio }}</span>
|
||||
<span class="text-xs font-thin font-mono">{{ ratio.ratio }}</span>
|
||||
</div>
|
||||
<span class="text-[10px]">
|
||||
{{ ratio?.label || getRatio(ratio.ratio).w > getRatio(ratio.ratio).h ? '横向' : '纵向' }}
|
||||
{{
|
||||
ratio?.label || getRatio(ratio.ratio).w === getRatio(ratio.ratio).h ? '正方形' : (getRatio(ratio.ratio).w > getRatio(ratio.ratio).h ? '横向' : '纵向')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import type {ResultBlockMeta} from "~/components/aigc/drawing/index";
|
||||
import type {PropType} from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import type {ResultBlockMeta} from '~/components/aigc/drawing/index';
|
||||
import type {PropType} from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const props = defineProps({
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'i-tabler-photo-filled'
|
||||
default: 'i-tabler-photo-filled',
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
prompt: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
images: {
|
||||
type: Array,
|
||||
default: (): Array<string> => []
|
||||
default: (): Array<string> => [],
|
||||
},
|
||||
meta: {
|
||||
type: Object as PropType<ResultBlockMeta>
|
||||
}
|
||||
type: Object as PropType<ResultBlockMeta>,
|
||||
},
|
||||
})
|
||||
|
||||
const expand_prompt = ref(false)
|
||||
@@ -50,7 +50,10 @@ const show_meta = ref(true)
|
||||
<UButton color="gray" size="xs" icon="i-tabler-copy" variant="ghost" class="-mt-1"></UButton>
|
||||
</div>
|
||||
<div v-if="images.length > 0" class="flex items-center overflow-x-auto h-64 gap-2 pb-2 snap-x">
|
||||
<img v-for="(url, i) in images" class="result-image" :src="url" alt="" :key="i">
|
||||
<img v-for="(url, i) in images" class="result-image" :src="useBlobUrlFromB64(url)" alt="AI Generated" :key="i"/>
|
||||
</div>
|
||||
<div v-else class="h-64 aspect-[3/4] mb-4 rounded-lg placeholder-gradient flex justify-center items-center">
|
||||
<UIcon name="i-svg-spinners-tadpole" class="text-3xl" />
|
||||
</div>
|
||||
<Transition v-if="meta" name="meta">
|
||||
<div v-if="show_meta" class="w-full flex items-center gap-2 flex-wrap whitespace-nowrap pb-2 mt-2">
|
||||
@@ -94,4 +97,8 @@ const show_meta = ref(true)
|
||||
@apply snap-start;
|
||||
@apply h-full aspect-auto object-cover rounded-lg shadow-md;
|
||||
}
|
||||
|
||||
.placeholder-gradient {
|
||||
@apply animate-pulse bg-gradient-to-br from-neutral-200 to-neutral-300 dark:from-neutral-700 dark:to-neutral-800;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user