ImageTaskCard.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <template>
  2. <el-card body-class="" class="image-card">
  3. <div class="image-operation">
  4. <div>
  5. <el-button type="primary" text bg v-if="imageDetail?.status === 10">生成中</el-button>
  6. <el-button text bg v-else-if="imageDetail?.status === 20">已完成</el-button>
  7. <el-button type="danger" text bg v-else-if="imageDetail?.status === 30">异常</el-button>
  8. </div>
  9. <!-- TODO @fan:1)按钮要不调整成详情、下载、再次生成、删除?;2)如果是再次生成,就把当前的参数填写到左侧的框框里? -->
  10. <div>
  11. <el-button class="btn" text :icon="Download"
  12. @click="handlerBtnClick('download', imageDetail)"/>
  13. <el-button class="btn" text :icon="Delete" @click="handlerBtnClick('delete', imageDetail)"/>
  14. <el-button class="btn" text :icon="More" @click="handlerBtnClick('more', imageDetail)"/>
  15. </div>
  16. </div>
  17. <div class="image-wrapper" ref="cardImageRef">
  18. <!-- TODO @fan:要不加个点击,大图预览? -->
  19. <img class="image" :src="imageDetail?.picUrl"/>
  20. <div v-if="imageDetail?.status === 30">{{imageDetail?.errorMessage}}</div>
  21. </div>
  22. <!-- TODO @fan:style 使用 unocss 替代下 -->
  23. <div class="image-mj-btns">
  24. <el-button size="small" v-for="button in imageDetail?.buttons" :key="button"
  25. style="min-width: 40px;margin-left: 0; margin-right: 10px; margin-top: 5px;"
  26. @click="handlerMjBtnClick(button)"
  27. >
  28. {{ button.label }}{{ button.emoji }}
  29. </el-button>
  30. </div>
  31. </el-card>
  32. </template>
  33. <script setup lang="ts">
  34. import {Delete, Download, More} from "@element-plus/icons-vue";
  35. import {ImageDetailVO, ImageMjButtonsVO} from "@/api/ai/image";
  36. import {PropType} from "vue";
  37. import {ElLoading} from "element-plus";
  38. const cardImageRef = ref<any>() // 卡片 image ref
  39. const cardImageLoadingInstance = ref<any>() // 卡片 image ref
  40. const props = defineProps({
  41. imageDetail: {
  42. type: Object as PropType<ImageDetailVO>,
  43. require: true
  44. }
  45. })
  46. /** 按钮 - 点击事件 */
  47. const handlerBtnClick = async (type, imageDetail: ImageDetailVO) => {
  48. emits('onBtnClick', type, imageDetail)
  49. }
  50. const handlerLoading = async (status: number) => {
  51. // TODO @fan:这个搞成 Loading 组件,然后通过数据驱动,这样搞可以哇?
  52. if (status === 10) {
  53. cardImageLoadingInstance.value = ElLoading.service({
  54. target: cardImageRef.value,
  55. text: '生成中...'
  56. })
  57. } else {
  58. if (cardImageLoadingInstance.value) {
  59. cardImageLoadingInstance.value.close();
  60. cardImageLoadingInstance.value = null;
  61. }
  62. }
  63. }
  64. /** mj 按钮 click */
  65. const handlerMjBtnClick = async (button: ImageMjButtonsVO) => {
  66. emits('onMjBtnClick', button, props.imageDetail)
  67. }
  68. // watch
  69. const { imageDetail } = toRefs(props)
  70. watch(imageDetail, async (newVal, oldVal) => {
  71. await handlerLoading(newVal.status as string)
  72. })
  73. // emits
  74. const emits = defineEmits(['onBtnClick', 'onMjBtnClick'])
  75. //
  76. onMounted(async () => {
  77. await handlerLoading(props.imageDetail.status as string)
  78. })
  79. </script>
  80. <style scoped lang="scss">
  81. .image-card {
  82. width: 320px;
  83. height: auto;
  84. border-radius: 10px;
  85. position: relative;
  86. display: flex;
  87. flex-direction: column;
  88. .image-operation {
  89. display: flex;
  90. flex-direction: row;
  91. justify-content: space-between;
  92. .btn {
  93. //border: 1px solid red;
  94. padding: 10px;
  95. margin: 0;
  96. }
  97. }
  98. .image-wrapper {
  99. overflow: hidden;
  100. margin-top: 20px;
  101. height: 280px;
  102. flex: 1;
  103. .image {
  104. width: 100%;
  105. border-radius: 10px;
  106. }
  107. }
  108. .image-mj-btns {
  109. margin-top: 5px;
  110. width: 100%;
  111. display: flex;
  112. flex-direction: row;
  113. flex-wrap: wrap;
  114. justify-content: flex-start;
  115. }
  116. }
  117. </style>