Browse Source

(+)数据恢复api接口

master
peng.peng 2 years ago
parent
commit
7cba9151f3
  1. 118
      api/app/lib/controllers/backups/index.js
  2. 89
      api/app/lib/models/backups.js
  3. 23
      api/app/lib/routes/backups/index.js
  4. 43
      web/client/src/sections/backups/containers/backupTask.js
  5. 2
      web/client/src/sections/backups/containers/index.js

118
api/app/lib/controllers/backups/index.js

@ -0,0 +1,118 @@
'use strict';
function getBackupsList(opts) {
return async function (ctx, next) {
const models = ctx.fs.dc.models;
const { page, limit, name } = ctx.query;
const Op = ctx.fs.dc.ORM.Op;
let errMsg = { message: '获取数据备份失败' }
try {
let searchWhere = {
username: { $not: 'SuperAdmin' }
}
let option = {
where: searchWhere,
order: [["id", "desc"]],
attributes: { exclude: ['password'] },
}
if (name) {
searchWhere.note = { $like: '%' + name + '%' };
}
option.where = searchWhere
let limit_ = limit || 10;
let page_ = page || 1;
let offset = (page_ - 1) * limit_;
if (limit && page) {
option.limit = limit_
option.offset = offset
}
const res = await models.Backups.findAndCount(option);
ctx.status = 200;
ctx.body = res;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errMsg
}
}
}
// 新增数据备份
function addBackups(opts) {
return async function (ctx, next) {
const models = ctx.fs.dc.models;
try {
let rslt = ctx.request.body;
await models.Backups.create(Object.assign({}, rslt))
ctx.status = 204;
ctx.body = { message: '新建数据备份成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '新建数据备份失败' }
}
}
}
// 修改数据备份
function editBackups(opts) {
return async function (ctx, next) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
const body = ctx.request.body;
await models.Backups.update(
body,
{ where: { id: id, } }
)
ctx.status = 204;
ctx.body = { message: '修改数据备份成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '修改数据备份失败' }
}
}
}
// 删除数据备份
function deleteBackups(opts) {
return async function (ctx, next) {
try {
const models = ctx.fs.dc.models;
const { id } = ctx.params;
await models.Backups.destroy({
where: {
id: id
}
})
ctx.status = 204;
ctx.body = { message: '删除数据备份成功' }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: '删除数据备份失败' }
}
}
}
module.exports = {
getBackupsList,
addBackups,
editBackups,
deleteBackups,
}

89
api/app/lib/models/backups.js

@ -0,0 +1,89 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Backups = sequelize.define("backups", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "backups_id_uindex"
},
note: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "备注信息",
primaryKey: false,
field: "note",
autoIncrement: false
},
databases: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "databases",
autoIncrement: false
},
size: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "size",
autoIncrement: false
},
createTime: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "create_time",
autoIncrement: false
},
completeTime: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: "备份完成时间",
primaryKey: false,
field: "complete_time",
autoIncrement: false
},
state: {
type: user - defined,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "state",
autoIncrement: false
},
source: {
type: DataTypes.TEXT,
allowNull: true,
defaultValue: null,
comment: "备份文件路径",
primaryKey: false,
field: "source",
autoIncrement: false
}
}, {
tableName: "backups",
comment: "",
indexes: []
});
dc.models.Backups = Backups;
return Backups;
};

23
api/app/lib/routes/backups/index.js

@ -0,0 +1,23 @@
'use strict';
const backups = require('../../controllers/backups/index');
module.exports = function (app, router, opts, AuthCode) {
app.fs.api.logAttr['POST/meta/backups'] = { content: '增加数据备份', visible: true };
router.post('/meta/backups', backups.addUser(opts))
// 修改数据备份信息
app.fs.api.logAttr['PUT/meta/backups/:id'] = { content: '修改数据备份信息', visible: true };
router.put('/meta/backups/:id', backups.editUser(opts))
// 删除数据备份信息
app.fs.api.logAttr['DEL/meta/backups/:id'] = { content: '删除数据备份信息', visible: true };
router.del('/meta/backups/:id', backups.deleteUser(opts))
//获取数据备份信息列表
app.fs.api.logAttr['GET/meta/backupss'] = { content: '获取数据备份信息列表', visible: true };
router.get('/meta/backupss', backups.getUserList(opts));
};

43
web/client/src/sections/backups/containers/restore.js → web/client/src/sections/backups/containers/backupTask.js

@ -12,24 +12,16 @@ function Member(props) {
const [pageSize, setPageSize] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
const [searchValue, setSearchValue] = useState('')
const [visible, setVisible] = useState(false);//是否展示新增编辑模态框
const [editData, setEditData] = useState(null);//模态框编辑数据
const [refreshTree, setRefreshTree] = useState(1);
const [searchRole, setSearchRole] = useState()
const queryData = (search) => {
const query = {
limit: search ? 10 : pageSize || 10,
page: search ? 1 : currentPage || 1,
name: searchValue,
role: searchRole
}
dispatch(actions.memberManagement.getUserList(query));
}
const { data: treeData = [] } = useFsRequest({
url: ApiTable.getResourceCatalog,
refreshDeps: [refreshTree]
});
useEffect(() => {
queryData();
@ -42,20 +34,20 @@ function Member(props) {
render: (text, record, index) => { return index + 1 }
},
{
title: '姓名',
dataIndex: 'name',
title: '备份信息',
dataIndex: 'note',
},
{
title: '用户名',
dataIndex: 'username',
title: '备份大小',
dataIndex: 'size',
},
{
title: '角色',
dataIndex: 'role',
title: '备份时间',
dataIndex: 'createTime',
},
{
title: '状态',
dataIndex: 'enabled',
dataIndex: 'state',
render: (text, record) => {
return <span style={{ color: record?.enabled ? '#87d068' : '#f50' }}> {record?.enabled ? '正常' : '禁用'}</span>
}
@ -67,13 +59,7 @@ function Member(props) {
valueType: 'option',
render: (text, record) => {
const options = [];
options.push(<MemberModal
editData={record}
triggerRender={<a>编辑</a>}
title="编辑用户"
onFinish={onFinish}
key="editUser"
/>)
options.push(
<Popconfirm
key="del"
@ -152,18 +138,10 @@ function Member(props) {
/>
</Col>
<Col span={12} style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}>
<span>用户姓名 </span> <Input
<span>备份信息 </span> <Input
value={searchValue} onChange={e => { setSearchValue(e.target.value) }}
style={{ width: 220, marginRight: 15 }} placeholder="请输入" />
<span>角色 </span> <Select
allowClear
value={searchRole} onChange={e => { setSearchRole(e) }}
style={{ width: 220, marginRight: 15 }} placeholder="请选择" >
<Select.Option value={'系统管理员'}>系统管理员</Select.Option>
<Select.Option value={'数据消费者'}>数据消费者</Select.Option>
</Select>
<Button onClick={() => {
setCurrentPage(1)
setPageSize(10)
@ -201,6 +179,7 @@ function Member(props) {
onChange: (page, pageSize) => {
setCurrentPage(page);
setPageSize(pageSize);
}
}}
dataSource={member?.rows || []}

2
web/client/src/sections/backups/containers/index.js

@ -1,5 +1,5 @@
'use strict';
import Restore from './restore';
import Restore from './backupTask';
export { Restore };

Loading…
Cancel
Save