chore: 同步Saber2.9版本

master
ssc 4 years ago
parent 3b6130d6f6
commit 2dc71dd150
  1. 2
      package.json
  2. 9
      public/cdn/avue/2.8.12/avue.min.js
  3. 1
      public/cdn/avue/2.8.12/index.css
  4. 9
      public/cdn/avue/2.8.18/avue.min.js
  5. 1
      public/cdn/avue/2.8.18/index.css
  6. 9
      public/cdn/avue/2.8.25/avue.min.js
  7. 1
      public/cdn/avue/2.8.25/index.css
  8. 5
      public/index.html
  9. 21
      src/api/system/tenant.js
  10. 50
      src/api/system/tenantpackage.js
  11. 10
      src/api/system/user.js
  12. 10
      src/api/user.js
  13. 1
      src/lang/en.js
  14. 1
      src/lang/zh.js
  15. 75
      src/page/index/top/index.vue
  16. 4
      src/page/login/userlogin.vue
  17. 9
      src/store/modules/user.js
  18. 5
      src/views/authority/datascope.vue
  19. 2
      src/views/desk/notice.vue
  20. 157
      src/views/system/tenant.vue
  21. 243
      src/views/system/tenantpackage.vue
  22. 47
      src/views/system/user.vue
  23. 2
      src/views/tool/code.vue
  24. 32
      src/views/wel/index.vue

@ -1,6 +1,6 @@
{ {
"name": "saber-admin", "name": "saber-admin",
"version": "2.8.2", "version": "2.9.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -15,7 +15,7 @@
<link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/index.css"> <link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/index.css">
<link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/avue/iconfont.css"> <link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/avue/iconfont.css">
<link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/saber/iconfont.css"> <link rel="stylesheet" href="<%= BASE_URL %>cdn/iconfont/saber/iconfont.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@smallwei/avue@2.8.24/lib/index.css"> <link rel="stylesheet" href="<%= BASE_URL %>cdn/avue/2.8.25/index.css">
<script src="<%= BASE_URL %>cdn/xlsx/FileSaver.min.js"></script> <script src="<%= BASE_URL %>cdn/xlsx/FileSaver.min.js"></script>
<script src="<%= BASE_URL %>cdn/xlsx/xlsx.full.min.js"></script> <script src="<%= BASE_URL %>cdn/xlsx/xlsx.full.min.js"></script>
<link rel="icon" href="<%= BASE_URL %>favicon.png"> <link rel="icon" href="<%= BASE_URL %>favicon.png">
@ -104,12 +104,11 @@
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
<script src="<%= BASE_URL %>util/aes.js" charset="utf-8"></script> <script src="<%= BASE_URL %>util/aes.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/vue/2.6.10/vue.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/vue/2.6.10/vue.min.js" charset="utf-8"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> -->
<script src="<%= BASE_URL %>cdn/vuex/3.1.1/vuex.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/vuex/3.1.1/vuex.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/vue-router/3.0.1/vue-router.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/vue-router/3.0.1/vue-router.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/axios/1.0.0/axios.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/axios/1.0.0/axios.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/element-ui/2.15.1/index.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/element-ui/2.15.1/index.js" charset="utf-8"></script>
<script src="https://cdn.jsdelivr.net/npm/@smallwei/avue@2.8.24" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/avue/2.8.25/avue.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/avue-form-design/index.umd.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/avue-form-design/index.umd.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/wf-design/index.umd.min.js" charset="utf-8"></script> <script src="<%= BASE_URL %>cdn/wf-design/index.umd.min.js" charset="utf-8"></script>
</body> </body>

@ -79,3 +79,24 @@ export const info = (domain) => {
} }
}) })
} }
export const packageInfo = (tenantId) => {
return request({
url: '/api/blade-system/tenant/package-detail',
method: 'get',
params: {
tenantId
}
})
}
export const packageSetting = (tenantId, packageId) => {
return request({
url: '/api/blade-system/tenant/package-setting',
method: 'post',
params: {
tenantId,
packageId
}
})
}

@ -0,0 +1,50 @@
import request from '@/router/axios';
export const getList = (current, size, params) => {
return request({
url: '/api/blade-system/tenant-package/list',
method: 'get',
params: {
...params,
current,
size,
}
})
}
export const getDetail = (id) => {
return request({
url: '/api/blade-system/tenant-package/detail',
method: 'get',
params: {
id
}
})
}
export const remove = (ids) => {
return request({
url: '/api/blade-system/tenant-package/remove',
method: 'post',
params: {
ids,
}
})
}
export const add = (row) => {
return request({
url: '/api/blade-system/tenant-package/submit',
method: 'post',
data: row
})
}
export const update = (row) => {
return request({
url: '/api/blade-system/tenant-package/submit',
method: 'post',
data: row
})
}

@ -118,3 +118,13 @@ export const grant = (userIds, roleIds) => {
} }
}) })
} }
export const unlock = (userIds) => {
return request({
url: '/api/blade-user/unlock',
method: 'post',
params: {
userIds,
}
})
}

@ -6,8 +6,8 @@ export const loginByUsername = (tenantId, deptId, roleId, username, password, ty
method: 'post', method: 'post',
headers: { headers: {
'Tenant-Id': tenantId, 'Tenant-Id': tenantId,
'Dept-Id': deptId, 'Dept-Id': (website.switchMode ? deptId : ''),
'Role-Id': roleId, 'Role-Id': (website.switchMode ? roleId : ''),
'Captcha-Key': key, 'Captcha-Key': key,
'Captcha-Code': code, 'Captcha-Code': code,
}, },
@ -37,11 +37,13 @@ export const loginBySocial = (tenantId, source, code, state) => request({
} }
}) })
export const refreshToken = (refresh_token, tenantId) => request({ export const refreshToken = (refresh_token, tenantId, deptId, roleId) => request({
url: '/api/blade-auth/oauth/token', url: '/api/blade-auth/oauth/token',
method: 'post', method: 'post',
headers: { headers: {
'Tenant-Id': tenantId 'Tenant-Id': tenantId,
'Dept-Id': (website.switchMode ? deptId : ''),
'Role-Id': (website.switchMode ? roleId : '')
}, },
params: { params: {
tenantId, tenantId,

@ -88,6 +88,7 @@ export default {
info: 'info', info: 'info',
logOut: 'logout', logOut: 'logout',
userinfo: 'userinfo', userinfo: 'userinfo',
switchDept : 'switch dept',
dashboard: 'dashboard', dashboard: 'dashboard',
lock: 'lock', lock: 'lock',
bug: 'none bug', bug: 'none bug',

@ -87,6 +87,7 @@ export default {
navbar: { navbar: {
logOut: '退出登录', logOut: '退出登录',
userinfo: '个人信息', userinfo: '个人信息',
switchDept : '部门切换',
dashboard: '首页', dashboard: '首页',
lock: '锁屏', lock: '锁屏',
bug: '没有错误日志', bug: '没有错误日志',

@ -88,11 +88,20 @@
<el-dropdown-item> <el-dropdown-item>
<router-link to="/info/index">{{$t('navbar.userinfo')}}</router-link> <router-link to="/info/index">{{$t('navbar.userinfo')}}</router-link>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="this.website.switchMode" @click.native="switchDept"
>{{$t('navbar.switchDept')}}
</el-dropdown-item>
<el-dropdown-item @click.native="logout" <el-dropdown-item @click.native="logout"
divided>{{$t('navbar.logOut')}} divided>{{$t('navbar.logOut')}}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<el-dialog title="用户信息选择"
append-to-body
:visible.sync="userBox"
width="350px">
<avue-form ref="form" :option="userOption" v-model="userForm" @submit="submitSwitch"/>
</el-dialog>
</div> </div>
</div> </div>
</template> </template>
@ -122,7 +131,55 @@
}, },
name: "top", name: "top",
data() { data() {
return {}; return {
userBox: false,
userForm: {
deptId: '',
roleId: ''
},
userOption: {
labelWidth: 70,
submitBtn: true,
emptyBtn: false,
submitText: '切换',
column: [
{
label: '部门',
prop: 'deptId',
type: 'select',
props: {
label: 'deptName',
value: 'id'
},
dicUrl: '/api/blade-system/dept/select',
span: 24,
display: false,
rules: [{
required: true,
message: "请选择部门",
trigger: "blur"
}],
},
{
label: '角色',
prop: 'roleId',
type: 'select',
props: {
label: 'roleName',
value: 'id'
},
dicUrl: '/api/blade-system/role/select',
span: 24,
display: false,
rules: [{
required: true,
message: "请选择角色",
trigger: "blur"
}],
},
]
}
};
}, },
filters: {}, filters: {},
created() { created() {
@ -162,6 +219,22 @@
setScreen() { setScreen() {
this.$store.commit("SET_FULLSCREN"); this.$store.commit("SET_FULLSCREN");
}, },
switchDept() {
const userId = this.userInfo.user_id;
const deptColumn = this.findObject(this.userOption.column, "deptId");
deptColumn.dicUrl = `/api/blade-system/dept/select?userId=${userId}`;
deptColumn.display = true;
const roleColumn = this.findObject(this.userOption.column, "roleId");
roleColumn.dicUrl = `/api/blade-system/role/select?userId=${userId}`;
roleColumn.display = true;
this.userBox = true;
},
submitSwitch (form, done) {
this.$store.dispatch("refreshToken", form).then(() => {
this.userBox = false;
})
done();
},
logout() { logout() {
this.$confirm(this.$t("logoutTip"), this.$t("tip"), { this.$confirm(this.$t("logoutTip"), this.$t("tip"), {
confirmButtonText: this.$t("submitText"), confirmButtonText: this.$t("submitText"),

@ -233,7 +233,9 @@
this.loginForm.deptId = deptId; this.loginForm.deptId = deptId;
this.loginForm.roleId = roleId; this.loginForm.roleId = roleId;
this.userBox = true; this.userBox = true;
loading.close(); this.$store.dispatch("LogOut").then(() => {
loading.close();
});
return false; return false;
} }
} }

@ -115,10 +115,13 @@ const user = {
}) })
}, },
//刷新token //刷新token
refreshToken({state, commit}) { refreshToken({state, commit}, userInfo) {
window.console.log('handle refresh token') window.console.log('handle refresh token');
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
refreshToken(state.refreshToken, state.tenantId).then(res => { refreshToken(state.refreshToken, state.tenantId,
!validatenull(userInfo) ? userInfo.deptId : state.userInfo.dept_id,
!validatenull(userInfo) ? userInfo.roleId : state.userInfo.role_id
).then(res => {
const data = res.data; const data = res.data;
commit('SET_TOKEN', data.access_token); commit('SET_TOKEN', data.access_token);
commit('SET_REFRESH_TOKEN', data.refresh_token); commit('SET_REFRESH_TOKEN', data.refresh_token);

@ -7,6 +7,7 @@
v-model="form" v-model="form"
:permission="permissionList" :permission="permissionList"
:before-open="beforeOpen" :before-open="beforeOpen"
:before-close="beforeClose"
@row-del="rowDel" @row-del="rowDel"
@row-update="rowUpdate" @row-update="rowUpdate"
@row-save="rowSave" @row-save="rowSave"
@ -571,6 +572,10 @@
} }
done(); done();
}, },
beforeClose(done) {
this.formScope = {};
done();
},
currentChange(currentPage) { currentChange(currentPage) {
this.page.currentPage = currentPage; this.page.currentPage = currentPage;
}, },

@ -278,7 +278,7 @@
values.releaseTimeRange = null; values.releaseTimeRange = null;
} }
this.loading = true; this.loading = true;
getList(page.currentPage, page.pageSize, values).then(res => { getList(page.currentPage, page.pageSize, Object.assign(values, this.query)).then(res => {
const data = res.data.data; const data = res.data.data;
this.page.total = data.total; this.page.total = data.total;
this.data = data.records; this.data = data.records;

@ -26,18 +26,38 @@
plain plain
@click="handleDelete"> @click="handleDelete">
</el-button> </el-button>
<el-button size="small" <el-tooltip class="item" effect="dark" content="给租户配置账号额度、过期时间等授权信息" placement="top">
plain <el-button size="small"
v-if="userInfo.role_name.includes('administrator')" plain
icon="el-icon-setting" v-if="userInfo.role_name.includes('administrator')"
@click="handleSetting">授权配置 icon="el-icon-setting"
</el-button> @click="handleSetting">授权配置
<el-button size="small" </el-button>
plain </el-tooltip>
v-if="userInfo.role_name.includes('administrator')" <el-tooltip class="item" effect="dark" content="给租户配置独立数据源以实现数据库隔离" placement="top">
icon="el-icon-coin" <el-button size="small"
@click="handleDatasource">数据源配置 plain
</el-button> v-if="userInfo.role_name.includes('administrator')"
icon="el-icon-coin"
@click="handleDatasource">数据源配置
</el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="将菜单产品包与租户配置绑定" placement="top">
<el-button size="small"
plain
v-if="userInfo.role_name.includes('administrator')"
icon="el-icon-notebook-1"
@click="handlePackage">产品包配置
</el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="将自定义的菜单集合定制为租户绑定的菜单产品包" placement="top">
<el-button size="small"
plain
v-if="userInfo.role_name.includes('administrator')"
icon="el-icon-notebook-2"
@click="handlePackageSetting">产品包管理
</el-button>
</el-tooltip>
</template> </template>
<template slot-scope="{row}" <template slot-scope="{row}"
slot="accountNumber"> slot="accountNumber">
@ -60,12 +80,27 @@
width="450px"> width="450px">
<avue-form :option="datasourceOption" v-model="datasourceForm" @submit="handleDatasourceSubmit"/> <avue-form :option="datasourceOption" v-model="datasourceForm" @submit="handleDatasourceSubmit"/>
</el-dialog> </el-dialog>
<el-dialog title="租户产品包配置"
append-to-body
:visible.sync="packageBox"
width="450px">
<avue-form ref="formPackage" :option="packageOption" v-model="packageForm" @submit="handlePackageSubmit"/>
</el-dialog>
<el-dialog title="租户产品包管理"
append-to-body
:visible.sync="packageSettingBox"
width="1000px">
<tenant-package></tenant-package>
</el-dialog>
</basic-container> </basic-container>
</template> </template>
<script> <script>
import {getList, getDetail, remove, update, add, setting, datasource} from "@/api/system/tenant"; import {getList, getDetail, remove, update, add, setting, datasource, packageInfo, packageSetting} from "@/api/system/tenant";
import {getDetail as packageDetail} from "@/api/system/tenantpackage";
import {mapGetters} from "vuex"; import {mapGetters} from "vuex";
import {getMenuTree} from "@/api/system/menu";
import {validatenull} from "@/util/validate";
export default { export default {
data() { data() {
@ -76,6 +111,8 @@ export default {
loading: true, loading: true,
box: false, box: false,
datasourceBox: false, datasourceBox: false,
packageBox: false,
packageSettingBox: false,
page: { page: {
pageSize: 10, pageSize: 10,
currentPage: 1, currentPage: 1,
@ -222,9 +259,53 @@ export default {
}] }]
}, },
] ]
} },
packageForm: {},
packageOption: {
column: [
{
label: "产品包",
prop: "packageId",
search: true,
span: 24,
type: "select",
dicUrl: "/api/blade-system/tenant-package/select",
props: {
label: "packageName",
value: "id"
},
rules: [{
required: true,
message: "请选择产品包",
trigger: "blur"
}]
},
{
label: "菜单预览",
prop: "menuId",
span: 24,
type: "tree",
dicData: [],
hide: true,
multiple: true,
props: {
label: "title"
},
},
]
},
}; };
}, },
watch: {
'packageForm.packageId'() {
if (!validatenull(this.packageForm.packageId)) {
packageDetail(this.packageForm.packageId).then(res => {
this.packageForm.menuId = res.data.data.menuId;
this.initData();
});
}
}
},
computed: { computed: {
...mapGetters(["userInfo", "permission"]), ...mapGetters(["userInfo", "permission"]),
permissionList() { permissionList() {
@ -247,6 +328,12 @@ export default {
} }
}, },
methods: { methods: {
initData() {
getMenuTree().then(res => {
const column = this.findObject(this.packageOption.column, "menuId");
column.dicData = res.data.data;
});
},
rowSave(row, done, loading) { rowSave(row, done, loading) {
add(row).then(() => { add(row).then(() => {
this.onLoad(this.page); this.onLoad(this.page);
@ -376,6 +463,34 @@ export default {
}); });
this.datasourceBox = true; this.datasourceBox = true;
}, },
handlePackage() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
if (this.selectionList.length !== 1) {
this.$message.warning("只能选择一条数据");
return;
}
if (this.selectionList.length === 1) {
packageInfo(this.selectionList[0].id).then(res => {
const data = res.data.data;
this.packageForm.packageId = data.id;
this.packageForm.menuId = data.menuId;
});
} else {
this.packageForm.menuId = '';
}
this.packageBox = true;
//
setTimeout(() => {
const form = this.$refs.formPackage;
form.updateDic('packageId');
}, 10);
},
handlePackageSetting() {
this.packageSettingBox = true;
},
handleSubmit(form, done, loading) { handleSubmit(form, done, loading) {
setting(this.ids, form).then(() => { setting(this.ids, form).then(() => {
this.onLoad(this.page); this.onLoad(this.page);
@ -403,6 +518,20 @@ export default {
loading(); loading();
}); });
}, },
handlePackageSubmit(form, done, loading) {
packageSetting(this.tenantId, form.packageId).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "配置成功!"
});
done();
this.packageBox = false;
}, error => {
window.console.log(error);
loading();
});
},
currentChange(currentPage) { currentChange(currentPage) {
this.page.currentPage = currentPage; this.page.currentPage = currentPage;
}, },

@ -0,0 +1,243 @@
<template>
<avue-crud :option="option"
:table-loading="loading"
:data="data"
:page.sync="page"
:permission="permissionList"
:before-open="beforeOpen"
v-model="form"
ref="crud"
@row-update="rowUpdate"
@row-save="rowSave"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad">
<template slot="menuLeft">
<el-button type="danger"
size="small"
icon="el-icon-delete"
plain
@click="handleDelete">
</el-button>
</template>
</avue-crud>
</template>
<script>
import {getList, getDetail, add, update, remove} from "@/api/system/tenantpackage";
import {mapGetters} from "vuex";
import {getMenuTree} from "@/api/system/menu";
export default {
name: "tenantPackage",
data() {
return {
form: {},
query: {},
loading: true,
page: {
pageSize: 10,
currentPage: 1,
total: 0
},
selectionList: [],
option: {
height: 'auto',
calcHeight: 30,
tip: false,
searchShow: true,
searchMenuSpan: 6,
border: true,
index: true,
viewBtn: true,
selection: true,
dialogClickModal: false,
dialogWidth: 600,
column: [
{
label: "产品包名",
prop: "packageName",
search: true,
span: 24,
rules: [{
required: true,
message: "请输入产品包名称",
trigger: "blur"
}]
},
{
label: "菜单列表",
prop: "menuId",
span: 24,
type: "tree",
dicData: [],
hide: true,
multiple: true,
props: {
label: "title"
},
rules: [{
required: true,
message: "请选择菜单",
trigger: "blur"
}]
},
{
label: "备注",
prop: "remark",
span: 24
},
]
},
data: []
};
},
computed: {
...mapGetters(["permission"]),
permissionList() {
return {
addBtn: true,
viewBtn: false,
delBtn: true,
editBtn: true
};
},
ids() {
let ids = [];
this.selectionList.forEach(ele => {
ids.push(ele.id);
});
return ids.join(",");
}
},
methods: {
initData() {
getMenuTree().then(res => {
const column = this.findObject(this.option.column, "menuId");
column.dicData = res.data.data;
});
},
rowSave(row, done, loading) {
row.menuId = row.menuId.join(",");
add(row).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
done();
}, error => {
loading();
window.console.log(error);
});
},
rowUpdate(row, index, done, loading) {
update(row).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
done();
}, error => {
loading();
console.log(error);
});
},
rowDel(row) {
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return remove(row.id);
})
.then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
});
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return remove(this.ids);
})
.then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
this.$refs.crud.toggleSelection();
});
},
beforeOpen(done, type) {
if (["add", "edit"].includes(type)) {
this.initData();
}
if (["edit", "view"].includes(type)) {
getDetail(this.form.id).then(res => {
this.form = res.data.data;
});
}
done();
},
searchReset() {
this.query = {};
this.onLoad(this.page);
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
selectionChange(list) {
this.selectionList = list;
},
selectionClear() {
this.selectionList = [];
this.$refs.crud.toggleSelection();
},
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>
<style>
</style>

@ -59,6 +59,13 @@
icon="el-icon-setting" icon="el-icon-setting"
@click="handlePlatform">平台配置 @click="handlePlatform">平台配置
</el-button> </el-button>
<el-button type="info"
size="small"
plain
v-if="userInfo.role_name.includes('admin')"
icon="el-icon-coordinate"
@click="handleLock">账号解封
</el-button>
<el-button type="success" <el-button type="success"
size="small" size="small"
plain plain
@ -159,17 +166,17 @@
</template> </template>
<script> <script>
import { import {
getList, getList,
getUser, getUser,
getUserPlatform, getUserPlatform,
remove, remove,
update, update,
updatePlatform, updatePlatform,
add, add,
grant, grant,
resetPassword resetPassword, unlock
} from "@/api/system/user"; } from "@/api/system/user";
import {getDeptTree, getDeptLazyTree} from "@/api/system/dept"; import {getDeptTree, getDeptLazyTree} from "@/api/system/dept";
import {getRoleTree} from "@/api/system/role"; import {getRoleTree} from "@/api/system/role";
import {getPostList} from "@/api/system/post"; import {getPostList} from "@/api/system/post";
@ -262,7 +269,7 @@
index: true, index: true,
selection: true, selection: true,
viewBtn: true, viewBtn: true,
//dialogType: 'drawer', dialogType: 'drawer',
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ {
@ -860,6 +867,22 @@
handlePlatform() { handlePlatform() {
this.platformBox = true; this.platformBox = true;
}, },
handleLock() {
this.$confirm("确定将选择账号解封?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return unlock(this.ids);
})
.then(() => {
this.$message({
type: "success",
message: "操作成功!"
});
});
},
handleImport() { handleImport() {
this.excelBox = true; this.excelBox = true;
}, },

@ -73,7 +73,7 @@
index: true, index: true,
selection: true, selection: true,
labelWidth: 120, labelWidth: 120,
menuWidth: 250, menuWidth: 300,
viewBtn: true, viewBtn: true,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [

@ -11,7 +11,7 @@
<p style="text-align: center"> <p style="text-align: center">
<img src="https://img.shields.io/badge/Release-V2.8.2-green.svg" alt="Downloads"/> <img src="https://img.shields.io/badge/Release-V2.8.2-green.svg" alt="Downloads"/>
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status"/> <img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status"/>
<img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR11-blue.svg" alt="Coverage Status"/> <img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR12-blue.svg" alt="Coverage Status"/>
<img src="https://img.shields.io/badge/Spring%20Boot-2.3.12.RELEASE-blue.svg" alt="Downloads"/> <img src="https://img.shields.io/badge/Spring%20Boot-2.3.12.RELEASE-blue.svg" alt="Downloads"/>
<a target="_blank" href="https://bladex.vip"> <a target="_blank" href="https://bladex.vip">
<img src="https://img.shields.io/badge/Saber%20Author-Small%20Chill-ff69b4.svg" alt="Downloads"/> <img src="https://img.shields.io/badge/Saber%20Author-Small%20Chill-ff69b4.svg" alt="Downloads"/>
@ -138,6 +138,34 @@
<el-row> <el-row>
<basic-container> <basic-container>
<el-collapse v-model="logActiveNames" @change="handleChange"> <el-collapse v-model="logActiveNames" @change="handleChange">
<el-collapse-item title="2.9.0.RELEASE发布,新增租户菜单产品包功能" name="25">
<div>1.[升级]SpringCloud Hoxton.SR12</div>
<div>2.[升级]AlibabaCloud 2.2.7.RELEASE</div>
<div>3.[升级]Nacos 2.0.3</div>
<div>4.[升级]Log4j2 2.17.0</div>
<div>5.[升级]Druid 1.2.8</div>
<div>6.[升级]FastJson 1.2.78</div>
<div>7.[升级]Lombok 1.18.22</div>
<div>8.[升级]Avue 2.8.25</div>
<div>9.[升级]阿里云仓库为最新地址</div>
<div>10.[新增]租户菜单产品包功能</div>
<div>11.[新增]部门角色在线切换功能</div>
<div>12.[新增]登录错误次数支持从参数管理读取</div>
<div>13.[新增]管理端手动解锁用户功能</div>
<div>14.[新增]actuator接口增加内网放行外网认证功能</div>
<div>15.[新增]pg数据库int类型条件查询处理示例</div>
<div>16.[新增]Lemon平台代码生成模板</div>
<div>17.[优化]角色删除增加子节点判断</div>
<div>18.[优化]流程条件查询增加租户过滤</div>
<div>19.[优化]流程列表增加名称查询</div>
<div>20.[优化]登录成功时清除错误次数</div>
<div>21.[优化]适配cloud最新版异常处理</div>
<div>22.[优化]数据权限新增成功后清空表单数据</div>
<div>23.[修复]修复用户导入部门数据为null时保存报错的问题</div>
<div>24.[修复]修复刷新token导致多部门id被覆盖的问题</div>
<div>25.[修复]修复登录界面多部门选择弹框出现后直接刷新就能进入主页的问题</div>
<div>26.[修复]修复通知公告分页未带入查询条件的问题</div>
</el-collapse-item>
<el-collapse-item title="2.8.2.RELEASE发布,增强用户登录方案" name="24"> <el-collapse-item title="2.8.2.RELEASE发布,增强用户登录方案" name="24">
<div>1.[升级]SpringBoot 2.3.12</div> <div>1.[升级]SpringBoot 2.3.12</div>
<div>2.[升级]SpringBootAdmin 2.3.1</div> <div>2.[升级]SpringBootAdmin 2.3.1</div>
@ -667,7 +695,7 @@
data() { data() {
return { return {
activeNames: ['1', '2', '3', '5'], activeNames: ['1', '2', '3', '5'],
logActiveNames: ['24'] logActiveNames: ['25']
}; };
}, },
computed: { computed: {

Loading…
Cancel
Save