index.vue 6.6 KB
<template>
  <div v-if="cardData" class="go-items-list-card">
    <n-card hoverable size="small">
      <template v-if="operationKey">
        <n-checkbox v-model:checked="cardData.checkedValue"> </n-checkbox>
      </template>
      <div class="list-content">
        <div class="list-content-img" @click="editHandle()">
          <n-image object-fit="fill" height="180" width="350" preview-disabled :src="requestImag(cardData.imageUrl)"
            :alt="cardData.name" :fallback-src="requireErrorImg()"></n-image>
        </div>
      </div>
      <template #action>
        <div class="go-flex-items-center list-footer" justify="space-between">
          <div class="go-ellipsis-1" style="display: flex; flex-direction: column; align-items: start">
            <n-tooltip trigger="hover">
              <template #trigger>
                <n-text v-if="!focus" @click="handleFocus">
                  <n-button class="list-footer-button" secondary size="tiny">
                    <span class="title">
                      {{ cardData.name || cardData.id }}
                    </span>
                  </n-button>
                </n-text>
                <n-input v-else ref="inputInstRef" size="small" type="text" maxlength="16" show-count
                  v-model:value.trim="title" @blur="handleBlur"></n-input>
              </template>
              {{ cardData.name || cardData.id }}
            </n-tooltip>
            <n-text style="font-size: 12px; margin-left: 6px">{{ cardData.createTime }}</n-text>
          </div>
          <!-- 工具 -->
          <div class="go-flex-items-center list-footer-ri">
            <n-space>
              <n-text>
                <n-badge class="go-animation-twinkle" dot
                  :color="cardData.state === 1 ? '#34c749' : '#fcbc40'"></n-badge>
                {{ cardData.state === 1 ? $t('project.release') : $t('project.unreleased') }}
              </n-text>

              <template v-for="item in fnBtnList" :key="item.key">
                <template v-if="item.key === 'select'">
                  <n-dropdown trigger="hover" placement="bottom" :options="[
                    {
                      label: cardData?.state ? renderLang('global.r_unpublish') : renderLang('global.r_publish'),
                      key: 'release',
                      icon: renderIcon(SendIcon)
                    },
                    {
                      label: renderLang('global.r_delete'),
                      key: 'delete',
                      icon: renderIcon(TrashIcon)
                    }
                  ]" :show-arrow="true" @select="handleSelect">
                    <n-button size="small">
                      <template #icon>
                        <component :is="item.icon"></component>
                      </template>
                    </n-button>
                  </n-dropdown>
                </template>

                <n-tooltip v-else placement="bottom" trigger="hover">
                  <template #trigger>
                    <n-button size="small" @click="handleSelect(item.key)">
                      <template #icon>
                        <component :is="item.icon"></component>
                      </template>
                    </n-button>
                  </template>
                  <component :is="item.label"></component>
                </n-tooltip>
              </template>
            </n-space>
          </div>
          <!-- end -->
        </div>
      </template>
    </n-card>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, PropType, nextTick } from 'vue'
import { renderIcon, renderLang, requireErrorImg } from '@/utils'
import { icon } from '@/plugins'
import { ChartType } from '../..'
import { updateThreeJsModel } from '@/api/external/contentSave/content'

const { EllipsisHorizontalCircleSharpIcon, TrashIcon, PencilIcon, SendIcon } = icon.ionicons5

const emit = defineEmits(['delete', 'resize', 'edit', 'release', 'inputUpdateCard'])

const props = defineProps({
  cardData: Object as PropType<ChartType>,
  operationKey: String
})

// 处理url获取
const requireUrl = (name: string) => {
  return new URL(`../../../../../assets/images/${name}`, import.meta.url).href
}

const focus = ref<boolean>(false)

const inputInstRef = ref(null)

const title = ref<string>('')

const fnBtnList = reactive([
  {
    label: renderLang('global.r_edit'),
    key: 'edit',
    icon: renderIcon(PencilIcon)
  },
  {
    label: renderLang('global.r_more'),
    key: 'select',
    icon: renderIcon(EllipsisHorizontalCircleSharpIcon)
  }
])

const handleSelect = (key: string) => {
  switch (key) {
    case 'delete':
      deleteHandle()
      break
    case 'release':
      releaseHandle()
      break
    case 'edit':
      editHandle()
      break
  }
}

// 删除处理
const deleteHandle = () => {
  emit('delete', props.cardData)
}

// 编辑处理
const editHandle = () => {
  emit('edit', props.cardData)
}

// 发布处理
const releaseHandle = () => {
  emit('release', props.cardData)
}

const handleFocus = () => {
  focus.value = true
  nextTick(() => {
    inputInstRef.value && (inputInstRef.value as any).focus()
  })
}

const handleBlur = async () => {
  focus.value = false
  if (!title.value) return
  await updateThreeJsModel({
    id: props.cardData?.id as string,
    name: title.value
  })
  emit('inputUpdateCard')
  window['$message'].success(window['$t']('common.operationSuccessText'))
}

const requestImag = (imageUrl: string | undefined) => {
  return !imageUrl ? requireUrl('ThreeModelDefault.svg') : imageUrl
}
</script>

<style lang="scss" scoped>
$contentHeight: 180px;

@include go('items-list-card') {
  position: relative;
  border-radius: $--border-radius-base;
  border: 1px solid rgba(0, 0, 0, 0);
  @extend .go-transition;

  // &:hover {
  //   @include hover-border-color('hover-border-color');
  // }
  .list-content {
    cursor: pointer;
    border-radius: $--border-radius-base;

    // @include background-image('background-point');
    // @extend .go-point-bg;
    &-top {
      position: absolute;
      top: 10px;
      left: 10px;
      height: 22px;
    }

    &-img {
      height: $contentHeight;
      @extend .go-flex-center;
      @extend .go-border-radius;

      @include deep() {
        img {
          @extend .go-border-radius;
        }
      }
    }
  }

  .list-footer {
    flex-wrap: nowrap;
    justify-content: space-between;
    line-height: 30px;

    &-ri {
      justify-content: flex-end;
      min-width: 180px;
    }

    .list-footer-button {
      display: flex;
      // justify-content: flex-start;
      width: 125px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
</style>