diff --git a/components/aigc/drawing/ResultBlock.vue b/components/aigc/drawing/ResultBlock.vue
index d34f801..a9945f3 100644
--- a/components/aigc/drawing/ResultBlock.vue
+++ b/components/aigc/drawing/ResultBlock.vue
@@ -9,9 +9,6 @@ const props = defineProps({
type: String,
default: 'i-tabler-photo-filled',
},
- title: {
- type: String,
- },
prompt: {
type: String,
},
@@ -26,6 +23,7 @@ const props = defineProps({
type: Object as PropType
,
},
})
+const emit = defineEmits(['use-reference'])
const toast = useToast()
@@ -37,7 +35,9 @@ const cachedImagesInterval = ref(null)
onMounted(async () => {
cachedImagesInterval.value = setInterval(async () => {
- cachedImages.value = await get(props.fid) as string[] || []
+ const res = await get(props.fid) as string[] || []
+ if (res.length === cachedImages.value.length) return
+ cachedImages.value = res
}, 1000)
})
@@ -54,6 +54,23 @@ const handle_download = (url: string) => {
a.click()
}
+const handle_use_reference = async (blob_url: string) => {
+ fetch(blob_url)
+ .then(res => res.blob())
+ .then(blob => {
+ const file = new File([blob], `xsh_drawing-${props.meta?.datetime! * 1000}.png`, {type: 'image/png'})
+ emit('use-reference', file)
+ })
+ .catch(() => {
+ toast.add({
+ title: '转换失败',
+ description: '无法获取图片数据',
+ color: 'red',
+ icon: 'i-tabler-circle-x',
+ })
+ })
+}
+
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text).then(() => {
toast.add({
@@ -78,7 +95,7 @@ const copyToClipboard = (text: string) => {
- {{ title }}
+ {{ meta.type || 'AI 智能绘图' }}
{
scale-105 opacity-0 group-hover:scale-100 group-hover:opacity-100 transition">
-
+
+ @click="handle_download(url)">
@@ -124,6 +142,10 @@ const copyToClipboard = (text: string) => {
{{ meta.modal }}
+
+
+ {{ meta.style }}
+
{{ meta.cost }}
diff --git a/components/aigc/drawing/index.d.ts b/components/aigc/drawing/index.d.ts
index 3f48d83..e431a6a 100644
--- a/components/aigc/drawing/index.d.ts
+++ b/components/aigc/drawing/index.d.ts
@@ -1,7 +1,9 @@
export declare interface ResultBlockMeta {
- modal?: string
- cost?: string
- ratio?: string
- id?: string
- datetime?: number
+ modal?: string
+ cost?: string
+ ratio?: string
+ id?: string
+ style?: string
+ datetime?: number
+ type?: string
}
\ No newline at end of file
diff --git a/composables/useFileGo.ts b/composables/useFileGo.ts
new file mode 100644
index 0000000..ec56618
--- /dev/null
+++ b/composables/useFileGo.ts
@@ -0,0 +1,38 @@
+import {useFetchWrapped} from '~/composables/useFetchWrapped';
+
+const putOSS = (file: File, signed_url: string) => new Promise((resolve, reject) => {
+ let xhr = new XMLHttpRequest()
+ xhr.open('PUT', signed_url as string)
+ xhr.setRequestHeader('Content-Type', '')
+ xhr.onload = () => {
+ if (xhr.status === 200) {
+ resolve()
+ } else {
+ reject()
+ }
+ }
+ xhr.onerror = reject
+ xhr.send(file)
+})
+
+export const useFileGo = (file: File) => new Promise((resolve, reject) => {
+ useFetchWrapped('App.Tools_Upload.GoOss', {
+ token: useLoginState().token!,
+ user_id: useLoginState().user.id,
+ file_name: file.name,
+ file_type: file.type,
+ file_size: file.size,
+ }).then(async res => {
+ if (res !== '') {
+ try {
+ await putOSS(file, res)
+ let url = res.split('?')[0]
+ resolve(url)
+ } catch (err) {
+ reject(err)
+ }
+ }
+ }).catch(err => {
+ reject(err)
+ })
+})
\ No newline at end of file
diff --git a/nuxt.config.ts b/nuxt.config.ts
index d1041e7..8f7616c 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -18,6 +18,7 @@ export default defineNuxtConfig({
families: {
Rubik: '100..900',
'Noto Sans SC': '100..900',
+ 'Barlow Condensed': '100..900'
}
}],
],
diff --git a/pages/aigc/drawing/index.vue b/pages/aigc/drawing/index.vue
index d24a719..f563d54 100644
--- a/pages/aigc/drawing/index.vue
+++ b/pages/aigc/drawing/index.vue
@@ -10,6 +10,7 @@ import {useFetchWrapped} from '~/composables/useFetchWrapped';
import type {ResultBlockMeta} from '~/components/aigc/drawing';
import {useHistory} from '~/composables/useHistory';
import {del, set} from 'idb-keyval';
+import ReferenceFigureSelector from '~/components/aigc/ReferenceFigureSelector.vue';
useHead({
title: '绘画 | XSH AI',
@@ -52,8 +53,6 @@ const handle_stick_mousedown = (e: MouseEvent, min: number = 240, max: number =
}
}
-// const histories = ref([])
-
const defaultRatios = [
{
ratio: '1:1',
@@ -177,6 +176,28 @@ const defaultStyles: StyleItem[] = [
value: 116,
},
]
+const img2imgStyles: StyleItem[] = [
+ {
+ label: '水彩画',
+ value: 106,
+ },
+ {
+ label: '2.5D',
+ value: 110,
+ },
+ {
+ label: '日系动漫',
+ value: 201,
+ },
+ {
+ label: '美系动漫',
+ value: 202,
+ },
+ {
+ label: '唯美古风',
+ value: 203,
+ },
+]
const defaultFormSchema = object({
prompt: string().required('请输入提示词'),
@@ -186,6 +207,7 @@ const defaultFormSchema = object({
label: string(),
value: number(),
}).required('请选择风格'),
+ file: string().nullable(),
})
type DefaultFormSchema = InferType
@@ -195,6 +217,14 @@ const defaultFormState = reactive({
negative_prompt: '',
resolution: '1024:768',
styles: defaultStyles.find(item => item.value === 401),
+ file: null,
+})
+watch(() => defaultFormState.file, (newVal) => {
+ if (newVal) {
+ defaultFormState.styles = img2imgStyles[0]
+ } else {
+ defaultFormState.styles = defaultStyles.find(item => item.value === 401)
+ }
})
const onDefaultFormSubmit = (event: FormSubmitEvent) => {
@@ -203,24 +233,27 @@ const onDefaultFormSubmit = (event: FormSubmitEvent) => {
return
}
generating.value = true
+ const styleItem = event.data.styles as StyleItem
+ if (!event.data.file) delete event.data.file
// generate a uuid
const fid = Math.random().toString(36).substring(2)
const meta: ResultBlockMeta = {
cost: '1000',
modal: '混元大模型',
+ style: styleItem.label,
ratio: event.data.resolution,
datetime: dayjs().unix(),
+ type: event.data.file ? '智能图生图' : '智能文生图',
}
history.text2img.unshift({
fid,
meta,
prompt: event.data.prompt,
})
- const styleItem = event.data.styles as StyleItem
useFetchWrapped<
- HunYuan.Text2Img.req & AuthedRequest,
- BaseResponse
- >('App.Assistant_HunYuan.TenTextToImg', {
+ (HunYuan.Text2Img.req | HunYuan.Img2Img.req) & AuthedRequest,
+ BaseResponse
+ >(event.data.file ? 'App.Assistant_HunYuan.TenImgToImg' : 'App.Assistant_HunYuan.TenTextToImg', {
token: loginState.token as string,
user_id: loginState.user.id,
device_id: 'web',
@@ -292,9 +325,18 @@ const onDefaultFormSubmit = (event: FormSubmitEvent) => {
resize/>
+
+
+ {defaultFormState.file = file; console.log('recv', file)}"
+ text="选择参考图片" text-on-select="已选择参考图"/>
+
+
-
+
@@ -310,7 +352,7 @@ const onDefaultFormSubmit = (event: FormSubmitEvent) => {
{{ generating ? '生成中' : '生成' }}
- 生成即代表您同意用户许可协议
@@ -333,9 +375,9 @@ const onDefaultFormSubmit = (event: FormSubmitEvent
) => {
没有记录