🎉 增加多租户数据库隔离、动态数据源切换功能

dev
smallchill 5 years ago
parent 70756ef148
commit 38bf1fd32e
  1. 11
      src/api/system/tenant.js
  2. 632
      src/views/system/tenant.vue

@ -59,6 +59,17 @@ export const setting = (ids, form) => {
}) })
} }
export const datasource = (tenantId, datasourceId) => {
return request({
url: '/api/blade-system/tenant/datasource',
method: 'post',
params: {
tenantId,
datasourceId
}
})
}
export const info = (domain) => { export const info = (domain) => {
return request({ return request({
url: '/api/blade-system/tenant/info', url: '/api/blade-system/tenant/info',

@ -32,14 +32,20 @@
icon="el-icon-setting" icon="el-icon-setting"
@click="handleSetting">授权配置 @click="handleSetting">授权配置
</el-button> </el-button>
<el-button size="small"
plain
v-if="userInfo.role_name.includes('administrator')"
icon="el-icon-coin"
@click="handleDatasource">数据源配置
</el-button>
</template> </template>
<template slot-scope="{row}" <template slot-scope="{row}"
slot="accountNumber"> slot="accountNumber">
<el-tag>{{row.accountNumber>0?row.accountNumber:'不限制'}}</el-tag> <el-tag>{{ row.accountNumber > 0 ? row.accountNumber : '不限制' }}</el-tag>
</template> </template>
<template slot-scope="{row}" <template slot-scope="{row}"
slot="expireTime"> slot="expireTime">
<el-tag>{{row.expireTime?row.expireTime:'不限制'}}</el-tag> <el-tag>{{ row.expireTime ? row.expireTime : '不限制' }}</el-tag>
</template> </template>
</avue-crud> </avue-crud>
<el-dialog title="租户授权配置" <el-dialog title="租户授权配置"
@ -48,315 +54,375 @@
width="450px"> width="450px">
<avue-form :option="settingOption" v-model="settingForm" @submit="handleSubmit"/> <avue-form :option="settingOption" v-model="settingForm" @submit="handleSubmit"/>
</el-dialog> </el-dialog>
<el-dialog title="租户数据源配置"
append-to-body
:visible.sync="datasourceBox"
width="450px">
<avue-form :option="datasourceOption" v-model="datasourceForm" @submit="handleDatasourceSubmit"/>
</el-dialog>
</basic-container> </basic-container>
</template> </template>
<script> <script>
import {getList, getDetail, remove, update, add, setting} from "@/api/system/tenant"; import {getList, getDetail, remove, update, add, setting, datasource} from "@/api/system/tenant";
import {mapGetters} from "vuex"; import {mapGetters} from "vuex";
export default { export default {
data() { data() {
return { return {
form: {}, form: {},
selectionList: [], selectionList: [],
query: {}, query: {},
loading: true, loading: true,
box: false, box: false,
page: { datasourceBox: false,
pageSize: 10, page: {
currentPage: 1, pageSize: 10,
total: 0 currentPage: 1,
}, total: 0
option: { },
height: 'auto', option: {
calcHeight: 30, height: 'auto',
tip: false, calcHeight: 30,
searchShow: true, tip: false,
searchMenuSpan: 6, searchShow: true,
border: true, searchMenuSpan: 6,
index: true, border: true,
selection: true, index: true,
viewBtn: true, selection: true,
dialogWidth: 900, viewBtn: true,
dialogClickModal: false, dialogWidth: 900,
column: [ dialogClickModal: false,
{ column: [
label: "租户ID", {
prop: "tenantId", label: "租户ID",
width: 100, prop: "tenantId",
search: true, width: 100,
addDisplay: false, search: true,
editDisplay: false, addDisplay: false,
span: 24, editDisplay: false,
rules: [{ span: 24,
required: true, rules: [{
message: "请输入租户ID", required: true,
trigger: "blur" message: "请输入租户ID",
}] trigger: "blur"
}, }]
{ },
label: "租户名称", {
prop: "tenantName", label: "租户名称",
search: true, prop: "tenantName",
width: 180, search: true,
span: 24, width: 180,
rules: [{ span: 24,
required: true, rules: [{
message: "请输入参数名称", required: true,
trigger: "blur" message: "请输入参数名称",
}] trigger: "blur"
}, }]
{ },
label: "联系人", {
prop: "linkman", label: "联系人",
width: 100, prop: "linkman",
search: true, width: 100,
rules: [{ search: true,
required: true, rules: [{
message: "请输入联系人", required: true,
trigger: "blur" message: "请输入联系人",
}] trigger: "blur"
}, }]
{ },
label: "联系电话", {
prop: "contactNumber", label: "联系电话",
width: 150, prop: "contactNumber",
}, width: 150,
{ },
label: "联系地址", {
prop: "address", label: "联系地址",
span: 24, prop: "address",
minRows: 2, span: 24,
type: "textarea", minRows: 2,
hide: true, type: "textarea",
}, hide: true,
{ },
label: "账号额度", {
prop: "accountNumber", label: "账号额度",
width: 90, prop: "accountNumber",
slot: true, width: 90,
addDisplay: false, slot: true,
editDisplay: false, addDisplay: false,
}, editDisplay: false,
{ },
label: "过期时间", {
prop: "expireTime", label: "过期时间",
width: 180, prop: "expireTime",
slot: true, width: 180,
addDisplay: false, slot: true,
editDisplay: false, addDisplay: false,
}, editDisplay: false,
{ },
label: "绑定域名", {
prop: "domain", label: "绑定域名",
span: 24, prop: "domain",
}, span: 24,
{ },
label: "系统背景", {
prop: "backgroundUrl", label: "系统背景",
type: 'upload', prop: "backgroundUrl",
listType: 'picture-img', type: 'upload',
action: '/api/blade-resource/oss/endpoint/put-file', listType: 'picture-img',
propsHttp: { action: '/api/blade-resource/oss/endpoint/put-file',
res: 'data', propsHttp: {
url: 'link', res: 'data',
}, url: 'link',
hide: true,
span: 24,
},
]
},
data: [],
settingForm: {},
settingOption: {
column: [
{
label: "账号额度",
prop: "accountNumber",
type: "number",
span: 24,
}, },
{ hide: true,
label: "过期时间", span: 24,
prop: "expireTime", },
type: "date", ]
format: "yyyy-MM-dd hh:mm:ss", },
valueFormat: "yyyy-MM-dd hh:mm:ss", data: [],
span: 24, settingForm: {},
settingOption: {
column: [
{
label: "账号额度",
prop: "accountNumber",
type: "number",
span: 24,
},
{
label: "过期时间",
prop: "expireTime",
type: "date",
format: "yyyy-MM-dd hh:mm:ss",
valueFormat: "yyyy-MM-dd hh:mm:ss",
span: 24,
},
]
},
datasourceForm: {},
datasourceOption: {
column: [
{
label: "数据源",
prop: "datasourceId",
search: true,
span: 24,
type: "select",
dicUrl: "/api/blade-develop/datasource/select",
props: {
label: "name",
value: "id"
}, },
] rules: [{
} required: true,
message: "请选择数据源",
trigger: "blur"
}]
},
]
}
};
},
computed: {
...mapGetters(["userInfo", "permission"]),
permissionList() {
return {
addBtn: this.vaildData(this.permission.tenant_add, false),
viewBtn: this.vaildData(this.permission.tenant_view, false),
delBtn: this.vaildData(this.permission.tenant_delete, false),
editBtn: this.vaildData(this.permission.tenant_edit, false)
}; };
}, },
computed: { ids() {
...mapGetters(["userInfo", "permission"]), let ids = [];
permissionList() { this.selectionList.forEach(ele => {
return { ids.push(ele.id);
addBtn: this.vaildData(this.permission.tenant_add, false), });
viewBtn: this.vaildData(this.permission.tenant_view, false), return ids.join(",");
delBtn: this.vaildData(this.permission.tenant_delete, false), },
editBtn: this.vaildData(this.permission.tenant_edit, false) tenantId() {
}; return this.selectionList[0].tenantId;
}, }
ids() { },
let ids = []; methods: {
this.selectionList.forEach(ele => { rowSave(row, done, loading) {
ids.push(ele.id); add(row).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
}); });
return ids.join(","); done();
} }, error => {
window.console.log(error);
loading();
});
}, },
methods: { rowUpdate(row, index, done, loading) {
rowSave(row, done, loading) { update(row).then(() => {
add(row).then(() => { this.onLoad(this.page);
this.onLoad(this.page); this.$message({
this.$message({ type: "success",
type: "success", message: "操作成功!"
message: "操作成功!"
});
done();
}, error => {
window.console.log(error);
loading();
}); });
}, done();
rowUpdate(row, index, done, loading) { }, error => {
update(row).then(() => { window.console.log(error);
loading();
});
},
rowDel(row) {
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return remove(row.id);
})
.then(() => {
this.onLoad(this.page); this.onLoad(this.page);
this.$message({ this.$message({
type: "success", type: "success",
message: "操作成功!" message: "操作成功!"
}); });
done();
}, error => {
window.console.log(error);
loading();
}); });
}, },
rowDel(row) { beforeOpen(done, type) {
this.$confirm("确定将选择数据删除?", { if (["view"].includes(type)) {
confirmButtonText: "确定", getDetail(this.form.id).then(res => {
cancelButtonText: "取消", const data = res.data.data;
type: "warning" if (!(data.accountNumber > 0)) {
}) data.accountNumber = "不限制";
.then(() => { }
return remove(row.id); if (!data.expireTime) {
}) data.expireTime = "不限制";
.then(() => { }
this.onLoad(this.page); this.form = data;
this.$message({ });
type: "success", }
message: "操作成功!" done();
}); },
}); searchReset() {
}, this.query = {};
beforeOpen(done, type) { this.onLoad(this.page);
if (["view"].includes(type)) { },
getDetail(this.form.id).then(res => { searchChange(params, done) {
const data = res.data.data; this.query = params;
if (!(data.accountNumber > 0)) { this.page.currentPage = 1;
data.accountNumber = "不限制"; this.onLoad(this.page, params);
} done();
if (!data.expireTime) { },
data.expireTime = "不限制"; selectionChange(list) {
} this.selectionList = list;
this.form = data; },
}); selectionClear() {
} this.selectionList = [];
done(); this.$refs.crud.toggleSelection();
}, },
searchReset() { handleDelete() {
this.query = {}; if (this.selectionList.length === 0) {
this.onLoad(this.page); this.$message.warning("请选择至少一条数据");
}, return;
searchChange(params, done) { }
this.query = params; this.$confirm("确定将选择数据删除?", {
this.page.currentPage = 1; confirmButtonText: "确定",
this.onLoad(this.page, params); cancelButtonText: "取消",
done(); type: "warning"
}, })
selectionChange(list) { .then(() => {
this.selectionList = list; return remove(this.ids);
},
selectionClear() {
this.selectionList = [];
this.$refs.crud.toggleSelection();
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}) })
.then(() => { .then(() => {
return remove(this.ids);
})
.then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
this.$refs.crud.toggleSelection();
});
},
handleSetting() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
if (this.selectionList.length === 1) {
getDetail(this.selectionList[0].id).then(res => {
const data = res.data.data;
this.settingForm.accountNumber = data.accountNumber;
this.settingForm.expireTime = data.expireTime;
});
} else {
this.settingForm.accountNumber = -1;
this.settingForm.expireTime = '';
}
this.box = true;
},
handleSubmit(form, done, loading) {
setting(this.ids, form).then(() => {
this.onLoad(this.page); this.onLoad(this.page);
this.$message({ this.$message({
type: "success", type: "success",
message: "配置成功!" message: "操作成功!"
}); });
done(); this.$refs.crud.toggleSelection();
this.box = false;
}, error => {
window.console.log(error);
loading();
}); });
}, },
currentChange(currentPage) { handleSetting() {
this.page.currentPage = currentPage; if (this.selectionList.length === 0) {
}, this.$message.warning("请选择至少一条数据");
sizeChange(pageSize) { return;
this.page.pageSize = pageSize; }
}, if (this.selectionList.length === 1) {
refreshChange() { getDetail(this.selectionList[0].id).then(res => {
this.onLoad(this.page, this.query);
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
const data = res.data.data; const data = res.data.data;
this.page.total = data.total; this.settingForm.accountNumber = data.accountNumber;
this.data = data.records; this.settingForm.expireTime = data.expireTime;
this.loading = false;
this.selectionClear();
}); });
} else {
this.settingForm.accountNumber = -1;
this.settingForm.expireTime = '';
}
this.box = true;
},
handleDatasource() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
} }
if (this.selectionList.length !== 1) {
this.$message.warning("只能选择一条数据");
return;
}
getDetail(this.selectionList[0].id).then(res => {
const data = res.data.data;
this.datasourceForm.datasourceId = data.datasourceId;
});
this.datasourceBox = true;
},
handleSubmit(form, done, loading) {
setting(this.ids, form).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "配置成功!"
});
done();
this.box = false;
}, error => {
window.console.log(error);
loading();
});
},
handleDatasourceSubmit(form, done, loading) {
datasource(this.tenantId, form.datasourceId).then(() => {
this.$message({
type: "success",
message: "配置成功!"
});
done();
this.datasourceBox = false;
}, error => {
window.console.log(error);
loading();
});
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
refreshChange() {
this.onLoad(this.page, this.query);
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
const data = res.data.data;
this.page.total = data.total;
this.data = data.records;
this.loading = false;
this.selectionClear();
});
} }
}; }
};
</script> </script>
<style> <style>

Loading…
Cancel
Save