Files
mayfly-go/mayfly_go_web/src/views/ops/db/DbSqlExecLog.vue
2024-02-29 22:12:50 +08:00

181 lines
5.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="db-sql-exec-log">
<page-table
ref="pageTableRef"
:page-api="dbApi.getSqlExecs"
:lazy="true"
height="100%"
:search-items="searchItems"
v-model:query-form="query"
:columns="columns"
>
<template #dbSelect>
<el-select v-model="query.db" placeholder="请选择数据库" filterable clearable>
<el-option v-for="item in dbs" :key="item" :label="`${item}`" :value="item"> </el-option>
</el-select>
</template>
<template #action="{ data }">
<el-link
v-if="
data.status == DbSqlExecStatusEnum.Success.value &&
(data.type == DbSqlExecTypeEnum.Update.value || data.type == DbSqlExecTypeEnum.Delete.value)
"
type="primary"
plain
size="small"
:underline="false"
@click="onShowRollbackSql(data)"
>
还原SQL</el-link
>
</template>
</page-table>
<el-dialog width="55%" :title="`还原SQL`" v-model="rollbackSqlDialog.visible">
<el-input type="textarea" :autosize="{ minRows: 15, maxRows: 30 }" v-model="rollbackSqlDialog.sql" size="small"> </el-input>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, Ref, ref, toRefs, watch } from 'vue';
import { dbApi } from './api';
import { DbSqlExecTypeEnum, DbSqlExecStatusEnum } from './enums';
import PageTable from '@/components/pagetable/PageTable.vue';
import { TableColumn } from '@/components/pagetable';
import { SearchItem } from '@/components/SearchForm';
const props = defineProps({
dbId: {
type: [Number],
required: true,
},
dbs: {
type: [Array<String>],
required: true,
},
});
const searchItems = [
SearchItem.slot('db', '数据库', 'dbSelect'),
SearchItem.input('table', '表名'),
SearchItem.select('type', '操作类型').withEnum(DbSqlExecTypeEnum),
];
const columns = ref([
TableColumn.new('db', '数据库'),
TableColumn.new('table', '表'),
TableColumn.new('type', '类型').typeTag(DbSqlExecTypeEnum).setAddWidth(10),
TableColumn.new('creator', '执行人'),
TableColumn.new('sql', 'SQL').canBeautify(),
TableColumn.new('remark', '备注'),
TableColumn.new('status', '执行状态').typeTag(DbSqlExecStatusEnum),
TableColumn.new('res', '执行结果'),
TableColumn.new('createTime', '执行时间').isTime(),
TableColumn.new('oldValue', '原值').canBeautify(),
TableColumn.new('action', '操作').isSlot().setMinWidth(90).fixedRight().alignCenter(),
]);
const pageTableRef: Ref<any> = ref(null);
const state = reactive({
dbs: [],
query: {
dbId: 0,
db: '',
table: '',
status: [DbSqlExecStatusEnum.Success.value, DbSqlExecStatusEnum.Fail.value].join(','),
type: null,
pageNum: 1,
pageSize: 10,
},
rollbackSqlDialog: {
visible: false,
sql: '',
},
filterDb: {
param: '',
cache: [],
list: [],
},
});
const { query, rollbackSqlDialog } = toRefs(state);
onMounted(async () => {
state.query.dbId = props.dbId;
state.query.pageNum = 1;
await searchSqlExecLog();
});
watch(props, async () => {
state.query.dbId = props.dbId;
state.query.pageNum = 1;
await searchSqlExecLog();
});
const searchSqlExecLog = async () => {
if (state.query.dbId) {
pageTableRef.value.search();
}
};
const onShowRollbackSql = async (sqlExecLog: any) => {
const columns = await dbApi.columnMetadata.request({ id: sqlExecLog.dbId, db: sqlExecLog.db, tableName: sqlExecLog.table });
const primaryKey = getPrimaryKey(columns);
const oldValue = JSON.parse(sqlExecLog.oldValue);
let schema = '';
let dbArr = sqlExecLog.db.split('/');
if (dbArr.length == 2) {
schema = dbArr[1] + '.';
}
const rollbackSqls = [];
if (sqlExecLog.type == DbSqlExecTypeEnum.Update.value) {
for (let ov of oldValue) {
const setItems = [];
for (let key in ov) {
if (key == primaryKey) {
continue;
}
setItems.push(`${key} = ${wrapValue(ov[key])}`);
}
rollbackSqls.push(`UPDATE ${schema}${sqlExecLog.table} SET ${setItems.join(', ')} WHERE ${primaryKey} = ${wrapValue(ov[primaryKey])};`);
}
} else if (sqlExecLog.type == DbSqlExecTypeEnum.Delete.value) {
const columnNames = columns.map((c: any) => c.columnName);
for (let ov of oldValue) {
const values = [];
for (let column of columnNames) {
values.push(wrapValue(ov[column]));
}
rollbackSqls.push(`INSERT INTO ${schema}${sqlExecLog.table} (${columnNames.join(', ')}) VALUES (${values.join(', ')});`);
}
}
state.rollbackSqlDialog.sql = rollbackSqls.join('\n');
state.rollbackSqlDialog.visible = true;
};
const getPrimaryKey = (columns: any) => {
const col = columns.find((c: any) => c.isPrimaryKey);
if (col) {
return col.columnName;
}
return columns[0].columnName;
};
/**
* 包装值如果值类型为number则直接返回其他则需要使用''包装
*/
const wrapValue = (val: any) => {
if (typeof val == 'number') {
return val;
}
return `'${val}'`;
};
</script>
<style lang="scss"></style>