index.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <!-- dall3 -->
  2. <template>
  3. <div class="prompt">
  4. <el-text tag="b">画面描述</el-text>
  5. <el-text tag="p">建议使用“形容词+动词+风格”的格式,使用“,”隔开.</el-text>
  6. <el-input
  7. v-model="prompt"
  8. maxlength="1024"
  9. rows="5"
  10. style="width: 100%; margin-top: 15px;"
  11. input-style="border-radius: 7px;"
  12. placeholder="例如:童话里的小屋应该是什么样子?"
  13. show-word-limit
  14. type="textarea"
  15. />
  16. </div>
  17. <div class="hot-words">
  18. <div>
  19. <el-text tag="b">随机热词</el-text>
  20. </div>
  21. <el-space wrap class="word-list">
  22. <el-button round
  23. class="btn"
  24. :type="(selectHotWord === hotWord ? 'primary' : 'default')"
  25. v-for="hotWord in hotWords"
  26. :key="hotWord"
  27. @click="handlerHotWordClick(hotWord)"
  28. >
  29. {{ hotWord }}
  30. </el-button>
  31. </el-space>
  32. </div>
  33. <div class="model">
  34. <div>
  35. <el-text tag="b">模型</el-text>
  36. </div>
  37. <el-space wrap class="model-list">
  38. <div
  39. :class="selectModel === model ? 'modal-item selectModel' : 'modal-item'"
  40. v-for="model in models"
  41. :key="model.key"
  42. >
  43. <el-image
  44. :src="model.image"
  45. fit="contain"
  46. @click="handlerModelClick(model)"
  47. />
  48. <div class="model-font">{{model.name}}</div>
  49. </div>
  50. </el-space>
  51. </div>
  52. <div class="image-style">
  53. <div>
  54. <el-text tag="b">样式</el-text>
  55. </div>
  56. <el-space wrap class="image-style-list">
  57. <div
  58. :class="selectImageStyle === imageStyle ? 'image-style-item selectImageStyle' : 'image-style-item'"
  59. v-for="imageStyle in imageStyleList"
  60. :key="imageStyle"
  61. >
  62. <el-image
  63. :src="imageStyle.image"
  64. fit="contain"
  65. @click="handlerStyleClick(imageStyle)"
  66. />
  67. <div class="style-font">{{imageStyle.name}}</div>
  68. </div>
  69. </el-space>
  70. </div>
  71. <div class="image-size">
  72. <div>
  73. <el-text tag="b">尺寸</el-text>
  74. </div>
  75. <el-space wrap class="size-list">
  76. <div class="size-item"
  77. v-for="imageSize in imageSizeList"
  78. :key="imageSize.key"
  79. @click="handlerSizeClick(imageSize)">
  80. <div :class="selectImageSize === imageSize ? 'size-wrapper selectImageSize' : 'size-wrapper'">
  81. <div :style="imageSize.style"></div>
  82. </div>
  83. <div class="size-font">{{ imageSize.name }}</div>
  84. </div>
  85. </el-space>
  86. </div>
  87. <div class="btns">
  88. <!-- <el-button size="large" round>重置内容</el-button>-->
  89. <el-button type="primary" size="large" round @click="handlerGenerateImage">生成内容</el-button>
  90. </div>
  91. </template>
  92. <script setup lang="ts">
  93. import {ImageApi, ImageDallReqVO} from '@/api/ai/image';
  94. // image 模型
  95. interface ImageModelVO {
  96. key: string
  97. name: string
  98. image: string
  99. }
  100. // image 大小
  101. interface ImageSizeVO {
  102. key: string
  103. style: string,
  104. }
  105. // 定义属性
  106. const prompt = ref<string>('') // 提示词
  107. const selectHotWord = ref<string>('') // 选中的热词
  108. const hotWords = ref<string[]>(['中国旗袍', '古装美女', '卡通头像', '机甲战士', '童话小屋', '中国长城']) // 热词
  109. const selectModel = ref<any>({}) // 模型
  110. const models = ref<ImageModelVO[]>([
  111. {
  112. key: 'dall-e-2',
  113. name: 'dall2',
  114. image: 'https://h5.cxyhub.com/images/model_1.png',
  115. },
  116. {
  117. key: 'dall-e-3',
  118. name: 'dall3',
  119. image: 'https://h5.cxyhub.com/images/model_2.png',
  120. },
  121. ]) // 模型
  122. selectModel.value = models.value[0]
  123. const selectImageStyle = ref<any>({}) // style 样式
  124. const imageStyleList = ref<ImageModelVO[]>([
  125. {
  126. key: 'vivid',
  127. name: '清晰',
  128. image: 'https://h5.cxyhub.com/images/model_1.png',
  129. },
  130. {
  131. key: 'natural',
  132. name: '自然',
  133. image: 'https://h5.cxyhub.com/images/model_2.png',
  134. },
  135. ]) // style
  136. selectImageStyle.value = imageStyleList.value[0]
  137. const selectImageSize = ref<ImageSizeVO>({} as ImageSizeVO) // 选中 size
  138. const imageSizeList = ref<ImageSizeVO[]>([
  139. {
  140. key: '1024x1024',
  141. name: '1:1',
  142. style: 'width: 30px; height: 30px;background-color: #dcdcdc;',
  143. },
  144. {
  145. key: '1024x1792',
  146. name: '3:5',
  147. style: 'width: 30px; height: 50px;background-color: #dcdcdc;',
  148. },
  149. {
  150. key: '1792x1024',
  151. name: '5:3',
  152. style: 'width: 50px; height: 30px;background-color: #dcdcdc;',
  153. }
  154. ]) // size
  155. selectImageSize.value = imageSizeList.value[0]
  156. // 定义 Props
  157. const props = defineProps({})
  158. /**
  159. * 热词 - click
  160. */
  161. const handlerHotWordClick = async (hotWord: string) => {
  162. // 取消
  163. if (selectHotWord.value == hotWord) {
  164. selectHotWord.value = ''
  165. return
  166. }
  167. // 选中
  168. selectHotWord.value = hotWord
  169. }
  170. /**
  171. * 模型 - click
  172. */
  173. const handlerModelClick = async (model: ImageModelVO) => {
  174. if (selectModel.value === model) {
  175. selectModel.value = {} as ImageModelVO
  176. return
  177. }
  178. selectModel.value = model
  179. }
  180. /**
  181. * 样式 - click
  182. */
  183. const handlerStyleClick = async (imageStyle: ImageModelVO) => {
  184. if (selectImageStyle.value === imageStyle) {
  185. selectImageStyle.value = {} as ImageModelVO
  186. return
  187. }
  188. selectImageStyle.value = imageStyle
  189. }
  190. /**
  191. * size - click
  192. */
  193. const handlerSizeClick = async (imageSize: ImageSizeVO) => {
  194. if (selectImageSize.value === imageSize) {
  195. selectImageSize.value = {} as ImageSizeVO
  196. return
  197. }
  198. selectImageSize.value = imageSize
  199. }
  200. /**
  201. * 图片生产
  202. */
  203. const handlerGenerateImage = async () => {
  204. // todo @范 图片生产逻辑
  205. console.log('prompt.value', prompt)
  206. console.log('prompt.value', prompt.value)
  207. const form = {
  208. prompt: prompt.value, // 提示词
  209. model: selectModel.value.key, // 模型
  210. style: selectImageStyle.value.key, // 图像生成的风格
  211. size: selectImageSize.value.key, // size不能为空
  212. } as ImageDallReqVO
  213. // 发送请求
  214. await ImageApi.dall(form)
  215. }
  216. </script>
  217. <style scoped lang="scss">
  218. // 提示词
  219. .prompt {
  220. }
  221. // 热词
  222. .hot-words {
  223. display: flex;
  224. flex-direction: column;
  225. margin-top: 30px;
  226. .word-list {
  227. display: flex;
  228. flex-direction: row;
  229. flex-wrap: wrap;
  230. justify-content: start;
  231. margin-top: 15px;
  232. .btn {
  233. margin: 0;
  234. }
  235. }
  236. }
  237. // 模型
  238. .model {
  239. margin-top: 30px;
  240. .model-list {
  241. margin-top: 15px;
  242. .modal-item {
  243. width: 110px;
  244. //outline: 1px solid blue;
  245. overflow: hidden;
  246. display: flex;
  247. flex-direction: column;
  248. align-items: center;
  249. border: 3px solid transparent;
  250. cursor: pointer;
  251. .model-font {
  252. font-size: 14px;
  253. color: #3e3e3e;
  254. font-weight: bold;
  255. }
  256. }
  257. .selectModel {
  258. border: 3px solid #1293ff;
  259. border-radius: 5px;
  260. }
  261. }
  262. }
  263. // 样式 style
  264. .image-style {
  265. margin-top: 30px;
  266. .image-style-list {
  267. margin-top: 15px;
  268. .image-style-item {
  269. width: 110px;
  270. //outline: 1px solid blue;
  271. overflow: hidden;
  272. display: flex;
  273. flex-direction: column;
  274. align-items: center;
  275. border: 3px solid transparent;
  276. cursor: pointer;
  277. .style-font {
  278. font-size: 14px;
  279. color: #3e3e3e;
  280. font-weight: bold;
  281. }
  282. }
  283. .selectImageStyle {
  284. border: 3px solid #1293ff;
  285. border-radius: 5px;
  286. }
  287. }
  288. }
  289. // 尺寸
  290. .image-size {
  291. width: 100%;
  292. margin-top: 30px;
  293. .size-list {
  294. display: flex;
  295. flex-direction: row;
  296. justify-content: space-between;
  297. width: 100%;
  298. margin-top: 20px;
  299. .size-item {
  300. display: flex;
  301. flex-direction: column;
  302. align-items: center;
  303. cursor: pointer;
  304. .size-wrapper {
  305. display: flex;
  306. flex-direction: column;
  307. align-items: center;
  308. justify-content: center;
  309. border-radius: 7px;
  310. padding: 4px;
  311. width: 50px;
  312. height: 50px;
  313. background-color: #fff;
  314. border: 1px solid #fff;
  315. }
  316. .size-font {
  317. font-size: 14px;
  318. color: #3e3e3e;
  319. font-weight: bold;
  320. }
  321. }
  322. }
  323. .selectImageSize {
  324. border: 1px solid #1293ff !important;
  325. }
  326. }
  327. .btns {
  328. display: flex;
  329. justify-content: center;
  330. margin-top: 50px;
  331. }
  332. </style>