mock create drawing
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { fetchWithAuth } from '#/utils/fetch-with-auth';
|
||||
|
||||
export async function getConversations() {
|
||||
const res = await fetchWithAuth('/api/ai/v1/conversations');
|
||||
const res = await fetchWithAuth('chat/conversations');
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
export async function createConversation() {
|
||||
const response = await fetchWithAuth('/api/ai/v1/conversations', {
|
||||
const response = await fetchWithAuth('chat/conversations', {
|
||||
method: 'POST',
|
||||
});
|
||||
if (!response.ok) {
|
||||
@@ -17,7 +17,7 @@ export async function createConversation() {
|
||||
|
||||
export async function getMessages(conversationId: number) {
|
||||
const res = await fetchWithAuth(
|
||||
`/api/ai/v1/messages?conversation_id=${conversationId}`,
|
||||
`chat/messages?conversation_id=${conversationId}`,
|
||||
);
|
||||
return await res.json();
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export async function fetchAIStream({
|
||||
content,
|
||||
conversation_id,
|
||||
}: FetchAIStreamParams) {
|
||||
const res = await fetchWithAuth('/api/ai/v1/stream', {
|
||||
const res = await fetchWithAuth('chat/stream', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ content, conversation_id }),
|
||||
});
|
||||
|
||||
47
web/apps/web-antd/src/api/ai/drawing.ts
Normal file
47
web/apps/web-antd/src/api/ai/drawing.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { fetchWithAuth } from '#/utils/fetch-with-auth';
|
||||
|
||||
export interface CreateImageTaskParams {
|
||||
prompt: string;
|
||||
style?: string;
|
||||
size?: string;
|
||||
model?: string;
|
||||
platform?: string;
|
||||
n?: number;
|
||||
}
|
||||
|
||||
export async function createImageTask(params: CreateImageTaskParams) {
|
||||
const res = await fetchWithAuth('drawing/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error('创建图片任务失败');
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
export async function fetchImageTaskStatus(id: number) {
|
||||
const res = await fetchWithAuth(`drawing/${id}/`);
|
||||
if (!res.ok) {
|
||||
throw new Error('查询图片任务状态失败');
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
export interface GetImagePageParams {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
export async function getImagePage(params: GetImagePageParams = {}) {
|
||||
const query = new URLSearchParams();
|
||||
if (params.page) query.append('page', String(params.page));
|
||||
if (params.page_size) query.append('page_size', String(params.page_size));
|
||||
const res = await fetchWithAuth(
|
||||
`drawing${query.toString() ? `?${query.toString()}` : ''}`,
|
||||
);
|
||||
if (!res.ok) {
|
||||
throw new Error('获取图片分页失败');
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
@@ -20,6 +20,10 @@
|
||||
"title": "AI CHAT",
|
||||
"name": "AI CHAT"
|
||||
},
|
||||
"drawing": {
|
||||
"title": "AI DRAWING",
|
||||
"name": "AI DRAWING"
|
||||
},
|
||||
"chat_conversation": {
|
||||
"title": "CHAT Management",
|
||||
"name": "CHAT Management"
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
"title": "AI对话",
|
||||
"name": "AI对话"
|
||||
},
|
||||
"drawing": {
|
||||
"title": "AI绘画",
|
||||
"name": "AI绘画"
|
||||
},
|
||||
"chat_conversation": {
|
||||
"title": "对话列表",
|
||||
"name": "对话列表"
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { formatToken } from '#/utils/auth';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { formatToken } from '#/utils/auth';
|
||||
|
||||
export const API_BASE = '/api/ai/v1/';
|
||||
|
||||
export function fetchWithAuth(input: RequestInfo, init: RequestInit = {}) {
|
||||
const accessStore = useAccessStore();
|
||||
const token = accessStore.accessToken;
|
||||
const headers = new Headers(init.headers || {});
|
||||
headers.append('Content-Type', 'application/json');
|
||||
headers.append('Authorization', formatToken(token) as string);
|
||||
return fetch(input, { ...init, headers });
|
||||
return fetch(API_BASE + input, { ...init, headers });
|
||||
}
|
||||
|
||||
200
web/apps/web-antd/src/views/ai/drawing/index.vue
Normal file
200
web/apps/web-antd/src/views/ai/drawing/index.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, h, reactive, ref } from 'vue';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Pagination,
|
||||
Row,
|
||||
Select,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { createImageTask } from '#/api/ai/drawing';
|
||||
|
||||
// 表单选项
|
||||
const platforms = [
|
||||
{ label: '通义千问', value: 'tongyi' },
|
||||
// { label: 'DeepSeek', value: 'deepseek' },
|
||||
// { label: 'OpenAI', value: 'openai' },
|
||||
// { label: 'Google GenAI', value: 'google-genai' },
|
||||
];
|
||||
const models = {
|
||||
tongyi: [{ label: 'wanx_v1', value: 'wanx_v1' }],
|
||||
// deepseek: [{ label: 'deepseek-img', value: 'deepseek-img' }],
|
||||
// openai: [{ label: 'dall-e-3', value: 'dall-e-3' }],
|
||||
// 'google-genai': [{ label: 'imagen', value: 'imagen' }],
|
||||
};
|
||||
const sizes = [
|
||||
{ label: '1024x1024', value: '1024x1024' },
|
||||
{ label: '720*1280', value: '720*1280' },
|
||||
{ label: '768*1152', value: '768*1152' },
|
||||
{ label: '1280*720', value: '1280*720' },
|
||||
];
|
||||
const styles = [
|
||||
{ label: '默认(由模型随机输出风格)', value: 'auto' },
|
||||
{ label: '摄影', value: 'photography' },
|
||||
{ label: '人像写真', value: 'portrait' },
|
||||
{ label: '3D卡通', value: '3d cartoon' },
|
||||
{ label: '动画', value: 'anime' },
|
||||
{ label: '油画', value: 'oil painting' },
|
||||
{ label: '水彩', value: 'watercolor' },
|
||||
{ label: '素描', value: 'sketch' },
|
||||
{ label: '中国画', value: 'chinese painting' },
|
||||
{ label: '扁平插画', value: 'flat illustration' },
|
||||
];
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
prompt: '近景镜头,18岁的中国女孩,古代服饰,圆脸,正面看着镜头,民族优雅的服装,商业摄影,室外,电影级光照,半身特写,精致的淡妆,锐利的边缘。',
|
||||
platform: 'tongyi',
|
||||
model: 'wanx_v1',
|
||||
size: '1024x1024',
|
||||
style: 'watercolor',
|
||||
});
|
||||
|
||||
// 图片数据与分页
|
||||
const images = ref<string[]>([]);
|
||||
const loading = ref(false);
|
||||
const page = ref(1);
|
||||
const pageSize = 12;
|
||||
const total = computed(() => images.value.length);
|
||||
const pagedImages = computed(() =>
|
||||
images.value.slice((page.value - 1) * pageSize, page.value * pageSize),
|
||||
);
|
||||
|
||||
// 平台切换时自动切换模型
|
||||
const onPlatformChange = (val: string) => {
|
||||
form.model = models[val][0].value;
|
||||
};
|
||||
|
||||
// 提交表单,调用AI画图API
|
||||
async function handleDraw() {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 这里调用你的AI画图API,返回图片url数组
|
||||
const res = await createImageTask(form);
|
||||
// images.value = res.data.images;
|
||||
// DEMO用假数据
|
||||
// images.value = Array.from(
|
||||
// { length: 30 },
|
||||
// (_, i) => `https://picsum.photos/seed/${form.prompt}-${i}/300/300`,
|
||||
// );
|
||||
page.value = 1;
|
||||
message.success('生成成功');
|
||||
} catch {
|
||||
message.error('生成失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<Row :gutter="24">
|
||||
<!-- 左侧表单 -->
|
||||
<Col :span="8">
|
||||
<Card title="AI画图" bordered>
|
||||
<Form layout="vertical" @submit.prevent="handleDraw">
|
||||
<Form.Item label="画画描述">
|
||||
<Input.TextArea
|
||||
v-model:value="form.prompt"
|
||||
:autosize="true"
|
||||
placeholder="请输入画面描述"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="平台选择">
|
||||
<Select v-model:value="form.platform" @change="onPlatformChange">
|
||||
<Select.Option
|
||||
v-for="item in platforms"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="模型选择">
|
||||
<Select v-model:value="form.model">
|
||||
<Select.Option
|
||||
v-for="item in models[form.platform]"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="图片尺寸">
|
||||
<Select v-model:value="form.size">
|
||||
<Select.Option
|
||||
v-for="item in sizes"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="图像风格">
|
||||
<Select v-model:value="form.style">
|
||||
<Select.Option
|
||||
v-for="item in styles"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" html-type="submit" :loading="loading">
|
||||
生成图片
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
</Col>
|
||||
<!-- 右侧图片展示 -->
|
||||
<Col :span="16">
|
||||
<Card title="生成结果" bordered>
|
||||
<Row :gutter="16">
|
||||
<Col
|
||||
v-for="(img, idx) in pagedImages"
|
||||
:key="img"
|
||||
:span="4"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<Card
|
||||
hoverable
|
||||
:cover="
|
||||
h('img', {
|
||||
src: img,
|
||||
style: 'width:100%;height:180px;object-fit:cover;',
|
||||
})
|
||||
"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Pagination
|
||||
v-if="total > pageSize"
|
||||
v-model:current="page"
|
||||
:total="total"
|
||||
:page-size="pageSize"
|
||||
style="margin-top: 16px; text-align: right"
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 可根据需要自定义样式 */
|
||||
</style>
|
||||
@@ -1,11 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>dsadsa</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="css">
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user