CardMode.vue 10.1 KB
<script lang="ts" setup>
  import { PageWrapper } from '/@/components/Page';
  import { BasicForm, useForm } from '/@/components/Form';
  import { List, Button, Tooltip, Card, PaginationProps, Image, Popconfirm } from 'ant-design-vue';
  import { ReloadOutlined } from '@ant-design/icons-vue';
  import { computed, onMounted, reactive, ref, unref } from 'vue';
  import {
    AuthIcon,
    CardLayoutButton,
    EnumTableCardMode,
    ModeSwitchButton,
  } from '/@/components/Widget';
  import { Authority } from '/@/components/Authority';
  import {
    deviceConfigDelete,
    deviceConfigGetQuery,
    setDeviceProfileIsDefaultApi,
  } from '/@/api/device/deviceConfigApi';
  import { ProfileRecord } from '/@/api/device/model/deviceConfigModel';
  import {
    defaultObj,
    searchFormSchema,
    DeviceTypeName,
    ProductPermission,
  } from './device.profile.data';
  import { useMessage } from '/@/hooks/web/useMessage';
  import DeviceProfileModal from './DeviceProfileModal.vue';
  import DeviceProfileDrawer from './DeviceProfileDrawer.vue';
  import { useModal } from '/@/components/Modal';
  import { useDrawer } from '/@/components/Drawer';
  import productDefault from '/@/assets/icons/product-default.svg';
  import { useRoute } from 'vue-router';
  import AuthDropDown from '/@/components/Widget/AuthDropDown.vue';

  defineProps<{
    mode: EnumTableCardMode;
  }>();

  const emit = defineEmits(['changeMode']);

  enum DropMenuEvent {
    SET_DEFAULT = 'setDefault',
    DELETE = 'delete',
  }
  const IMAGE_FALLBACK = productDefault;

  const { createMessage } = useMessage();

  const [register, { getFieldsValue, setFieldsValue }] = useForm({
    showAdvancedButton: true,
    labelWidth: 100,
    compact: true,
    baseColProps: { span: 8 },
    schemas: searchFormSchema,
    resetFunc: async () => {
      getDataSource({ name: '' });
    },
    submitFunc: async () => {
      getDataSource({ pageSize: pagination.pageSize, page: 1 });
    },
  });

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

  const loading = ref(false);

  const colNumber = ref(5);

  const pagination = reactive<PaginationProps>({
    size: 'small',
    showTotal: (total: number) => `共 ${total} 条数据`,
    current: 1,
    pageSize: unref(colNumber) * 2,
    onChange: (page: number) => {
      pagination.current = page;
      getDataSource();
    },
  });

  const dataSource = ref<ProfileRecord[]>([]);

  const getSelectAllFlag = computed(() => {
    return unref(dataSource).every((item) => item.checked || item.default);
  });

  const getCheckedRecord = computed(() => {
    return unref(dataSource)
      .filter((item) => item.checked && !item.default)
      .map((item) => item.id);
  });

  const getDataSource = async (otherParams: Recordable = {}) => {
    try {
      loading.value = true;
      if (otherParams) {
        setFieldsValue(otherParams);
      }
      const params = getFieldsValue();
      const pageSize = unref(colNumber) * 2;
      const { items, total } = await deviceConfigGetQuery({
        page: pagination.current,
        pageSize: unref(colNumber) * 2,
        ...params,
        ...otherParams,
      });
      Object.assign(pagination, { total, pageSize });
      dataSource.value = items.map((item) => ({ ...item, checked: false }));
    } catch (error) {
    } finally {
      loading.value = false;
    }
  };

  const handleModeChange = (mode: EnumTableCardMode) => {
    emit('changeMode', mode);
  };

  const handleCheckCard = (item: ProfileRecord) => {
    if (item.default || item.name == 'default') return;
    item.checked = !item.checked;
  };

  const handleSelectAll = () => {
    dataSource.value = unref(dataSource).map((item) => {
      return {
        ...item,
        checked: !item.default ? !unref(getSelectAllFlag) : false,
      };
    });
  };

  const handleCreate = () => {
    openModal(true, {
      isUpdate: false,
    });
  };

  const handleShowDetail = (record: ProfileRecord) => {
    openDrawer(true, { record });
  };

  const handleUpdate = (record: ProfileRecord) => {
    openModal(true, {
      record,
      isUpdate: true,
    });
  };

  const handleDelete = async (id: string[]) => {
    try {
      await deviceConfigDelete(id);
      createMessage.success('删除成功');
      await getDataSource();
    } catch (error) {
      throw error;
    }
  };

  const handleSetDefault = async (record: ProfileRecord) => {
    try {
      const { tbProfileId } = record;
      const data = await setDeviceProfileIsDefaultApi(tbProfileId, 'default', defaultObj);
      if (!data) return createMessage.error('设置该产品为默认失败');
      createMessage.success('设置该产品为默认成功');
      await getDataSource();
    } catch (error) {
      throw error;
    }
  };

  const handleCardLayoutChange = () => {
    pagination.current = 1;
    getDataSource();
  };

  const { query: routeParams } = useRoute();
  onMounted(() => {
    routeParams.name = decodeURIComponent(
      ((routeParams as unknown as Recordable) || {})?.name || ''
    );
    getDataSource(routeParams);
  });
</script>

<template>
  <PageWrapper dense contentFullHeight contentClass="flex">
    <section class="flex-auto p-4 w-full profile-list">
      <div class="flex-auto w-full bg-light-50 dark:bg-dark-900 p-4">
        <BasicForm @register="register" />
      </div>
      <List
        ref="listEl"
        :loading="loading"
        class="flex-auto bg-light-50 dark:bg-dark-900 !p-2 !mt-4"
        position="bottom"
        :pagination="pagination"
        :data-source="dataSource"
        :grid="{ gutter: 4, column: colNumber }"
      >
        <template #header>
          <div class="flex gap-3 justify-end">
            <Authority :value="ProductPermission.CREATE">
              <Button type="primary" @click="handleCreate">新增产品</Button>
            </Authority>

            <Button type="primary" @click="handleSelectAll">
              {{ getSelectAllFlag ? '反选' : '全选' }}
            </Button>
            <Authority :value="ProductPermission.DELETE">
              <Popconfirm
                title="您确定要批量删除数据"
                ok-text="确定"
                cancel-text="取消"
                @confirm="handleDelete(getCheckedRecord)"
              >
                <Button type="primary" danger :disabled="!getCheckedRecord.length">
                  批量删除
                </Button>
              </Popconfirm>
            </Authority>

            <ModeSwitchButton :value="$props.mode" @change="handleModeChange" />
            <CardLayoutButton v-model:value="colNumber" @change="handleCardLayoutChange" />

            <Tooltip title="刷新">
              <Button type="primary" @click="getDataSource">
                <ReloadOutlined :spin="loading" />
              </Button>
            </Tooltip>
          </div>
        </template>
        <template #renderItem="{ item }">
          <List.Item>
            <Card
              hoverable
              @click="handleCheckCard(item)"
              :class="item.checked ? '!border-blue-500 !border-2' : ''"
            >
              <template #cover>
                <div class="h-full w-full !flex justify-center items-center text-center p-1">
                  <Image
                    @click.stop
                    :height="144"
                    :src="item.image || IMAGE_FALLBACK"
                    placeholder
                    :fallback="IMAGE_FALLBACK"
                  />
                </div>
              </template>
              <template class="ant-card-actions" #actions>
                <Tooltip title="详情">
                  <AuthIcon
                    :auth="ProductPermission.DETAIL"
                    class="!text-lg"
                    icon="ant-design:eye-outlined"
                    @click.stop="handleShowDetail(item)"
                  />
                </Tooltip>
                <Tooltip title="编辑">
                  <AuthIcon
                    :auth="ProductPermission.UPDATE"
                    class="!text-lg"
                    icon="ant-design:form-outlined"
                    @click.stop="handleUpdate(item)"
                    :disabled="item.name == 'default'"
                  />
                </Tooltip>
                <AuthDropDown
                  @click.stop
                  :trigger="['hover']"
                  :drop-menu-list="[
                    {
                      text: '默认',
                      event: DropMenuEvent.SET_DEFAULT,
                      icon: 'ant-design:unordered-list-outlined',
                      onClick: handleSetDefault.bind(null, item),
                      disabled: item.default,
                    },
                    {
                      text: '删除',
                      event: DropMenuEvent.DELETE,
                      auth: ProductPermission.DELETE,
                      icon: 'ant-design:delete-outlined',
                      popconfirm: {
                        title: '是否确认删除操作?',
                        onConfirm: handleDelete.bind(null, [item.id]),
                        disabled: item.default,
                      },
                      disabled: item.default || item.name == 'default',
                    },
                  ]"
                />
              </template>
              <Card.Meta>
                <template #title>
                  <span class="truncate"> {{ item.name }} </span>
                </template>
                <template #description>
                  <div class="truncate h-11">
                    <div class="truncate">{{ DeviceTypeName[item.deviceType] }} </div>
                    <div class="truncate">{{ item.transportType }} </div>
                  </div>
                </template>
              </Card.Meta>
            </Card>
          </List.Item>
        </template>
      </List>
    </section>
    <DeviceProfileModal @register="registerModal" @success="getDataSource" />
    <DeviceProfileDrawer @register="registerDrawer" />
  </PageWrapper>
</template>

<style lang="less" scoped>
  .profile-list:deep(.ant-image-img) {
    @apply !w-full !h-full;
  }

  .profile-list:deep(.ant-card-body) {
    @apply !p-4;
  }
</style>