index.vue 8.95 KB
<template>
  <div class="go-items-list">
    <!-- 搜索区域 -->
    <n-form ref="formRef" label-placement="left" label-width="auto" :model="formValue" :size="formSize">
      <n-grid :cols="24" :x-gap="24">
        <n-grid-item :span="6" label="Input" path="name">
          <n-form-item :label="t('business.threeFormSearch.name')" path="name">
            <n-input v-model:value="formValue.name" :placeholder="t('business.threeFormSearch.placeholderName')" />
          </n-form-item>
        </n-grid-item>
        <n-grid-item :span="6" label="Select" path="state">
          <n-form-item :label="t('business.threeFormSearch.state')" path="state">
            <n-select
              v-model:value="formValue.state"
              :placeholder="t('business.threeFormSearch.placeholderState')"
              :options="statusOptions"
            />
          </n-form-item>
        </n-grid-item>
        <n-grid-item :span="8">
          <n-button type="primary" @click="handleSearchClick">
            <template #icon>
              <n-icon>
                <SearchIcon />
              </n-icon>
            </template>
            {{ t('business.threeFormSearch.search') }}
          </n-button>
          <n-button style="margin-left: 20px" @click="handleResetClick">
            <template #icon>
              <n-icon>
                <ReloadSearch />
              </n-icon>
            </template>
            {{ t('business.threeFormSearch.reset') }}
          </n-button>
        </n-grid-item>
      </n-grid>
    </n-form>
    <div v-show="loading">
      <go-loading></go-loading>
    </div>
    <div v-show="!loading">
      <div style="display: flex; flex-direction: row-reverse">
        <n-space>
          <n-button type="primary" @click="handleOpenThreeEditor"> {{ t('business.threeFormSearch.add') }} </n-button>
          <n-button v-if="list.length" @click="handleSelectAll" type="info">
            {{
              selectAllTextFlag ? t('business.threeFormSearch.selectAll') : t('business.threeFormSearch.selectUnAll')
            }}
          </n-button>
          <n-dropdown
            v-if="list.length"
            :disabled="isBulkOperationFlag"
            trigger="hover"
            :options="operationOptions"
            @select="handleOperationSelect"
          >
            <n-button :disabled="isBulkOperationFlag"> {{ t('business.threeFormSearch.batchOperate') }} </n-button>
          </n-dropdown>
        </n-space>
      </div>
      <n-grid
        v-if="list && list.length"
        style="margin-top: 16px"
        :x-gap="20"
        :y-gap="20"
        cols="2 s:2 m:3 l:4 xl:4 xxl:4"
        responsive="screen"
      >
        <n-grid-item v-for="(item, index) in list" :key="item.id">
          <div style="display: none">{{ index }}</div>
          <project-items-card
            :cardData="item"
            :operationKey="operationKey"
            @resize="resizeHandle"
            @delete="deleteHandle(item)"
            @release="releaseHandle(item)"
            @edit="editHandle"
            @inputUpdateCard="inputUpdateHandle"
          ></project-items-card>
        </n-grid-item>
      </n-grid>
      <div v-else style="height: calc(100vh - 40vh); display: flex; align-items: center; justify-content: center">
        <n-empty :description="t('business.threeFormSearch.noData')">
          <template #extra> </template>
        </n-empty>
      </div>
    </div>
    <div class="list-pagination">
      <n-pagination
        :page="pagination.page"
        :page-size="pagination.pageSize"
        :item-count="pagination.count"
        :page-sizes="[8, 16, 24, 32]"
        @update:page="changePage"
        @update:page-size="changeSize"
        show-size-picker
      >
        <template #prefix>
          {{ t('business.threeFormSearch.all') }} {{ pagination.count }} {{ t('business.threeFormSearch.count') }}
        </template>
      </n-pagination>
    </div>
  </div>
  <project-items-modal-card
    v-if="modalData"
    :modalShow="modalShow"
    :cardData="modalData"
    @close="closeModal"
    @edit="editHandle"
  ></project-items-modal-card>
</template>

<script setup lang="ts">
import { ProjectItemsCard } from '../ProjectItemsCard/index'
import { ProjectItemsModalCard } from '../ProjectItemsModalCard/index'
import { useModalDataInit } from './hooks/useModal.hook'
import { useDataListInit } from './hooks/useData.hook'
import { ref } from 'vue'
import type { FormInst } from 'naive-ui'
import { icon } from '@/plugins'
import { generateUUIDv4 } from '@/utils/utils'
import { threeJsDeleteApi, putReleaseThreeJsModel } from '@/api/external/contentSave/content'
import { ChartType } from '../..'
import { DialogEnum } from '@/enums/pluginEnum'
import { goDialog } from '@/utils'

const { SearchIcon, ReloadSearch } = icon.ionicons5

const t = window['$t']

const { modalData, modalShow, closeModal, resizeHandle, editHandle } = useModalDataInit()

const formRef = ref<FormInst | null>(null)

const formSize = ref('medium')

const formValue = ref({
  name: '',
  state: null
})

const statusOptions = ref([
  {
    label:  t('business.threeFormSearch.release'),
    value: 'yes'
  },
  {
    label: t('business.threeFormSearch.unRelease'),
    value: 'no'
  }
])

const operationKey = ref('')

const operationOptions = [
  {
    label: t('business.threeFormSearch.batchDelete'),
    key: 'Bulk delete'
  },
  {
    label: t('business.threeFormSearch.batchRelease'),
    key: 'Bulk release'
  },
  {
    label: t('business.threeFormSearch.batchUnRelease'),
    key: 'Bulk un release'
  }
]

const resetSelect = (list: ChartType[], flag: boolean) => {
  list.forEach(item => {
    item.checkedValue = flag
  })
}

const releaseGoDialog = (message: string, state: number, messageText: string) => {
  goDialog({
    type: DialogEnum.DELETE,
    promise: true,
    message,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    onPositiveCallback: () => {},
    promiseResCallback: async () => {
      // eslint-disable-next-line no-case-declarations
      const bulkDeleteIds = list.value
        ?.filter((item: ChartType) => item.checkedValue)
        ?.map((item: ChartType) => item.id)
      await putReleaseThreeJsModel(state, bulkDeleteIds as unknown as string[])
      window['$message'].success(window['$t'](messageText))
      setTimeout(() => {
        handleSearchClick()
      }, 500)
      isBulkOperationFlag.value = true
      selectAllTextFlag.value = true
      operationKey.value = ''
      resetSelect(list.value, false)
    }
  })
}

const handleOperationSelect = async (key: string) => {
  operationKey.value = key
  switch (key) {
    case 'Bulk delete':
      goDialog({
        type: DialogEnum.DELETE,
        promise: true,
        message: t('business.threeFormSearch.m1'),
        // eslint-disable-next-line @typescript-eslint/no-empty-function
        onPositiveCallback: () => {},
        promiseResCallback: async () => {
          // eslint-disable-next-line no-case-declarations
          const bulkDeleteIds = list.value
            ?.filter((item: ChartType) => item.checkedValue)
            ?.map((item: ChartType) => item.id)
          await threeJsDeleteApi([bulkDeleteIds] as unknown as string[])
          window['$message'].success(window['$t']('common.deleteSuccessText'))
          setTimeout(() => {
            handleSearchClick()
          }, 500)
          isBulkOperationFlag.value = true
          selectAllTextFlag.value = true
          operationKey.value = ''
          resetSelect(list.value, false)
        }
      })
      break
    case 'Bulk release':
      releaseGoDialog(t('business.threeFormSearch.m2'), 1, 'common.releaseSuccessText')
      break
    case 'Bulk un release':
      releaseGoDialog(t('business.threeFormSearch.m3'), 0, 'common.cancelReleaseSuccessText')
      break
  }
}

const {
  loading,
  pagination,
  list,
  changeSize,
  changePage,
  deleteHandle,
  releaseHandle,
  inputUpdateHandle,
  handleSearchClick
} = useDataListInit(formValue.value)

const isBulkOperationFlag = ref(true)

const selectAllTextFlag = ref(true)

const handleSelectAll = () => {
  selectAllTextFlag.value = !selectAllTextFlag.value
  if (!selectAllTextFlag.value) {
    resetSelect(list.value, true)
    isBulkOperationFlag.value = false
    operationKey.value = 'Bulk delete'
  } else {
    resetSelect(list.value, false)
    isBulkOperationFlag.value = true
    operationKey.value = ''
  }
}

const handleResetClick = () => {
  formValue.value.name = ''
  formValue.value.state = null
  handleSearchClick()
}

const handleOpenThreeEditor = () => {
  const { host, protocol, pathname } = location
  const randomId = generateUUIDv4()
  window.open(`${protocol}//${host}${pathname}editor/?three_file_uuid=${randomId}&action_type=create`)
}
</script>

<style lang="scss" scoped>
$contentHeight: 250px;
@include go('items-list') {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - #{$--header-height} * 2 - 2px);
  .list-content {
    position: relative;
    height: $contentHeight;
  }
  .list-pagination {
    position: fixed;
    bottom: 10px;
    right: 30px;
  }
}
</style>