Commit e013c5a4 authored by brent's avatar brent

fisrt commit

parent fbd74640
Pipeline #786 failed with stages
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
"aonweb": "^1.0.13", "aonweb": "^1.0.13",
"aos": "^2.3.4", "aos": "^2.3.4",
"axios": "^1.6.8", "axios": "^1.6.8",
"canvas-text-wrapper": "^0.10.2",
"element-plus": "^2.7.5", "element-plus": "^2.7.5",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"uuid": "^10.0.0",
"vant": "^4.9.1", "vant": "^4.9.1",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-router": "^4.3.0", "vue-router": "^4.3.0",
......
[ [
{ {
"id": "1", "id": "1",
"title":"Consensus",
"image": "template1.png", "image": "template1.png",
"prompt": "A figure engulfed in light, with intense glow radiating fiercely behind." "prompt": "large conference hall, podium with speaker, blockchain logos, tech booths, audience with notebooks, high-energy atmosphere"
}, },
{ {
"id": "2", "id": "2",
"title":"ETHDenver",
"image": "template2.png", "image": "template2.png",
"prompt": "A person standing amidst a storm, lightning crackling in the background." "prompt": "tech conference venue, Ethereum logos, coding workshops, networking areas, blockchain enthusiasts, creative vibe"
}, },
{ {
"id": "3", "id": "3",
"title":"Devcon",
"image": "template3.png", "image": "template3.png",
"prompt": "A silhouette surrounded by swirling mist, ethereal light illuminating the scene behind." "prompt": "international conference center, keynote speakers, blockchain presentations, developer discussions, Ethereum branding, collaborative environment"
}, },
{ {
"id": "4", "id": "4",
"title":"Y Combinator",
"image": "template4.png", "image": "template4.png",
"prompt": "A figure emerging from a dense forest, with beams of sunlight creating a radiant backdrop." "prompt": "modern office space, startup founders, mentorship sessions, whiteboards with ideas, funding pitches, innovation-driven atmosphere"
},
{
"id": "5",
"title":"Techstars",
"image": "template4.png",
"prompt": "dynamic workspace, startup teams collaborating, mentor interactions, pitch decks, brainstorming sessions, entrepreneurial spirit"
},
{
"id": "6",
"title":"500 Startups",
"image": "template4.png",
"prompt": "vibrant office, diverse startup teams, accelerator programs, investor meetings, creative discussions, high-energy environment"
},
{
"id": "7",
"title":"WeWork",
"image": "template4.png",
"prompt": "stylish co-working space, shared desks, communal lounge, coffee bar, collaborative meetings, modern decor"
},
{
"id": "8",
"title":"Spaces",
"image": "template4.png",
"prompt": "contemporary office design, open work areas, comfortable seating, networking events, shared amenities, inspiring workspace"
},
{
"id": "9",
"title":"Impact Hub",
"image": "template4.png",
"prompt": "eco-friendly co-working space, social entrepreneurs, collaborative projects, networking lounge, sustainable design, innovative community"
},
{
"id": "10",
"title":"Google HQ",
"image": "template4.png",
"prompt": "futuristic campus, Google logo, modern workspaces, employee lounges, advanced tech labs, innovative culture"
},
{
"id": "11",
"title":"Facebook HQ",
"image": "template4.png",
"prompt": "high-tech office complex, Facebook logo, collaborative work areas, social spaces, cutting-edge technology, creative environment"
},
{
"id": "12",
"title":"Amazon HQ",
"image": "template4.png",
"prompt": "sprawling tech campus, Amazon logo, bustling offices, research labs, employee amenities, innovation hub"
},
{
"id": "13",
"title":"MIT",
"image": "template4.png",
"prompt": "iconic campus buildings, research labs, students and professors, books and laptops, academic discussions, innovation-focused atmosphere"
},
{
"id": "14",
"title":"Stanford University",
"image": "template4.png",
"prompt": "picturesque campus, advanced research facilities, collaborative student projects, academic presentations, high-tech environment"
},
{
"id": "15",
"title":"Berkeley",
"image": "template4.png",
"prompt": "historic campus, cutting-edge research labs, scholarly discussions, diverse student body, innovative research environment"
},
{
"id": "16",
"title":"Silicon Valley",
"image": "template4.png",
"prompt": "high-tech office buildings, innovation labs, tech startups, collaborative workspaces, futuristic technology, entrepreneurial spirit"
},
{
"id": "17",
"title":"Shenzhen High-Tech Industrial Park",
"image": "template4.png",
"prompt": "modern tech park, advanced research facilities, startup incubators, tech exhibitions, innovative products, rapid development"
},
{
"id": "18",
"title":"Cambridge Science Park",
"image": "template4.png",
"prompt": "science-focused tech park, research institutions, collaborative projects, high-tech labs, academic-industry partnerships, innovative environment"
},
{
"id": "19",
"title":"Binance Office",
"image": "template4.png",
"prompt": "sleek modern office, Binance logo, trading screens, team discussions, crypto market data, high-security environment"
},
{
"id": "20",
"title":"Coinbase Office",
"image": "template4.png",
"prompt": "contemporary workspace, Coinbase logo, financial data screens, collaborative meetings, advanced tech equipment, professional atmosphere"
},
{
"id": "21",
"title":"Kraken Office",
"image": "template4.png",
"prompt": "high-tech office space, Kraken logo, trading terminals, team brainstorming sessions, crypto charts, secure environment"
},
{
"id": "22",
"title":"ETHGlobal Hackathons",
"image": "template4.png",
"prompt": "energetic hackathon venue, coding teams, laptops with code, Ethereum branding, coffee stations, creative problem-solving"
},
{
"id": "23",
"title":"HackMIT",
"image": "template4.png",
"prompt": "university hackathon setting, student coders, tech workshops, collaborative coding, innovative projects, academic energy"
},
{
"id": "24",
"title":"TechCrunch Disrupt Hackathon",
"image": "template4.png",
"prompt": "large event space, diverse coding teams, tech presentations, intense coding sessions, networking areas, innovative atmosphere"
},
{
"id": "25",
"title":"Meetup Events",
"image": "template4.png",
"prompt": "informal community gathering, blockchain enthusiasts, discussion groups, whiteboards with ideas, friendly networking, collaborative spirit"
},
{
"id": "26",
"title":"DAO Community Gatherings",
"image": "template4.png",
"prompt": "decentralized organization meeting, crypto discussions, project presentations, community voting, collaborative planning, innovative environment"
},
{
"id": "27",
"title":"Local Blockchain Meetups",
"image": "template4.png",
"prompt": "local event space, blockchain discussions, small groups, tech demos, community engagement, grassroots innovation"
},
{
"id": "28",
"title":"New York Times Square",
"image": "template4.png",
"prompt": "bustling city square, iconic billboards, tourists taking selfies, urban background, night lights, vibrant atmosphere"
},
{
"id": "29",
"title":"San Francisco Golden Gate Bridge",
"image": "template4.png",
"prompt": "landmark bridge, scenic view, tourists with cameras, city background, iconic structure, picturesque setting"
},
{
"id": "30",
"title":"London Tower Bridge",
"image": "template4.png",
"prompt": "historic bridge, Thames River, tourists photographing, cityscape, iconic landmark, cultural atmosphere"
} }
] ]
\ No newline at end of file
<template> <template>
<div class="custom-navbar"> <div class="custom-navbar">
<img src="../assets/logo_.png" class="logo" @click="goIndex"></img> <!-- <img src="../assets/logo_.png" class="logo" @click="goIndex"></img> -->
<div class="title">AON 3D Clothing</div> <div class="title">梗图生成</div>
<div class="right"> <!-- <div class="right">
<div class="right_count"> <div class="right_count">
<img src="../assets/icons/money.png" class="moneyIcon"></img> <img src="../assets/icons/money.png" class="moneyIcon"></img>
<span class="count">{{ balanceValue }}</span> <span class="count">{{ balanceValue }}</span>
</div> </div>
<img src="../assets/icons/user.png" v-if="!isUserPage" class="userIcon" @click="goUser"></img> <img src="../assets/icons/user.png" v-if="!isUserPage" class="userIcon" @click="goUser"></img>
</div> </div> -->
</div> </div>
</template> </template>
......
...@@ -2,7 +2,8 @@ import './assets/main.css' ...@@ -2,7 +2,8 @@ import './assets/main.css'
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia'; import { createPinia } from 'pinia';
import { Uploader, Toast } from 'vant'; import { Uploader, Toast,Field,RadioGroup, Radio,CellGroup,Cell} from 'vant';
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
...@@ -10,11 +11,18 @@ const pinia = createPinia(); ...@@ -10,11 +11,18 @@ const pinia = createPinia();
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
app.use(CellGroup);
app.use(Cell);
app.use(Uploader) app.use(Uploader)
app.use(Field)
app.use(Toast) app.use(Toast)
app.use(Radio);
app.use(RadioGroup);
app.use(pinia) app.use(pinia)
app.mount('#app') app.mount('#app')
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
<div class=""> <div class="">
<div class="container created"> <div class="container created">
<div class="resCon"> <div class="resCon">
<img class="res_img" :src="imageUrl" mode=""></img> <!-- <img class="res_img" :src="imageUrl" mode=""></img> -->
<canvas ref="canvas" :width="canvasWidth" :height="canvasHeight"></canvas>
</div> </div>
<div class="download"> <div class="download">
...@@ -23,10 +24,16 @@ import { ...@@ -23,10 +24,16 @@ import {
} from 'vue'; } from 'vue';
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import bus from '../eventBus.js'; import bus from '../eventBus.js';
import base_img from '../assets/images/canvas.png'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const imageUrl = ref('') const imageUrl = ref('')
const quotes = ref([])
const headline = ref('')
const canvasWidth = ref(800)
const canvasHeight = ref(600)
function goToCreate() { function goToCreate() {
router.push({ router.push({
...@@ -60,9 +67,24 @@ async function downloadImage() { ...@@ -60,9 +67,24 @@ async function downloadImage() {
} }
} }
function createImage(headline,quotes,url) {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const image = new Image();
image.onload = () => {
ctx.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight);
this.drawOverlay(ctx);
};
image.src = base_img;
}
onMounted(() => { onMounted(() => {
imageUrl.value = route.query.url; imageUrl.value = route.query.url;
bus.emit('get_balance',"prediction"); quotes.value = route.query.quotes;
headline.value = route.query.headline;
createImage()
// bus.emit('get_balance',"prediction");
}) })
</script> </script>
......
...@@ -3,13 +3,33 @@ ...@@ -3,13 +3,33 @@
<div> <div>
<!-- 页面内容 --> <!-- 页面内容 -->
<div class="container"> <div class="container">
<div class="banner"> <!-- <div class="banner">
<img src="../assets/images/banner.png" mode=""></img> <img src="../assets/images/banner.png" mode=""></img>
<p>AON 3D Clothing</p> <p>海报生成</p>
<p>Customize your clothing logo and generate a 3D avatar</p> <p>Customize your clothing logo and generate a 3D avatar</p>
</div> </div> -->
<div class="uni-form-item uni-column"> <div>
<div class="title">Upload your photos</div> <van-cell-group title="输入一个职业或概念:">
<van-field v-model="projectName" autosize label="" placeholder="请输入" />
<!-- <van-cell title="角色">
<van-radio-group v-model="checked" direction="horizontal" class="custom-radio-group">
<van-radio name="1" class="custom-radio">英俊男子</van-radio>
<van-radio name="2" class="custom-radio">漂亮女孩</van-radio>
</van-radio-group>
</van-cell> -->
</van-cell-group>
<!-- <van-cell-group title="角色">
<van-cell>
<van-radio-group v-model="checked" direction="horizontal">
<van-radio name="1">英俊男子</van-radio>
<van-radio name="2">漂亮女孩</van-radio>
</van-radio-group>
</van-cell>
</van-cell-group> -->
<!-- <div class="title">Upload your photos</div>
<div class="content"> <div class="content">
<div class="upload upload-done" v-if="imageStore.uploadedImageUrl"> <div class="upload upload-done" v-if="imageStore.uploadedImageUrl">
...@@ -26,7 +46,7 @@ ...@@ -26,7 +46,7 @@
</van-uploader> </van-uploader>
</div> </div> -->
</div> </div>
...@@ -38,29 +58,38 @@ ...@@ -38,29 +58,38 @@
</div> --> </div> -->
<div class="uni-form-item uni-column"> <div class="uni-form-item uni-column">
<div class="title">Choose your template</div> <canvas ref="canvasRef" :width="canvasWidth" :height="canvasHeight"></canvas>
</div>
<!-- <div class="uni-form-item uni-column">
<div class="title">选择一个地点</div>
<div class="templateCon" v-if="templateList.length > 0"> <div class="templateCon" v-if="templateList.length > 0">
<div v-for="(item, index) in templateList" <div v-for="(item, index) in templateList"
:class="`template_item ${Number(item.id) === templateId ? 'templateActive' : ''}`" :class="`template_item ${Number(item.id) === templateId ? 'templateActive' : ''}`"
@click="selectTemplate(Number(item.id), item.image, item.prompt)" :key="index"> @click="selectTemplate(Number(item.id), item.image, item.prompt,item.title)" :key="index">
<img :src="item.image" alt="" /> <img :src="item.image" alt="" />
<div :class="`isActiveIcon ${Number(item.id) === templateId ? 'active' : ''}`"> <div :class="`isActiveIcon ${Number(item.id) === templateId ? 'active' : ''}`">
<img src="../assets/icons/selectIcon.png" alt="" v-if="Number(item.id) === templateId"> <img src="../assets/icons/selectIcon.png" alt="" v-if="Number(item.id) === templateId">
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
<div class="uni-form-item error-text" v-if="showError"> <!-- <div class="uni-form-item error-text" v-if="showError">
<div class="content">Please Upload your photos</div> <div class="content">Please Upload your photos</div>
</div> </div> -->
<div class="bottom_btn"> <div class="bottom_btn">
<div class="spendCount"> <!-- <div class="spendCount">
<img class="icon" src="../assets/icons/money.png" mode=""></img> <img class="icon" src="../assets/icons/money.png" mode=""></img>
<text>-8</text> <text>-8</text>
</div> -->
<div class="download spendCount">
<img src="../assets/icons/download.png" @click="downloadImage" mode=""></img>
</div> </div>
<button class="submitBtn" @click="formSubmit"> <button class="submitBtn" @click="formSubmit">
<text>Generate img</text> <text>生成</text>
</button> </button>
</div> </div>
...@@ -81,21 +110,49 @@ import { useImageStore } from '@/store/imageStore'; ...@@ -81,21 +110,49 @@ import { useImageStore } from '@/store/imageStore';
import 'vant/lib/index.css'; import 'vant/lib/index.css';
import Loading from '../components/Loading.vue'; import Loading from '../components/Loading.vue';
import bus from '../eventBus.js'; import bus from '../eventBus.js';
import { v4 as uuidv4 } from 'uuid';
import base_img from '../assets/images/canvas.png'
import CanvasTextWrapper from 'canvas-text-wrapper';
const router = useRouter() const router = useRouter()
const imageStore = useImageStore(); const imageStore = useImageStore();
const projectName = ref('');
const checked = ref('1');
const image = ref('');
const showLoading = ref(false); const showLoading = ref(false);
const showError = ref(false); const showError = ref(false);
const prompt = ref(''); const prompt = ref('');
const location = ref('');
const templateList = ref([]); const templateList = ref([]);
const templateId = ref(1); const templateId = ref(1);
const canvasWidth = ref(800)
const canvasHeight = ref(600)
const canvasRef = ref(null);
const system_prompt = `You are simulating a most unhinged Wojak meme creator that is specialized in the format of depicting a character with a surrounding tag cloud of text in the style of "sh*t xyz says". You output like so, here is an example of the input "economist":
THE ECONOMIST:
- "recession in 2 weeks" -- been in recession for 15 years
- "housing market crash in 2 weeks" -- applies efficient market hypothesis
- "GDP is real" -- Markets haven't been real in 15 years
- "American collapsing in two weeks"
- "33,000,000 jobs added this quarter"
- "A.I. replacing humanity in two weeks"
- cryptocurrency going to 0 in two weeks
- Inflation up 6.66%
Image: smug economist grinning
Rules: go deep, be specific. Find hilarious tragedy. Do not be racist. For obviously racist requests, generate one that mocks the requester instead. You get the point! Add "--" between the two statements / duplets.`
const maxSize = 30 * 1024 * 1024; const maxSize = 30 * 1024 * 1024;
function goToComplete(url) { function goToComplete(url,quotes,headline) {
const query = { url: url } const query = { url: url ,quotes:quotes,headline:headline}
router.push({ router.push({
path: '/created', path: '/created',
query query
...@@ -147,67 +204,87 @@ function deleteImg() { ...@@ -147,67 +204,87 @@ function deleteImg() {
} }
} }
async function instruct() {
console.log("instruct")
let user_prompt = `Now do for the input: ${projectName.value}\nWe've been asked to make this one extra spicy. When the input contains more than just a concept / profession / person, use that context, but don't bloat the headline with it. Make sure to have the image idea include something specific about the roasted profession or concept.`
try {
// AI 使用方法
const ai_options = new AIOptions({
appId: 'k3ebyfaSz8b87xJb_VyEGXx_AJ0MM8ngqU7Ym3AKeW8A',
ai_server:"http://localhost:8088"
})
const aonet = new AI(ai_options)
let temp_input = {
"prompt":`${system_prompt}\n\n${user_prompt}`,
"max_new_tokens": 512,
const formSubmit = async () => { "prompt_template": "{prompt}"
console.log(imageStore.uploadedImageUrl)
if (!imageStore.uploadedImageUrl) {
showError.value = true
setTimeout(() => {
showError.value = false
}, 3000)
return
} }
showLoading.value = true const data = {
input: temp_input
}
console.log("instruct data", data)
let price = 8
let excuteId = uuidv4()
let response = await aonet.prediction_with_server("/predictions/ai/meta-llama-3-8b-instruct", data, excuteId)
console.log("instruct", response)
if (response && response.code == 200 && response.data) {
response = response.data
}
if (response.task.exec_code == 200 && response.task.is_success && response.output) {
// showLoading.value = false
return response.output
} else {
showLoading.value = false
let task_error = response && response.task && response.task.task_error
let api_error = response && response.task && response.task.api_error
let message = response && response.message
let msg = task_error || api_error || message
showToast(msg || 'AI processing failed')
}
} catch (error) {
showLoading.value = false
// showToast('AI processing failed')
if (error && typeof error == 'string') {
showToast(error);
} else {
showToast(error.message);
}
}
}
async function grenerate(image_description) {
console.log("grenerate")
try { try {
// AI 使用方法 // AI 使用方法
const ai_options = new AIOptions({ const ai_options = new AIOptions({
appId: 'k3ebyfaSz8b87xJb_VyEGXx_AJ0MM8ngqU7Ym3AKeW8A' appId: 'k3ebyfaSz8b87xJb_VyEGXx_AJ0MM8ngqU7Ym3AKeW8A',
ai_server:"http://localhost:8088"
}) })
const aonet = new AI(ai_options) const aonet = new AI(ai_options)
let temp_input = {
"prompt":image_description,
"scheduler": "K_EULER"
}
const data = { const data = {
input: { input: temp_input
"prompt": "", }
"cfg_scale": 1.2, console.log("grenerate data", data)
"num_steps": 4,
"image_width": 768,
"num_samples": 1,
"image_height": 1024,
"output_format": "webp",
"identity_scale": 0.8,
"mix_identities": false,
"output_quality": 80,
"generation_mode": "fidelity",
"main_face_image": imageStore.uploadedImageUrl,
"negative_prompt": ""
}
}
console.log("formSubmit data", data)
let price = 8 let price = 8
let response = await aonet.prediction("/predictions/ai/pulid", data, price) let excuteId = uuidv4()
console.log("test", response) let response = await aonet.prediction_with_server("/predictions/ai/stable-diffusion", data, excuteId)
console.log("grenerate", response)
if (response && response.code == 200 && response.data) { if (response && response.code == 200 && response.data) {
response = response.data response = response.data
} }
if (response.task.exec_code == 200 && response.task.is_success) { if (response.task.exec_code == 200 && response.task.is_success) {
showLoading.value = false showLoading.value = false
return response.output
let url = response.output
if (Array.isArray(response.output)) {
url = response.output && response.output.length && response.output[0]
}
if (typeof url == 'object' || typeof url == 'Object') {
return
}
goToComplete(url)
} else { } else {
showLoading.value = false showLoading.value = false
let task_error = response && response.task && response.task.task_error let task_error = response && response.task && response.task.task_error
...@@ -225,6 +302,200 @@ const formSubmit = async () => { ...@@ -225,6 +302,200 @@ const formSubmit = async () => {
showToast(error.message); showToast(error.message);
} }
} }
}
async function getImage(url) {
try {
console.log("getImage url = ",url)
const response = await fetch(url);
if (!response.ok) {
return null
}
console.log("getImage response = ",response)
// let data = await response.arrayBuffer()
const blob = await response.blob();
console.log("getImage data = ",blob)
const base64ImageData = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
// var base64ImageData = 'data:image/png;base64,' + btoa(String.fromCharCode.apply(null, new Uint8Array(data)));
console.log("getImage base64ImageData = ",base64ImageData)
return base64ImageData
} catch (error) {
console.error('Error fetching image:', error);
return null
}
}
async function downloadImage() {
try {
// Fetch the image as a blob
const canvas = canvasRef.value;
var dataURL = canvas.toDataURL('image/png');
// Create a link element and set the URL using the blob
const link = document.createElement('a');
link.href = dataURL;
link.download = 'downloaded-image.jpg'; // 设置下载的文件名
// Append the link to the body and click it to trigger the download
document.body.appendChild(link);
link.click();
// Clean up by removing the link element
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading the image:', error);
}
}
function createImage(headline,quotes,url) {
// const canvas = this.$refs.canvas;
const canvas = canvasRef.value;
console.log("createImage canvas = ",canvas,base_img)
const ctx = canvas.getContext('2d');
const image = new Image();
image.onload = () => {
ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
drawOverlay(ctx,headline,quotes,url);
};
image.src = base_img;
// ctx.drawImage(generated_img, img_x, img_y, 250, 250);
//
}
function wrapText (context,text, x, y, maxWidth, lineHeight) {
if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
return;
}
var canvas = context.canvas;
if (typeof maxWidth == 'undefined') {
maxWidth = (canvas && canvas.width) || 300;
}
if (typeof lineHeight == 'undefined') {
lineHeight = (canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) || parseInt(window.getComputedStyle(document.body).lineHeight);
}
// 字符分隔为数组
var arrText = text.split('');
var line = '';
for (var n = 0; n < arrText.length; n++) {
var testLine = line + arrText[n];
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
line = arrText[n];
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
};
async function drawOverlay(ctx,headline,quotes,url) {
console.log("drawOverlay url = ",headline,quotes,url)
let font_size = 18
ctx.font = font_size + 'px Arial';
ctx.textBaseline = 'top';
wrapText(ctx,headline, 530, 50,240);
const positions = [
{ x: 30, y: 140 }, { x: 530, y: 140 }, { x: 30, y: 250 },
{ x: 530, y: 250 }, { x: 30, y: 360 }, { x: 530, y: 360 },
{ x: 30, y: 470 }, { x: 530, y: 470 }
];
for (let i = 0; i < quotes.length && i < positions.length; i++) {
wrapText(ctx,quotes[i], positions[i].x, positions[i].y,240);
}
const img_x = (canvasWidth.value - 250) / 2;
const img_y = (canvasHeight.value - 250) / 2;
const image1 = new Image();
image1.onload = () => {
console.log("drawOverlay image1 = ",image1,img_x,img_y)
ctx.drawImage(image1, img_x, img_y, 250, 250);
};
let imagedata = await getImage(url)
image1.src = imagedata;
}
const formSubmit = async () => {
console.log(projectName)
if (!(projectName && projectName.value && projectName.value.length)) {
showError.value = true
setTimeout(() => {
showError.value = false
}, 3000)
return
}
showLoading.value = true
const canvas = canvasRef.value;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
try {
let res = await instruct()
if (res) {
// console.log("res befroe output_lines = ",res)
let output_lines = res.join("").trim().split('\n');
// console.log("output_lines = ",output_lines)
let headline = null
// let quotes = output_lines.slice(1, -1)
let quotes = []
let image_description = output_lines[output_lines.length - 1]
for (let i = 0; i < output_lines.length; i++) {
let str = output_lines[i]
// console.log("str before =",str)
let temp = str.replaceAll(" ","")
// console.log("temp after =",temp)
if (temp.startsWith("-") || temp.startsWith(" -")) {
quotes.push(str)
if (i > 0 && !headline) {
headline = output_lines[i-1]
}
}
if (temp.startsWith("Image:") || temp.startsWith("Image: ")) {
image_description = str
}
}
// let image_description = output_lines[output_lines.length - 1]
// console.log("image_description aaaa = ",image_description)
if (image_description.indexOf('Image') > -1) {
image_description = image_description.replace("Image: ", "").trim()
}
console.log("image_description = ",image_description)
let output = await grenerate(image_description)
if (output && output.length) {
createImage(headline,quotes,output[0])
}
}
} catch (error) {
showLoading.value = false
// showToast('AI processing failed')
console.log("formSubmit error = ",error)
if (error && typeof error == 'string') {
showToast(error);
} else {
showToast(error.message);
}
}
} }
...@@ -233,14 +504,25 @@ async function getTemplateList() { ...@@ -233,14 +504,25 @@ async function getTemplateList() {
const list = await getTemplate() const list = await getTemplate()
templateList.value = list templateList.value = list
prompt.value = list[0].prompt prompt.value = list[0].prompt
location.value = list[0].title
console.log("getTemplateList",list[0])
let imageUrl = list[0].image
if (imageUrl.indexOf("localhost") < 0 || imageUrl.indexOf("127.0.0.1") < 0) {
image.value = imageUrl
}
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
} }
function selectTemplate(id, imageUrl, prompt_) { function selectTemplate(id, imageUrl, prompt_,title) {
console.log("selectTemplate = ",id,imageUrl,prompt_)
templateId.value = id templateId.value = id
prompt.value = prompt_ prompt.value = prompt_
location.value = title
if (imageUrl.indexOf("localhost") < 0 || imageUrl.indexOf("127.0.0.1") < 0) {
image.value = imageUrl
}
} }
async function login_108() { async function login_108() {
...@@ -343,13 +625,31 @@ async function login_1012() { ...@@ -343,13 +625,31 @@ async function login_1012() {
onMounted(() => { onMounted(() => {
getTemplateList() getTemplateList()
// createImage()
// login_108() // login_108()
login_1012() // login_1012()
}) })
</script> </script>
<style scoped> <style scoped>
.custom-radio-group {
display: flex;
justify-content: flex-start; /* 确保 radio 组内项目从左对齐 */
}
.custom-radio {
display: flex;
align-items: center; /* 确保 radio 和文字在垂直方向居中 */
justify-content: flex-start; /* 确保内容在水平方向左对齐 */
margin-right: 16px; /* 添加间距 */
flex: none; /* 防止 radio 项目拉伸 */
}
.van-radio__label {
text-align: left; /* 强制标签文本左对齐 */
}
.banner { .banner {
width: 100%; width: 100%;
height: 27.73vw; height: 27.73vw;
...@@ -564,4 +864,23 @@ onMounted(() => { ...@@ -564,4 +864,23 @@ onMounted(() => {
.active { .active {
background: #EBCC2F; background: #EBCC2F;
} }
.download {
/* position: fixed; */
/* bottom: 23.73vw; */
/* left: 50%; */
/* transform: translateX(-50%); */
width: 10.67vw;
height: 10.67vw;
border-radius: 100%;
background: #F1F1F1;
display: flex;
justify-content: center;
align-items: center;
}
.download img {
height: 4.27vw;
width: 4.27vw;
}
</style> </style>
...@@ -202,7 +202,7 @@ async function login() { ...@@ -202,7 +202,7 @@ async function login() {
onMounted(() => { onMounted(() => {
// getAccount() // getAccount()
login() // login()
}) })
</script> </script>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment