assessDirty.vue 6.98 KB
<route lang="yaml">
  name: assessDirty
</route>

<script lang="ts" setup name="assessDirty">
import { ref } from "vue";
import { calcColumnWidth } from "@/utils/index";
import Moment from 'moment';
import {
  getQueryDirtyData,
  getQueryDirtyFields,
  downloadDirtyData
} from '@/api/modules/dataQualityAssess';
import { download } from '@/utils/common'
import { ElMessage } from "element-plus";
import { TableColumnWidth } from "@/utils/enum";

const { proxy } = getCurrentInstance() as any;
const route: any = useRoute();
const planExecGuid = route.query.planExecGuid;
const qualityModelGuid = route.query.qualityModelGuid;
const name = route.query.name;

const dirtyDataLoading = ref(false);
const dirtyData = ref([{
  guid: 1,
}, {
  guid: '2',
  isDirty: true
}, {
  guid: 3
}]);

const dirtyDataFields: any = ref([{
  enName: 'guid',
  chName: '主键',
  dataType: 'string'
}]);

/** 脏数据下载 */
const exportData = () => {
  if (!dirtyData.value.length || !dirtyDataFields.value.length) {
    ElMessage.error('当没有可下载的脏数据');
    return;
  }
  downloadDirtyData({
    planExecGuid: planExecGuid,
    qualityModelGuid: qualityModelGuid
  }).then((res: any) => {
    if (res && !res.msg) {
      download(res, `脏数据-${name}.xlsx`, 'excel');
    } else {
      res?.msg && ElMessage.error(res?.msg);
    }
  })
}

const getTableData = () => {
  dirtyData.value = [];
  dirtyDataLoading.value = true;
  let ps1 = getQueryDirtyData({
    pageSize: pageInfo.value.limit,
    pageIndex: pageInfo.value.curr,
    qualityModelGuid: qualityModelGuid,
    planExecGuid: planExecGuid,
  }).then((res: any) => {
    if (res.code == proxy.$passCode) {
      let data = res.data || {};
      dirtyData.value = data.records || [];
      pageInfo.value.curr = data.pageIndex;
      pageInfo.value.rows = data.totalRows || 0;
    } else {
      ElMessage.error(res.msg);
    }
  });
  let ps2 = getQueryDirtyFields(qualityModelGuid).then((res: any) => {
    if (res.code == proxy.$passCode) {
      dirtyDataFields.value = res.data.fields || [];
    } else {
      ElMessage.error(res.msg);
    }
  })
  Promise.all([ps1, ps2]).then(res => {
    dirtyDataLoading.value = false;
  });
};

onBeforeMount(() => {
  getTableData();
});

const pageInfo = ref({
  limit: 50,
  curr: 1,
  sizes: [
    { label: "10", value: 10 },
    { label: "50", value: 50 },
    { label: "100", value: 100 },
    { label: "150", value: 150 },
    { label: "200", value: 200 },
  ],
  type: "normal",
  rows: 0,
})

const pageChange = (info) => {
  pageInfo.value.curr = Number(info.curr);
  pageInfo.value.limit = Number(info.limit);
  getTableData();
}

const formatterPreviewDate = (row, info) => {
  let enName = info.enName;
  let v = row[enName]?.value;
  if (v === "" || v === 0) {
    return v;
  }
  if (v == null) {
    return '--';
  }
  if (info.dataType === 'datetime') {
    return Moment(v).format('YYYY-MM-DD HH:mm:ss');
  }
  if (info.dataType === 'date') {
    if (isNaN(<any>(new Date(v)))) {
      return Moment(parseInt(v)).format('YYYY-MM-DD');
    } else {
      return Moment(v).format('YYYY-MM-DD');
    }
  }
  return v;
};

const getTextAlign = (field) => {
  if (field.dataType === 'decimal' || field.dataType === 'int' || field.dataType == 'bit' || field.dataType == 'tinyint') {
    return 'right';
  }
  return 'left'
}

/** otherWidth表示使用标题宽度时添加标题排序图标等宽度 */
const calcTableColumnWidth = (data: any[], prop, title, otherWidth = 0) => {
  let d: any[] = [];
  data.forEach((dt) => d.push(dt[prop]));
  return calcColumnWidth(
    d,
    title,
    {
      fontSize: 14,
      fontFamily: "SimSun",
    },
    {
      fontSize: 14,
      fontFamily: "SimSun",
    },
    otherWidth
  );
};

/** 每列字段对应的列宽计算结果。 */
const originTableFieldColumn: any = ref({
  guid: 140
});

watch(
  () => dirtyData.value,
  (val: any[], oldVal) => {
    if (!dirtyDataFields.value?.length) {
      originTableFieldColumn.value = {};
      return;
    }
    originTableFieldColumn.value = {};
    dirtyDataFields.value.forEach((field, index) => {
      originTableFieldColumn.value[field.enName] = calcTableColumnWidth(
        val?.map(v => {
          let json = {};
          for (const k in v) {
            json[k] = v[k]?.value
          }
          return json;
        }) || [],
        field.enName,
        field.chName,
        24
      );
    });
  }
);

const handleDityCellClass = ({ row, column, rowIndex, columnIndex }) => {
  let v = dirtyData.value[rowIndex][column.property];
  if (v?.checkInfo?.length) {
    return 'dirty-cell-bg';
  }
}

</script>

<template>
  <div class="container_wrap">
    <div class="table_tool_wrap">
      <div class="tools_btns">
        <el-button type="primary" @click="exportData" v-preReClick>脏数据下载</el-button>
      </div>
    </div>
    <div class="table_panel_wrap">
      <el-table key="guid" v-loading="dirtyDataLoading" :data="dirtyData" border tooltip-effect="light" style="
                width: 100%;
                min-width: 200px;
                max-width: 100%;
                height: calc(100% - 44px);
                display: inline-block;
              " stripe :cell-class-name="handleDityCellClass">
        <el-table-column v-for="(field, index) in dirtyDataFields" :key="field.enName" :prop="field.enName"
          :label="field.chName" :width="field.dataType === 'datetime'
          ? TableColumnWidth.DATETIME
          : field.dataType === 'date'
            ? TableColumnWidth.DATE
            : originTableFieldColumn[field.enName]
          " :align="getTextAlign(field)" :header-align="getTextAlign(field)" :show-overflow-tooltip="true"
          >
          <template #default="scope">
            <el-tooltip v-if="scope.row[field.enName].checkInfo?.length" placement="bottom-start" effect="light"
              popper-class="table_tooltip" trigger="click">
              <template #content>
                <div style="width: 236px; text-align: justify">
                  <p class="tips_title">不符合规则</p>
                  <p v-for="(item) in (scope.row[field.enName].checkInfo || [])">{{ item }}</p>
                </div>
              </template>
              <span class="dirty-cell-tooltip">{{ formatterPreviewDate(scope.row, field) }}</span>
            </el-tooltip>
            <span v-else>{{ formatterPreviewDate(scope.row, field) }}</span>
          </template>
        </el-table-column>
      </el-table>
      <PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.table_tool_wrap {
  width: 100%;
  height: 44px;
  padding: 8px;

  .tools_btns {
    padding: 0;
  }
}

.table_panel_wrap {
  width: 100%;
  height: calc(100% - 44px);
  padding: 0 8px;
}

:deep(.el-table) {
  .dirty-cell-bg {
    background: #FFF1D4 !important;

    .cell.el-tooltip {
      padding: 0px;
    }
  }

  .dirty-cell-tooltip {
    width: 100%;
    min-height: 24px;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 12px;
  }
}
</style>