2064af17创建于 2025年1月20日历史提交
<template>
  <div class="history-table-wrapper">
    <el-table
      :data="showList"
      border
      tooltip-effect="light"
      :tooltip-options="{ rawContent: true }"
      style="width: 100%"
      v-loading="loading"
      class="history-table"
    >
      <el-table-column align="center" :label="t('historyTable.column.no')" width="60">
        <template #default="{ row }">
          <div>
            <span v-if="row.lock" class="iconfont icon-lock num-icon"></span>
            {{ row.index }}
          </div>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        prop="startTime"
        :label="t('historyTable.column.startTime')"
        width="160"
      ></el-table-column>
      <el-table-column
        header-align="center"
        align="center"
        :label="t('historyTable.column.status')"
        width="75"
      >
        <template #default="{ row }">
          <span :class="['status-dot', row.success ? 'success' : 'fail']"></span>
          {{ row.success ? $t('message.success') : $t('message.fail') }}
        </template>
      </el-table-column>
      <el-table-column align="center" :label="t('historyTable.column.sql')">
        <template #header>
          <FilterTableDataHeaderSlot v-model="sqlFilterInput" v-model:show="showSqlFilter">
            {{ $t('historyTable.column.sql') }}
          </FilterTableDataHeaderSlot>
        </template>
        <template #default="{ row }">
          <div class="single-line-omission">
            {{ row.sql.slice(0, 200) }}
          </div>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        prop="updateCount"
        :label="t('historyTable.column.effectLineNumber')"
        width="75"
      ></el-table-column>
      <el-table-column
        align="center"
        prop="executeTime"
        :label="t('historyTable.column.executeTime')"
        width="100"
      ></el-table-column>
      <el-table-column
        header-align="center"
        align="left"
        :label="t('historyTable.column.operation')"
        width="100"
      >
        <template #default="{ row }">
          <span
            class="iconfont icon-yulan opetation-button"
            @click="handlePreviewSql(row)"
            :title="$t('historyTable.dialog.title')"
          ></span>
          <span
            v-if="!row.lock"
            class="iconfont icon-lock opetation-button"
            @click="handleLock(row, true)"
            :title="$t('button.lock')"
          ></span>
          <span
            v-if="row.lock"
            class="iconfont icon-unlock opetation-button"
            @click="handleLock(row, false)"
            :title="$t('button.unlock2')"
          ></span>
          <span
            v-if="!row.lock"
            class="iconfont icon-shanchu opetation-button"
            @click="handleDelelte(row)"
            :title="$t('button.delete')"
          ></span>
          <el-icon
            v-if="!row.success && row.errMes"
            class="opetation-button"
            style="vertical-align: text-bottom; font-size: 17px"
            @click="handlePreviewError(row)"
            :title="$t('historyTable.column.errorMessage')"
            ><Warning
          /></el-icon>
        </template>
      </el-table-column>
    </el-table>
    <ShowHistorySqlDetailDialog v-model="visibleSqlDetailDialog" :sql="sqlDetail" />
    <ErrorMessageDetailDialog v-model="visibleErrorDetailDialog" :sql="errorDetail" />
  </div>
</template>

<script lang="ts" setup>
  import { Tooltip as VxeTooltip } from 'vxe-table';
  import { ElMessage, ElMessageBox } from 'element-plus';
  import { useUserStore } from '@/store/modules/user';
  import { useI18n } from 'vue-i18n';
  import ShowHistorySqlDetailDialog from './ShowHistorySqlDetailDialog.vue';
  import ErrorMessageDetailDialog from './ErrorMessageDetailDialog.vue';
  import FilterTableDataHeaderSlot from '@/components/FilterTableDataHeaderSlot.vue';
  import { querySqlHistory, updateSqlHistory, deleteSqlHistory } from '@/api/sqlHistory';

  interface SqlTableRow {
    id: number;
    startTime: string;
    sql: string;
    executeTime: string;
    webUser: string;
    success: boolean;
    errMes: string;
    lock: boolean;
    updateCount: number;
    index: number;
  }

  const UserStore = useUserStore();
  const { t } = useI18n();
  const loading = ref(false);
  const visibleSqlDetailDialog = ref(false);
  const visibleErrorDetailDialog = ref(false);
  const sqlDetail = ref('');
  const errorDetail = ref('');
  const tableData = ref<SqlTableRow[]>([]);
  const showSqlFilter = ref(false);
  const sqlFilterInput = ref('');

  const showList = computed(() => {
    return tableData.value.filter(
      (item) => item.lock || item.sql.indexOf(sqlFilterInput.value) > -1,
    );
  });

  const getData = async () => {
    loading.value = true;
    hideNamefilter();
    querySqlHistory({
      webUser: UserStore.userId,
    })
      .then((res) => {
        tableData.value = res.map((item, index) => ({
          ...item,
          index: index + 1,
        }));
      })
      .finally(() => {
        loading.value = false;
      });
  };

  const hideNamefilter = () => {
    showSqlFilter.value = false;
    sqlFilterInput.value = '';
  };

  const handlePreviewSql = (row) => {
    sqlDetail.value = row.sql;
    visibleSqlDetailDialog.value = true;
  };
  const handlePreviewError = (row) => {
    errorDetail.value = row.errMes;
    visibleErrorDetailDialog.value = true;
  };
  const handleLock = async (row: SqlTableRow, status: boolean) => {
    await updateSqlHistory({
      id: row.id,
      lock: status,
      webUser: UserStore.userId,
    });
    ElMessage.success(t('message.setSuccess'));
    getData();
  };
  const handleDelelte = (row: SqlTableRow) => {
    ElMessageBox.confirm(t('message.deleteRecord'), t('common.warning'), {
      type: 'warning',
    })
      .then(async () => {
        await deleteSqlHistory({ id: row.id });
        ElMessage({
          type: 'success',
          message: t('message.deleteSuccess'),
        });
        getData();
      })
      .catch(() => ({}));
  };

  defineExpose({
    getData,
  });
</script>

<style lang="scss" scoped>
  .history-table-wrapper {
    height: 100%;
    overflow: hidden;
  }
  .history-table {
    font-size: 12px;
    height: 100%;
    :deep(.el-table__cell) {
      padding: 3px 0;
    }

    :deep(.cell) {
      padding: 0 8px;
    }
  }
  .status-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    &.success {
      background: green;
    }
    &.fail {
      background: red;
    }
  }
  .num-icon {
    margin-right: 5px;
    user-select: none;
    font-size: 16px;
  }
  .opetation-button {
    color: var(--el-color-primary);
    cursor: pointer;
    &:nth-child(n + 2) {
      margin-left: 5px;
    }
  }
</style>