index.vue 12.2 KB
<script setup lang="ts">
  import { Card, Button, Tooltip } from 'ant-design-vue';
  import { computed, unref, reactive } from 'vue';
  import { OrganizationIdTree, useOrganizationTree } from '../common/organizationIdTree';
  import {
    bigScreenCancelPublish,
    bigScreenPublish,
    deleteBigScreenenter,
    getPage,
    shareLargeScreen,
  } from '/@/api/bigscreen/center/bigscreenCenter';
  import { BigScreenCenterItemsModel } from '/@/api/bigscreen/center/model/bigscreenCenterModel';
  import { PageWrapper } from '/@/components/Page';
  import { ConfigurationPermission, searchFormSchema } from './config';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { Authority } from '/@/components/Authority';
  import ConfigurationCenterDrawer from './BigScreenDrawer.vue';
  import { useDrawer } from '/@/components/Drawer';
  import configurationSrc from '/@/assets/icons/configuration.svg';
  import { cloneDeep } from 'lodash';
  import { useGlobSetting } from '/@/hooks/setting';
  import { AuthIcon } from '/@/components/Widget';
  import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';
  import { PublicApiDrawer } from './publicApi/index';
  import { useModal } from '/@/components/Modal';
  import { ShareModal } from '/@/views/common/ShareModal';
  import { ViewTypeEnum } from '../common/ShareModal/config';
  import { ViewType } from '../visual/board/config/panelDetail';
  import { useUserStore } from '/@/store/modules/user';
  import { useLocaleStore } from '/@/store/modules/locale';
  import { RoleEnum } from '/@/enums/roleEnum';
  import { useRole } from '/@/hooks/business/useRole';
  import { useClipboard } from '@vueuse/core';
  import { BasicCardList, useCardList } from '/@/components/CardList';
  import { useI18n } from '/@/hooks/web/useI18n';

  const [registerOrgTree, { getSelectKey, clearSelected }] = useOrganizationTree({
    onSelect: () => {
      reload();
    },
  });

  const { t } = useI18n();

  const searchInfo = reactive<Recordable>({});

  const [registerCardList, { reload }] = useCardList({
    api: getPage,
    title: t('visual.dataview.name'),
    useSearchForm: true,
    gutter: 4,
    searchInfo: searchInfo,
    formConfig: {
      labelWidth: 80,
      schemas: searchFormSchema,
      resetFunc: async () => clearSelected(),
    },
    beforeFetch: async (params: Recordable) => {
      return { ...params, organizationId: getSelectKey() };
    },
  });

  const [registerDrawer, { openDrawer }] = useDrawer();

  const [registerPublicDrawer, { openDrawer: openPublicApiDrawer }] = useDrawer();

  const { createMessage } = useMessage();

  const { isCustomerUser } = useRole();

  const handleCreateOrUpdate = (record?: BigScreenCenterItemsModel) => {
    if (record) {
      openDrawer(true, {
        isUpdate: true,
        record: cloneDeep(record),
      });
    } else {
      openDrawer(true, {
        isUpdate: false,
      });
    }
  };

  const handleCreateOrUpdatePublicApi = () => openPublicApiDrawer(true);

  const { largeDesignerPrefix } = useGlobSetting();

  const handlePreview = (record: BigScreenCenterItemsModel) => {
    window.open(
      `${largeDesignerPrefix}/#/chart/preview/${record.id}?organizationId=${record.organizationId}&locale=${localeStore.getLocale}`
    );
  };

  const handleDesign = (record: BigScreenCenterItemsModel) => {
    if (record.state === 1) return;
    window.open(
      `${largeDesignerPrefix}/#/chart/home/${record.id}?organizationId=${record.organizationId}&locale=${localeStore.getLocale}`
    );
  };

  const handleDelete = async (record: BigScreenCenterItemsModel) => {
    try {
      await deleteBigScreenenter([record.id]);
      createMessage.success(t('common.deleteSuccessText'));
      reload();
    } catch (error) {}
  };

  const [registerShareModal, { openModal }] = useModal();
  const handleOpenShareModal = (record: BigScreenCenterItemsModel) => {
    openModal(true, { record, href: createShareUrl(record) });
  };

  const createShareUrl = (record: BigScreenCenterItemsModel) => {
    const { origin } = location;
    return `${origin}${largeDesignerPrefix}/#/share/preview/${record.id}/${record.publicId}?locale=${localeStore.getLocale}`;
  };

  const userStore = useUserStore();

  const localeStore = useLocaleStore();

  const hasPublicInterfacePermission = computed(() => {
    return userStore.getUserInfo.roles![0] !== RoleEnum.CUSTOMER_USER;
  });

  const { copied, copy } = useClipboard({ legacy: true });
  const handleCreateShareUrl = async (record: BigScreenCenterItemsModel) => {
    await copy(createShareUrl(record));
    if (unref(copied)) {
      createMessage.success(t('common.copyOk'));
    }
  };

  const handlePublish = async ({ id, state }) => {
    state === 0 ? await bigScreenPublish(id) : await bigScreenCancelPublish(id);
    createMessage.success(
      state === 0 ? t('common.releaseOkText') : t('common.cancelReleaseOkText')
    );
    reload();
  };

  function handleSelect(organization) {
    searchInfo.organizationId = organization;
    reload();
  }
</script>

<template>
  <PageWrapper dense contentFullHeight contentClass="flex">
    <OrganizationIdTree @select="handleSelect" @register="registerOrgTree" />
    <BasicCardList
      @register="registerCardList"
      class="flex-auto p-4 w-3/4 xl:w-4/5 w-full configuration-list"
    >
      <template #toolbar>
        <section class="flex gap-4">
          <Authority v-if="!isCustomerUser" :value="ConfigurationPermission.CREATE">
            <Button type="primary" @click="handleCreateOrUpdate()">
              {{ t('visual.dataview.buttonAddName') }}
            </Button>
          </Authority>
          <Authority
            v-if="hasPublicInterfacePermission"
            :value="ConfigurationPermission.PUBLISH_INTERFACE"
          >
            <Button type="primary" @click="handleCreateOrUpdatePublicApi()">{{
              t('visual.dataview.buttonManagement')
            }}</Button>
          </Authority>
        </section>
      </template>
      <template #renderItem="{ item }: BasicCardListRenderItem<BigScreenCenterItemsModel>">
        <Card
          :style="{
            '--viewType': item.viewType === ViewType.PUBLIC_VIEW ? '#faad14' : '#1890ff',
          }"
          class="card-container"
        >
          <template #cover>
            <div class="h-full w-full relative hover-show-modal-content img-container">
              <img
                style="position: relative"
                class="w-full h-45 hover-show-modal"
                alt="example"
                :src="item.thumbnail || configurationSrc"
                @click="handlePreview(item)"
              />
              <span class="absolute top-0 left-0 text-light-50 transform -rotate-45 translate-y-1">
                {{
                  (item as Recordable).viewType === ViewTypeEnum.PRIVATE_VIEW
                    ? t('common.private')
                    : t('common.public')
                }}
              </span>
              <div class="masker-content">
                <div class="masker-text">
                  <div>
                    <span>{{ item.name }} </span>
                  </div>
                  <div>
                    <span class="masker-text-org">
                      {{ t('business.organizationText') }}:{{ item?.organizationDTO?.name }}</span
                    >
                  </div>
                  <div>
                    <span class="masker-text-state"
                      >{{ t('visual.dataview.textPublishStatus') }}:{{
                        item.state === 1 ? t('commom.publishedText') : t('common.unpublishedText')
                      }}</span
                    >
                  </div>
                </div>
              </div>
            </div>
          </template>
          <template class="ant-card-actions" #actions>
            <Tooltip :title="t('common.previewText')">
              <AuthIcon
                :auth="ConfigurationPermission.DATAVIEW_PREVIEW"
                class="!text-lg"
                icon="ant-design:eye-outlined"
                @click="handlePreview(item)"
              />
            </Tooltip>
            <Tooltip v-if="!isCustomerUser" :title="t('common.designText')">
              <AuthIcon
                :auth="ConfigurationPermission.DESIGN"
                :disabled="item.state === 1"
                icon="ant-design:edit-outlined"
                @click="handleDesign(item)"
              />
            </Tooltip>
            <Tooltip :title="t('visual.dataview.textCopyLink')">
              <AuthIcon
                :auth="ConfigurationPermission.SHARE"
                :disabled="!item.publicId"
                class="!text-lg"
                icon="ant-design:share-alt-outlined"
                @click="handleCreateShareUrl(item)"
              />
            </Tooltip>
            <AuthDropDown
              v-if="!isCustomerUser"
              :dropMenuList="[
                {
                  text: t('common.shareText'),
                  auth: ConfigurationPermission.SHARE,
                  icon: 'ant-design:share-alt-outlined',
                  event: '',
                  onClick: handleOpenShareModal.bind(null, item),
                },
                {
                  text: item.state == 0 ? t('common.releaseText') : t('common.cancelReleaseText'),
                  auth: ConfigurationPermission.PUBLISH,
                  icon:
                    item.state == 0
                      ? 'ant-design:node-expand-outlined'
                      : 'ant-design:node-collapse-outlined',
                  event: '',
                  onClick: handlePublish.bind(null, item),
                },
                {
                  text: t('common.editText'),
                  auth: ConfigurationPermission.UPDATE,
                  icon: 'clarity:note-edit-line',
                  event: '',
                  onClick: handleCreateOrUpdate.bind(null, item),
                  disabled: item.state === 0 ? false : true,
                },
                {
                  text: t('common.delText'),
                  auth: ConfigurationPermission.DELETE,
                  icon: 'ant-design:delete-outlined',
                  disabled: item.state === 0 ? false : true,
                  event: '',
                  popconfirm: {
                    title: t('common.isDelete'),
                    onConfirm: handleDelete.bind(null, item),
                  },
                },
              ]"
              :trigger="['hover']"
            />
          </template>
        </Card>
      </template>
    </BasicCardList>

    <ShareModal @register="registerShareModal" :shareApi="shareLargeScreen" @success="reload()" />
    <ConfigurationCenterDrawer @register="registerDrawer" @success="reload()" />
    <PublicApiDrawer @register="registerPublicDrawer" />
  </PageWrapper>
</template>

<style lang="less" scoped>
  .configuration-list:deep(.ant-list-header) {
    border-bottom: none !important;
  }

  .configuration-list:deep(.ant-list-pagination) {
    height: 24px;
  }

  .configuration-list:deep(.ant-card-body) {
    padding: 16px !important;
  }

  .configuration-list:deep(.ant-list-empty-text) {
    @apply w-full h-full flex justify-center items-center;
  }

  :deep(.ant-card-body) {
    display: none;
  }

  .masker-content {
    opacity: 0;
    z-index: 1000;
    width: 100%;
    height: 11.25rem;
    background-color: rgba(0, 0, 0, 0.5);
    position: absolute;
    transition: opacity 0.5;
    pointer-events: none;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;

    .masker-text {
      color: #fff;
      font-size: 16px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      line-height: 2.5rem;
      margin: 4rem 0;

      .masker-text-org {
        font-size: 12px;
        position: absolute;
        bottom: 0;
        left: 0.8rem;
      }

      .masker-text-state {
        font-size: 12px;
        position: absolute;
        bottom: 0;
        right: 0.8rem;
      }
    }
  }

  .hover-show-modal-content:hover > .masker-content {
    opacity: 1;
  }

  .card-container {
    // background-color: red;
    .img-container {
      border-top-left-radius: 80px;
      background-color: #fff;

      img {
        border-top-left-radius: 80px;
      }
    }
  }

  .card-container:deep(.ant-card-cover) {
    background-color: var(--viewType);
  }
</style>