<template>
  <page-title :title="getTitle"/>

    <div class="ns-table-wrapper">
      <div class="ns-table" :class="{ 'ns-table-no-search': !(formConfig?.schemas.length > 0) }">
        <a-spin :spinning="tableState.loading">
          <a-row type="flex" class="ns-table-main">
            <a-col flex="180px">
              <ns-table-header
                  :headerActions="headerActions"
                  :searchData="formModel"
                  :tableTitle="tableTitle"
                  :data="tableState.selectedRows">
                <template #header="data">
                  <slot name="header" v-bind="data || {}"></slot>
                </template>
              </ns-table-header>
              <Skeleton :loading="loadingTree" active>
                <div class="type-tree-wrapper">
                <div class="tree-top-header">
                  <div class="tree-node-content-wrapper" :class="{'selected': allSelected}" @click="onAllSelect">全部类别</div>
                  <ns-button type="link" @click="onContextMenuClick(null, 'add')" v-if="authMap['add']">
                    <PlusCircleOutlined/>
                    添加类别
                  </ns-button>
                </div>
                <a-tree v-model:expandedKeys="expandedKeys" :tree-data="treeData" v-model:selectedKeys="selectedKeys"
                        @expand="onExpand" @select="onTreeSelect">
                  <template #title="{ key: treeKey, title, dataRef }">
                    <a-dropdown :trigger="['contextmenu']">
                      <span style="min-width: 80px; display: block">{{ title }}</span>
                      <template #overlay>
                        <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey, dataRef)">
                          <a-menu-item key="edit" v-if="authMap['edit']">
                            <EditOutlined/>
                            编辑
                          </a-menu-item>
                          <a-menu-item key="add" v-if="authMap['add']">
                            <PlusCircleOutlined/>
                            添加
                          </a-menu-item>
                          <a-menu-item key="remove" v-if="authMap['remove']">
                            <DeleteOutlined/>
                            删除
                          </a-menu-item>
                        </a-menu>
                      </template>
                    </a-dropdown>
                  </template>
                </a-tree>
              </div>
              </Skeleton>
            </a-col>
            <a-col flex="auto">
              <!-- {{ formConfig }} -->
              <div class="ns-table-search">
                <ns-form
                    ref="formElRef"
                    class="ns-table-form"
                    :showAction="true"
                    v-bind="formConfig"
                    formLayout="flex"
                    :expand="expand"
                    :showExpand="showExpand"
                    :model="formModel"
                    @finish="formFinish"/>
              </div>
              <Skeleton :loading="loadingTable" active>
                <div class="section0">
                  <div class="section-content" v-if="tableData  && tableData.length>0">
                    <template v-for="(item) in tableData">
                      <div class="item card-item" @click="onCLickCard(item)">
                        <header class="item-header">
                          <div class="info-card-header">
                            <div class="card-title">{{ item['alias'] }}</div>
                          </div>
                        </header>
                        <div class="info-item-block">
                          <div class="card-icon"><img :src="imgSrc + item['iconID']" alt=""></div>
                          <div class="card-description-wrapper">
                            <div class="card-description"><span>{{ item['desc'] }}</span>
                            </div>
                          </div>
                        </div>
                        <footer class="item-footer">
                          <div class="card-item-footer">
                            <div class="card-footer-left">
                              {{ item['typeClassAlias'] }}
                            </div>
                            <div class="card-footer-right">
                              <div class="card-status">
                                <span v-if="item['shelfState']"> <i class="iconfont iconGreen font-12">&#xe658;</i> 已上架
                                </span>
                                <span v-if="!item['shelfState']"><i class="iconfont iconRed font-12">&#xe658;</i> 待上架
                                </span>
                              </div>
                            </div>
                          </div>
                        </footer>
                      </div>
                    </template>
                  </div>
                  <div class="section-content" v-if="tableData  && tableData.length === 0 || !tableData">
                    <div class="ns-table-content"> <a-empty /> </div>
                  </div>
                </div>
                <div class="pagination" v-if="tableData && tableData.length === 0 || tableData!=null">
                  <a-pagination
                      v-bind="getPagination"
                      show-quick-jumper
                      show-size-changer
                      @change=" (current,pageSize) => onChange({current,pageSize})"
                      size="small"
                      :show-total="(total, range) => `显示 ${range[0]} 到 ${range[1]} 条数据，共计${total}条`"
                  />
                </div>
              </Skeleton>
            </a-col>
          </a-row>
        </a-spin>
      </div>
    </div>
  <a-modal v-model:visible="modalVisible" :title="modalOperation.title" @ok="handleOk" @cancel="cancel" v-if="modalVisible">
    <div class="add-form" id="app" v-if="typeSchema.length">
      <ns-form
          ref="configRef"
          formLayout="ns-vertical-form"
          :schemas="typeSchema"
          :model="typeData"
      />
    </div>
  </a-modal>
</template>

<script lang="ts">
import {computed, defineComponent, reactive, ref, unref, watch} from "vue";
import {Skeleton, Pagination} from "ant-design-vue";
import {debounce, cloneDeep, isArray, get} from "lodash-es";
import {tableProps} from "../../../lib/component/table/props";
import {http, PropTypes, stringUtil} from "../../../lib/util";
import {useRoute} from "vue-router";
import {PlusCircleOutlined, EditOutlined, DeleteOutlined, ExclamationCircleOutlined} from "@ant-design/icons-vue";
import {NsMessage, NsModal} from "../../../lib/component";
import {RequestParams} from "/nerv-lib/component/table/table";
import {AxiosRequestConfig} from "axios";
import {useApi, useParams} from "/nerv-lib/use";
import {useTableRefresh} from "/nerv-lib/component/table/use-table-refresh";
import {useTableSession} from "/nerv-lib/component/table/use-table-session";
import {APP} from "/@/router/index.ts";
import {authorizationService} from "/nerv-lib/paas";

export default defineComponent({
  name: 'TreeAndTableList',
  components: {
    Skeleton,
    PlusCircleOutlined,
    EditOutlined,
    DeleteOutlined,
    'a-pagination': Pagination,
  },
  props: {
    ...tableProps,
    title: PropTypes.string,
    tableTitle: PropTypes.func,
    showTitle: {
      type: Boolean,
      default: true,
    },
    resultField: PropTypes.string
  },
  setup: (props, {attrs, emit}) => {
    const nsTableRef = ref();
    const route = useRoute();
    const formModel = ref({});
    // 搜索form参数
    const formParamsRef = ref({});
    // table参数
    const tableState = reactive({
      selectedRowKeys: [],
      selectedRows: [],
      loading: false,
      loadError: false,
      loadErrorMessage: '',
    });
    const expandedKeys = ref()
    const { delayFetch } = useTableRefresh({ props, reload });
    const defaultPageRef = ref(0);
    const { getParams } = useParams();
    const treeParamsRef = ref({});
    const dataRef = ref([]);
    const orderRef = ref({});
    const { setTableSession } = useTableSession(formModel.value, formParamsRef, defaultPageRef);
    const tableData = ref<Recordable[]>([]);
    let allSelected = ref(true);
    const selectedKeys = ref([]);
    let loadingTable = ref<boolean>(false);
    let loadingTree = ref<boolean>(false);
    const imgSrc = ref(`/api/${APP}/objs/Images/`)
    let typeFieldErrors = ref({});
    //  缓存
    function initTableSession() {
      const { fullPath } = route;
      const tableSession = JSON.parse(sessionStorage[fullPath] || '{}');
      if (!props.enableTableSession) return;
      if (tableSession['formModel']) {
        Object.assign(formModel.value, tableSession['formModel']);
        let code = formModel.value['typeClassCode'];
        if(code){
          treeParamsRef.value['typeClassCode'] = code;
          selectedKeys.value =[ code];
          allSelected.value = false;
        }
      }
    }
    initTableSession();
    //权限部分
    let authMap = ref({});
    const resourceTypeClassOp= ['add', 'edit', 'remove'];
    resourceTypeClassOp.forEach( key => {
      authMap.value[key]= authorizationService().checkPermission('resourceRepo', 'resourceTypeClass', key);
    })
    // 页面标题
    const getTitle = computed(() => {
      const {title} = props;
      if (title) return title;
      const {
        params: {pageTitle},
      } = route;
      if (pageTitle) return pageTitle;
    });
    // 搜索参数
    const formFinish = debounce((data) => {
      formParamsRef.value = data;
      fetch({
        page: 1,
      });
    }, 300);
    const tableChangeEvent = (pagination: Props, filters: [], sorter?: any) => {
      // console.log('params', pagination, filters, sorter);
      if (sorter?.field) {
        if (sorter.order) {
          orderRef.value = {
            [props.paramsOrderField]: stringUtil.toLine(
                `${sorter.field} ${sorter.order.replace('end', '')}`,
            ),
          };
        } else {
          orderRef.value = { [props.paramsOrderField]: '' }; //覆盖默认params
        }
        fetch({
          page: pagination?.current || getPagination.value?.current || 1,
          pageSize: pagination?.pageSize,
        });
      } else if (pagination?.current) {
        fetch({
          page: pagination?.current,
          pageSize: pagination.pageSize,
        });
      }
    };
    // pagination
    const getPagination: Recordable | Boolean = computed(() => {
      const { pagination } = props;
      if (pagination) {
        const current = get(dataRef.value, props.pageField);
        return {
          showQuickJumper: true,
          showLessItems: true,
          showSizeChanger: true,
          showTotal: (total: number, range: Array<number>) =>
              `显示第${range[0]}到${range[1]}条记录 ,共 ${total} 条记录`,
          ...(pagination as Props),
          total: get(dataRef.value, props.totalField),
          current: (current >= 0 ? current : 0) + props.pageFieldOffset, // 后端0 开始
          pageSize: get(dataRef.value, props.sizeField),
        }
      }
      return false;
    });

    const getTableBindValues = computed(() => {
      const { params, dynamicParams } = props;
      return {
        ...attrs,
        ...props,
        params: dynamicParams
            ? getParams({ ...route.params, ...route.query }, dynamicParams, params)
            : params || {},
        pagination: getPagination.value,
        onChange: tableChangeEvent,
      };
    });

    watch(
        () => getTableBindValues.value.api,
        () => {
          fetch();
        },
        {
          immediate: true,
        },
    );

    function fetch(requestParams: RequestParams = {}, clearDelay = true) {
      clearDelay && delayFetch();
      const { api, pagination } = props;
      const { page, pageSize } = requestParams;
      if (api) {
        let pageParams: Recordable = {};

        if (pagination !== false) {
          pageParams = {
            [props.paramsPageField]: page ? page - props.pageFieldOffset : defaultPageRef.value, // 后端0 开始
            [props.paramsPageSizeField]:
            pageSize || getPagination.value?.pageSize || props.defaultPageSize,
          };
        } else {
          pageParams = {
            [props.paramsPageField]: defaultPageRef.value, // 后端0 开始
            [props.paramsPageSizeField]:
            pageSize || getPagination.value?.pageSize || props.defaultPageSize,
          };
        }
        const httpParams = {
          ...getTableBindValues.value.params,
          ...pageParams,
          ...formParamsRef.value,
          ...treeParamsRef.value,
          ...orderRef.value,

        };

        setTableSession(pageParams[props.paramsPageField]);

        clearDelay && setLoading(true);

        const requestConfig: AxiosRequestConfig = { method: 'get' };
        const { httpRequest } = useApi();
        httpRequest({
          api,
          params: httpParams,
          pathParams: { ...route.params, ...route.query },
          requestConfig,
        }).then((res: any) => {

              tableState.loadError = false;
              tableState.loadErrorMessage = '';
              dataRef.value = res;
              tableData.value = get(unref(dataRef), props.listField);
              emit('update:dataSource', tableData.value);
              clearDelay && setLoading(false);
              loadingTable.value = false;
            })
            .catch((error: any) => {
              const { response, code, message } = error || {};
              let errMessage = response?.data?.msg;
              const err: string = error?.toString?.() ?? '';
              if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
                errMessage = '接口请求超时,请刷新页面重试!';
              }
              if (err?.includes('Network Error')) {
                errMessage = '网络异常，请检查您的网络连接是否正常!';
              }
              tableState.loadError = true;
              tableState.loadErrorMessage = errMessage;
              clearDelay && setLoading(false);
              loadingTable.value = false;
            });
      }
    }

    function setLoading(loading: boolean) {
      tableState.loading = loading;
    }


    // 右侧树形结构
    const treeData = ref( []);
    // 树形结构添加
    let typeSchema = ref([]);
    const getTypeSchema = (mode) => {
      let schema = [
        {
          field: 'alias',
          component: 'NsInput',
          label: '类别名称',
          rules: [
            {
              required: true,
              trigger: 'change',
              validator: async (rule, value) => {
                if (!value) {
                  return Promise.reject('类别名称不能为空');
                }
                if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
                  return Promise.reject(
                      '只能包括大小写字母、中文、数字和短横线（-）、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
                  );
                }
              },
            },
            {
              trigger: 'change',
              validator: async (rule, value) => {
                if (Object.keys(typeFieldErrors.value).indexOf('alias') !== -1) {
                  const errorInfo = typeFieldErrors.value['alias'];
                  delete typeFieldErrors.value['alias'];
                  return Promise.reject(errorInfo);
                }
              },
            },
          ],
        },
      ];
      if (mode === 'add') {
        schema.push(
            {
              field: 'code',
              component: 'NsInput',
              label: '类别代码',
              rules: [
                {
                  required: true,
                  trigger: 'change',
                  validator: async (rule, value) => {
                    if (!value) {
                      return Promise.reject('类别代码不能为空');
                    }
                    if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
                      return Promise.reject(
                          '只能包括大小写字母、中文、数字和短横线（-）、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
                      );
                    }
                  },
                },
                {
                  trigger: 'change',
                  validator: async (rule, value) => {
                    if (Object.keys(typeFieldErrors.value).indexOf('code') !== -1) {
                      const errorInfo = typeFieldErrors.value['code'];
                      delete typeFieldErrors.value['code'];
                      return Promise.reject(errorInfo);
                    }
                  },
                },
              ],
            })
      } else if (mode === 'edit') {
        schema.push(
            {
              field: 'code',
              component: 'NsInputText',
              label: '类别代码',
            })
      }
      return schema || [];
    }
    const typeData = ref({});
    let modalVisible = ref(false);
    let modalOperation = ref({
      title: '添加类别',
      key: 'add'
    });
    // 搜索
    const formElRef = ref(null);
    const getFormConfig = computed(() => {
      const formConfig = cloneDeep(props.formConfig);
      if (formConfig) {
        formConfig.showAction = false;
        if (!isArray(formConfig.schemas)) {
          formConfig.schemas = [];
        }
        if (formConfig.keySearch !== false) {
          formConfig.schemas.push({
            field: 'alias',
            label: '关键字',
            component: 'NsInputSearch',
            rules: [
              {
                message: '请输入关键字',
                trigger: 'change',
              },
            ],
            componentProps: {
              maxlength: 50,
              onSearch: () => {
                unref(formElRef)?.triggerSubmit()
                // unref(nsTableRef)?.formElRef?.triggerSubmit();
              },
              onKeydown: (event) => {
                //fix 单个input回车会提交表单 造成重复提交
                if (event.key === 'Enter' || event.code === 'Enter') {
                  event.preventDefault();
                }
              },
              placeholder: '请输入关键字',
            },
          });
        }
      }
      return formConfig;
    });
    // 卡片列表分页信息
    function onTreeSelect(selectedKeys: never[],
                          e: {
                            selected: boolean;
                            selectedNodes: { props: { dataRef: any } }[];
                            node: any;
                            event: any;
                          })
    {
      allSelected.value = false;
      const dataRef = e.selectedNodes[0];
      treeParamsRef.value = getParams(dataRef, {typeClassCode: 'code'});
      unref(formElRef)?.triggerSubmit();
      let key = 'typeClassCode';
      if (e.selected) {
        formModel.value[key] = treeParamsRef.value[key];
      } else {
        updateFormModel();
      }
    }
    function reload(clearDelay = true) {
      const pagination = unref(getPagination);
      fetch(
          {
            page: pagination === false ? 1 : pagination.current,
          },
          clearDelay,
      );
    }
    const updateFormModel = function (value?:any) {
      const key = 'typeClassCode';
      const model: object = formModel.value;
      if (value) {
        if (Object.keys(model).includes(key) && model[key] === value) {
          delete model[key];
        }
      } else if (Object.keys(model).includes(key)){
        delete model[key];
      }
    }
    return {
      tableState,
      getTitle,
      treeData,
      expandedKeys,
      formModel,
      formFinish,
      tableData,
      typeSchema,
      typeData,
      modalVisible,
      modalOperation,
      typeFieldErrors,
      getTypeSchema,
      formConfig: getFormConfig.value,
      nsTableRef,
      formElRef,
      getParams,
      onTreeSelect,

      onChange: tableChangeEvent,
      allSelected,
      selectedKeys,
      treeParamsRef,
      loadingTable,
      loadingTree,
      imgSrc,
      getTableBindValues,
      getPagination,
      authMap,
      updateFormModel,
      setTableSession
    }
  },
  mounted() {
    this.getDataTree()
  },
  methods: {
    onCLickCard(item) {
      this.$router.push(item['code'] + '/detail' );
    },
    // 转换树结构数据
    transferTree(data) {
      if( isArray(data) && data.length > 0) {
        data.forEach(it=>{
          it['title'] = it['alias'];
          it['key']=it['code'];
          if(it['children'] ) {
            this.transferTree(it['children']);
          }
        })
      } else {
        return;
      }
    },
    getDataTree() {
      http.get(`/api/${APP}/objs/ResourceTypeClasses`).then(res => {
        this.transferTree(res)
        this.treeData = res;

        this.loadingTree = false;
      }).catch( err => {
        this.loadingTree = false;
      })
    },
    onAllSelect() {
      this.allSelected = !this.allSelected;
      this.selectedKeys = [];
      this.treeParamsRef = null;
      this.updateFormModel();
      this.formElRef.triggerSubmit();
    },
    // onExpand(keys) {
    //   this.expandedKeys = keys;
    // },
    onContextMenuClick(treeKey, menuKey, data) {
      this.modalOperation.key = menuKey
      if (menuKey === 'add')     {
        this.modalOperation.title = '添加类别';
        this.modalVisible = true;
        this.typeData['parentID'] = data?.id || null;
        this.typeSchema = this.getTypeSchema('add')
      }
      if (menuKey === 'edit') {
        this.modalOperation.title = '编辑类别';
        this.modalVisible = true;
        this.typeData = {
          alias: data['title'],
          code: data['code'],
          id: data['id'],
          parentID: data['parentID']
        }
        this.typeSchema = [
          {
            field: 'alias',
            component: 'NsInput',
            label: '类别名称',
            rules: [
              {
                required: true,
                trigger: 'change',
                validator: async (rule, value) => {
                  if (!value) {
                    return Promise.reject('类别名称不能为空');
                  }
                  if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
                    return Promise.reject(
                        '只能包括大小写字母、中文、数字和短横线（-）、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
                    );
                  }
                },
              },
            ],
          },
          {
            field: 'code',
            component: 'NsInputText',
            label: '类别代码'
          },
          {
            field: 'parentID',
            label: '类别',
            component: 'NsSelectTreeApi',
            componentProps: {
              showCheckedStrategy: 'TreeSelect.SHOW_ALL',
              selectType: 'tree',
              api: `/api/${APP}/objs/ResourceTypeClasses`,
              labelField: 'alias',
              valueField: 'id',
              resultField: '',
              immediate: true,
              placeholder: '请选择类型',
              allowClear: true,
              unSelectable: {
                level: -1,
              }
            }
          }
        ];
      }
      if (menuKey === 'remove') {
        const thisObj = this;
        NsModal.confirm(
            {
              title: '警告',
              content: `确定要删除该项吗？\n删除后不可恢复，请谨慎操作！`,
              okText: '确认',
              cancelText: '取消',
              onOk() {
                http.delete(`/api/${APP}/objs/ResourceTypeClasses`, {id: data['id']}).then(() => {
                  NsMessage.success('删除成功');
                  if (data['code']) {
                    thisObj.updateFormModel( data['code']);
                    thisObj.setTableSession(thisObj.getPagination.current);
                  }
                  thisObj.getDataTree();
                })
              }
        });
      }
    },
    handleArgumentError(data) {
      const error = data?.response?.data;
      if(error && error['errType'] === 'ArgumentError') {
        this.typeFieldErrors = error['fieldErrors'];
        this.$refs.configRef.triggerSubmit();
      }
    },
    addType() {
      http.post(`/api/${APP}/objs/ResourceTypeClasses`, this.typeData).then((res) => {
        NsMessage.success('操作成功');
        this.getDataTree();
        this.typeData = {};
        this.modalVisible = false;
      }).catch((e)=>{
        this.handleArgumentError(e)
      })
    },
    editType() {
      if (Object.keys(this.typeData).includes('parentID')) {
        this.typeData['parentID'] = 0;
      }
      http.put(`/api/${APP}/objs/ResourceTypeClasses`, this.typeData).then((res) => {
        NsMessage.success('操作成功');
        this.getDataTree();
        this.typeData = {};
        this.modalVisible = false;
      }).catch((e)=>{
        this.handleArgumentError(e)
      })
    },
    removeType() {
      console.log(this.typeData)
    },
    handleOk() {
      if (['add'].includes(this.modalOperation.key)) {
        this.$refs.configRef.triggerSubmit().then(() => {
          this.addType();
        });
      }
      if (['edit'].includes(this.modalOperation.key)) {
        this.$refs.configRef.triggerSubmit().then(() => {
          this.editType();
        });
      }
      if (['remove'].includes(this.modalOperation.key)) {
        this.removeType();
      }
    },
    cancel() {
      this.typeData = {};
      this.modalVisible = false;
      this.typeFieldErrors = {};
    }
  },
});
</script>

<style lang="less" scoped>
.ns-table-main {
  flex-wrap: nowrap;
}

:deep(.ns-table-header) {
  min-width: unset;
  .ant-btn {
    margin-left: 0 !important;
  }
}

.ns-table-wrapper {
  margin: 0 24px;
}

:deep(.ns-table-search .ns-form-item label) {
  display: none;
}
.type-tree-wrapper {
  color: rgba(0, 0, 0, 0.65);
  border-right: 1px solid rgba(0, 0, 0, 0.08);
  height: 800px;
  overflow-y: auto;

  .tree-top-header {
    display: flex;
    justify-content: space-between;
    cursor: pointer;
    margin-bottom: 4px;
    .tree-node-content-wrapper {
      padding: 0 4px;
      line-height: 30px;
      &.selected {
        background-color: rgba(0, 172, 255, 0.1);
        color: #00acff;
      }
    }
  }
}

:deep(.ant-tree ) {
  color: rgba(0, 0, 0, 0.65);

  .ant-tree-node-content-wrapper.ant-tree-node-selected {
    background-color: rgba(0, 172, 255, 0.1);
    color: #00acff
  }
}

// 卡片列表
.section0 {
  height: 100%;
  max-height: 600px;
  overflow-y: auto;
  .iconRed {
    color: #EB5757;
  }
  .iconGreen {
    color: #0DCB70;
  }
  .font-12 {
    font-size: 12px;
  }
  margin: 0 6px 0 24px;

  .section-content {
    .item {
      width: 24%;
      //border: 1px solid #dedede;
      margin-right: 8px;
      display: inline-block;
      margin-bottom: 10px;
      cursor: pointer;
      //transition: box-shadow 400ms;
      //box-shadow: none;s

      transition-property: box-shadow, border;
      transition-duration: 400ms, 400ms;


      border: 1px solid #F1F3F5;
      box-shadow: 0 0 16px rgba(0, 0, 0, 0.09);
      border-radius: 6px;

      &:hover {
        //box-shadow: 0 2px 12px rgba(0, 172, 255, .7);
        border: 1px solid #6DCFFF;
        box-shadow: 0 0 16px rgba(0, 172, 255, 0.3);
      }

      .item-header {
        background-color: inherit;
        display: flex;
        height: auto;
        padding: 10px 14px 0 14px;
        justify-content: space-between;
        align-items: center;
        //border-bottom: .05rem solid #dedede;
        .info-card-header {
          flex: 1;
          height: 32px;
          max-height: 32px;
          overflow: hidden;
          .card-title {
            font-size: 16px;
            font-weight: 500;
            overflow-x: hidden;
            overflow-y: hidden;
            text-overflow: ellipsis
          }
        }
      }

      .info-item-block {
        height: 90px;
        overflow: hidden;
        align-items: center;
        //border-bottom: .05rem solid #dedede;
        padding: 4px 14px;
        display: flex;

        .card-icon {
          display: flex;
          align-items: center;
          text-align: center;
          //width: 54px;
          max-height: 88px;
          img {
            width: 64px;
            max-height: 88px;
          }
        }

        .card-description-wrapper {
          display: grid;
          height: 88px;
          width: 100%;
          align-items: center;
          overflow: hidden;
          .card-description {
            max-height: 88px;
            padding-left: 6px;

            span {
              line-height: 20px;
            }
          }
        }
      }

      .item-footer {
        padding: 10px 14px;
        background-color: #fafbfe;
        border-bottom-left-radius: 6px;
        border-bottom-right-radius: 6px;

        .card-item-footer {
          display: flex;
          justify-content: space-between;
          width: 100%;
          overflow-x: auto;

          .card-footer-left {
            line-height: 22px;
          }

        }
      }
    }
  }
}
.pagination {
  display: flex;
  justify-content: flex-end;
  padding: 6px;
}
// 无数据
.ant-empty-description {
  color: #bfbfbf;
}
</style>
