修改了MJ界面,目前还是静态页面版

This commit is contained in:
carter 2024-08-19 09:56:38 +08:00
parent d26f953d4d
commit 019ad90085
10 changed files with 662 additions and 470 deletions

View File

@ -0,0 +1,7 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,5 +1,6 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
import naive from 'naive-ui'
import '@/styles/lib/viewer.css' import '@/styles/lib/viewer.css'
import VueViewer from 'v-viewer' import VueViewer from 'v-viewer'
import App from './App.vue' import App from './App.vue'
@ -17,6 +18,7 @@ window.$message = useMessage()
async function bootstrap() { async function bootstrap() {
const app = createApp(App) const app = createApp(App)
app.use(VueViewer) app.use(VueViewer)
app.use(naive)
app.use(MotionPlugin) app.use(MotionPlugin)
setupAssets() setupAssets()
setupScrollbarStyle() setupScrollbarStyle()

View File

@ -0,0 +1,18 @@
<script setup lang="ts">
import MjBot from '@/assets/images/MidjourneyBot.png'
</script>
<template>
<n-flex vertical class="p-2">
<!-- header -->
<n-flex align="start">
<n-avatar round size="large" :src="MjBot" />
</n-flex>
<!-- content -->
</n-flex>
</template>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,69 @@
<script setup>
import { ref, watch } from 'vue'
const props = defineProps({
ratios: {
type: Array,
default: () => [
{ value: '1:1', name: '头像' },
{ value: '3:2', name: '文章配图' },
{ value: '3:4', name: '社交媒体' },
{ value: '4:3', name: '公众号配图' },
{ value: '9:16', name: '海报图' },
],
},
})
const emit = defineEmits(['update:modelValue'])
const selectedRatio = ref('')
const customRatio = ref({ width: 1, height: 2 })
const selectRatio = (ratio) => {
selectedRatio.value = ratio
emit('update:modelValue', ratio)
}
watch(customRatio, (newValue) => {
const ratio = `${newValue.width}:${newValue.height}`
selectRatio(ratio)
}, { deep: true })
const onlyAllowNumber = value => !value || /^\d+$/.test(value)
</script>
<template>
<div class=" p-1 rounded-lg">
<div class="grid grid-cols-5 gap-1 mb-2">
<button
v-for="(ratio, index) in ratios" :key="index"
class=" rounded border-gray-400 text-sm min-w-10 flex flex-col justify-center items-center"
:class="{ 'text-blue-400': selectedRatio === ratio.value }"
style="font-size: 10px; border-width: 1px ;"
@click="selectRatio(ratio.value)"
>
<span>{{ ratio.value }}</span>
<span>{{ ratio.name }}</span>
</button>
</div>
<div class="grid grid-cols-2 gap-1 ">
<button
class=" rounded border-gray-500 text-sm min-w-10 flex flex-col justify-center items-center"
:class="{ 'text-blue-400': selectedRatio === '16:9' }"
style="font-size: 10px; border-width: 1px ;"
@click="selectRatio('16:9')"
>
<span>16:9</span>
<span>电脑壁纸</span>
</button>
<div class="flex flex-col justify-center items-center border-gray-500 rounded px-2" style="border-width: 1px; font-size: 10px;">
<span class="mr-2" :class="{ 'text-blue-400': ratios.map(item => item.value).includes(selectedRatio) === -1 && selectedRatio !== '16:9' }">自定义</span>
<div class="grid grid-cols-9 items-center">
<n-input v-model:value="customRatio.width" type="text" :allow-input="onlyAllowNumber" class=" col-span-4" size="tiny" />
<span class="mx-1">:</span>
<n-input v-model:value="customRatio.height" type="text" :allow-input="onlyAllowNumber" class=" col-span-4" size="tiny" />
</div>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,37 @@
<script setup lang="ts">
import { ArrowRedoCircle } from '@vicons/ionicons5'
</script>
<template>
<n-thing class="relative">
<n-input
placeholder="输入你想要生成的图片内容,中文也可以"
class="w-full pt-2 pr-2 pl-2 pb-12 rounded"
size="small"
type="textarea"
clearable
:autosize="{
minRows: 2,
maxRows: 2,
}"
/>
<n-flex class="absolute bottom-0 w-full p-2 rounded" justify="space-between">
<n-flex>
<n-select />
</n-flex>
<br>
<n-button color="#3074F8FF">
<template #icon>
<n-icon>
<ArrowRedoCircle />
</n-icon>
</template>
发送
</n-button>
</n-flex>
</n-thing>
</template>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,37 @@
<script setup lang="ts">
import { InformationCircle } from '@vicons/ionicons5'
const prop = defineProps({
title: {
type: String,
require: true,
},
descriptions: {
type: Array as () => string[],
require: true,
},
})
</script>
<template>
<div class="flex items-center space-x-2 ">
<n-text>
{{ prop.title }}
</n-text>
<n-popover trigger="hover" placement="right">
<template #trigger>
<n-icon size="18">
<InformationCircle />
</n-icon>
</template>
<div class="flex flex-col">
<span v-for="(description, index) in prop.descriptions" :key="index">
{{ description }}
</span>
</div>
</n-popover>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,49 @@
<script lang="ts" setup>
import { ref } from 'vue'
import nijiImg from '@/assets/images/niji.png'
import mjImg from '@/assets/images/mj.png'
interface Option {
title: string
image: string
v: string
}
const emit = defineEmits<{
(e: 'select', v: string): void
}>()
const options: Option[] = [
{ title: 'Midjourney', image: mjImg, v: 'MJ' },
{ title: 'Niji', image: nijiImg, v: 'NIJI' },
]
const selected = ref<number | null>(0)
const selectOption = (index: number) => {
selected.value = index
emit('select', options[index].v)
}
</script>
<template>
<div class="flex space-x-4">
<div
v-for="(option, index) in options"
:key="index"
class="relative cursor-pointer transition-all duration-300 ease-in-out rounded-lg border-2 p-4 w-32 h-12"
:class="[
selected === index ? 'border-blue-500' : 'border-gray-300',
]"
@click="selectOption(index)"
>
<div
class="absolute inset-0 bg-cover bg-center transition-opacity duration-300 ease-in-out rounded"
:style="{ backgroundImage: `url(${option.image})` }"
:class="[selected === index ? 'opacity-100' : 'opacity-50']"
/>
<div class="relative z-10 text-white font-bold flex justify-center">
{{ option.title }}
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,256 @@
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFileInfo } from 'naive-ui'
import modelSelect from './modelSelect.vue'
import Mjp from '@/views/midjourney/components/mjp.vue'
import MjRatio from '@/views/midjourney/components/mjRatio.vue'
// const modelList = [
// { name: 'MJ', img: mjImg, val: 'mj' },
// { name: 'NIJI', img: nijiImg, val: 'niji' },
// ]
interface modelVersion {
MJ: string[]
NIJI: string[]
}
interface MjParamter {
model: string
version: string
selectedRatio: string
feature: string
chaos: number
stylize: number
base64Array: string[]
iw: number
cref: number
sref: number
}
const containerRef = ref<HTMLElement | undefined>(undefined)
const mjParamter = ref<MjParamter>({
model: 'MJ',
version: 'V6.1',
selectedRatio: '1:1',
feature: '',
chaos: 0,
stylize: 1,
base64Array: [],
iw: 0.3,
cref: 100,
sref: 180,
})
const featureList = [
{ label: '普通', vallue: '.25' },
{ label: '一般', vallue: '.5' },
{ label: '高清', vallue: '1' },
{ label: '超高清', vallue: '2' },
]
const defaultImages = ref<UploadFileInfo[]>([])
const crefImages = ref<UploadFileInfo[]>([])
const modelVersionList = ref<modelVersion>({
MJ: ['V6.1', 'V6', 'V5.2', 'V5.1', 'V5'],
NIJI: ['V6.1', 'V6', 'V5'],
})
const onlyAllowNumber = (value: string | number): boolean => {
if (typeof value === 'number')
return value <= 4294967295
return !value || /^\d+$/.test(value)
}
</script>
<template>
<div ref="containerRef" class="min-h-screen light:text-gray-400 flex-col space-y-4 relative">
<div class="space-y-1">
<Mjp title="模型选择" :descriptions="['MJ: 偏真实通用模型', 'NIJI: 偏动漫风格、适用于二次元模型']" />
<div>
<modelSelect @select="v => { mjParamter.model = v }" />
</div>
</div>
<div>
<n-grid cols="6" class="flex items-center">
<n-grid-item span="1">
<n-text>
版本
</n-text>
</n-grid-item>
<n-grid-item span="5">
<n-radio-group v-model:value="mjParamter.version" name="radio" class="rounded" size="small">
<n-radio-button v-for="item in modelVersionList[mjParamter.model]" :key="item" size="small" :value="item" :label="item" />
</n-radio-group>
</n-grid-item>
</n-grid>
</div>
<div class="space-y-1">
<Mjp title="图片比例" :descriptions="['参数释义:生成图片尺寸比例']" />
<div>
<MjRatio />
</div>
</div>
<div>
<n-grid cols="16" class="items-center">
<n-grid-item span="4">
<n-text>
品质
</n-text>
</n-grid-item>
<n-grid-item span="12" class="flex justify-end">
<n-radio-group v-model:value="mjParamter.feature" name="featureRadio" class="rounded" size="small">
<n-radio-button v-for="item in featureList" :key="item.vallue" :value="item.vallue" size="small" :label="item.label" />
</n-radio-group>
</n-grid-item>
</n-grid>
</div>
<div class="space-y-1">
<n-flex justify="space-between">
<Mjp title="混乱程度" :descriptions="['取值范围0-100、 --chaos 或 --c', '混乱级别可以理解为让AI天马行空的空间', '值越小越可靠、默认0最为精准']" />
<br>
<n-flex>
<n-text>
当前程度:
</n-text>
<div class="w-20">
<n-input-number v-model:value="mjParamter.chaos" size="tiny" :max="100" :min="0" />
</div>
</n-flex>
</n-flex>
<div>
<n-slider v-model:value="mjParamter.chaos" style="--n-fill-color:rgb(90, 145, 252);--n-fill-color-hover:rgb(62,116,222)" size="small" />
</div>
</div>
<div class="space-y-1">
<n-flex justify="space-between">
<Mjp title="风格化程度" :descriptions="['风格化:--stylize 或 --s范围 1-', '1000参数释义数值越高画面表现', '也会更具丰富性和艺术性']" />
<br>
<n-flex>
<n-text>
当前程度:
</n-text>
<div class="w-20">
<n-input-number v-model:value="mjParamter.stylize" size="tiny" :max="1000" :min="0" />
</div>
</n-flex>
</n-flex>
<div>
<n-slider v-model:value="mjParamter.stylize" :max="1000" :min="0" style="--n-fill-color:rgb(90, 145, 252);--n-fill-color-hover:rgb(62,116,222)" size="small" />
</div>
</div>
<div>
<n-flex justify="space-between">
<Mjp title="Seed" :descriptions="['种子数是为每个图像随机生成的,', '如果您使用相同的种子号和提示,', '您将获得相似的最终图像。', '范围为04294967295的整数。', '您可以在右侧找到喜欢的图片获取到此值!']" />
<br>
<div>
<n-input :allow-input="onlyAllowNumber" size="tiny" class="text-center" />
</div>
</n-flex>
</div>
<div class="space-y-2">
<Mjp title="垫图生图(普通参考图)" :descriptions="['普通参考图、数量最多五张', '参数的范围是0-33代表与原图最接近']" />
<n-upload
:default-file-list="defaultImages"
list-type="image-card"
:max="5"
>
点击上传
</n-upload>
</div>
<div class="space-y-2">
<n-flex justify="space-between">
<Mjp title="普通参考图权重" :descriptions="['数值越大对绘制结果影响越大']" />
<br>
<n-flex>
<n-text>
当前程度:
</n-text>
<div class="w-20">
<n-input-number v-model:value="mjParamter.iw" size="tiny" :max="3" :min="0" :step="0.01" />
</div>
</n-flex>
</n-flex>
<div>
<n-slider v-model:value="mjParamter.iw" :max="3" :step="0.01" :min="0" style="--n-fill-color:rgb(90, 145, 252);--n-fill-color-hover:rgb(62,116,222)" size="small" />
</div>
</div>
<div class="space-y-2">
<Mjp title="垫图生图(角色一致参考图)" :descriptions="['角色一致参考图、数量最多两张', '参数的范围是0-100', '0表示人脸100表示脸、头发和全身']" />
<n-upload
:default-file-list="crefImages"
list-type="image-card"
:max="2"
>
点击上传
</n-upload>
</div>
<div class="space-y-2">
<n-flex justify="space-between">
<Mjp title="角色一致参考图权重" :descriptions="['数值越大对绘制结果影响越大']" />
<br>
<n-flex>
<n-text>
当前程度:
</n-text>
<div class="w-16">
<n-input-number v-model:value="mjParamter.cref" size="tiny" :max="100" :min="0" />
</div>
</n-flex>
</n-flex>
<div>
<n-slider v-model:value="mjParamter.cref" :max="100" :min="0" style="--n-fill-color:rgb(90, 145, 252);--n-fill-color-hover:rgb(62,116,222)" size="small" />
</div>
</div>
<div class="space-y-2">
<Mjp title="垫图生图(风格一致参考图)" :descriptions="['风格一致参考图', '参数的范围是0-1000', '0表示不使用风格', '不能和角色一致垫图一起使用!']" />
<n-upload
:default-file-list="crefImages"
list-type="image-card"
:max="2"
>
点击上传
</n-upload>
</div>
<div class="space-y-2 pb-6">
<n-flex justify="space-between">
<Mjp title="风格一致参考图权重" :descriptions="['数值越大对绘制结果影响越大']" />
<br>
<n-flex>
<n-text>
当前程度:
</n-text>
<div class="w-16">
<n-input-number v-model:value="mjParamter.sref" size="tiny" :max="1000" :min="0" />
</div>
</n-flex>
</n-flex>
<div>
<n-slider v-model:value="mjParamter.sref" :max="1000" :min="0" style="--n-fill-color:rgb(90, 145, 252);--n-fill-color-hover:rgb(62,116,222)" size="small" />
</div>
</div>
<!-- <div>-->
<!-- <n-affix :bottom="0" :trigger-bottom="50" class="w-72 bg-[#f8f8f8] dark:bg-[#18181c] left-16 h-16" position="fixed" :listen-to="() => containerRef">-->
<!-- <n-flex>-->
<!-- <n-text>-->
<!-- 绘画积分余额-->
<!-- </n-text>-->
<!-- </n-flex>-->
<!-- </n-affix>-->
<!-- </div>-->
</div>
</template>
<style scoped>
.absolute-anchor-container {
width: 100%;
height: 200px;
position: relative;
}
.containerRef {
height: 200px;
background-color: rgba(128, 128, 128, 0.3);
border-radius: 3px;
overflow: auto;
}
</style>

File diff suppressed because one or more lines are too long