Преглед на файлове

1、多租户模式调整 2、其他优化

zuohuaijun преди 3 години
родител
ревизия
652be2c295

+ 1 - 1
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -6127,7 +6127,7 @@
         </member>
         <member name="M:Admin.NET.Core.Service.SysTenantService.InitNewTenant(Admin.NET.Core.SysTenant)">
             <summary>
-            新增租户初始化
+            新增租户初始化(Id隔离)
             </summary>
             <param name="newTenant"></param>
         </member>

+ 1 - 0
Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs

@@ -80,6 +80,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
             new SysMenu{ Id=252885263002314, Pid=252885263002310, Title="删除", Permission="sysTenant:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002315, Pid=252885263002310, Title="授权菜单", Permission="sysTenant:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002316, Pid=252885263002310, Title="重置密码", Permission="sysTenant:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002317, Pid=252885263002310, Title="生成库", Permission="sysTenant:createDb", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002320, Pid=252885263002300, Title="参数配置", Path="/platform/config", Name="sysConfig", Component="/system/config/index", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=110 },
             new SysMenu{ Id=252885263002321, Pid=252885263002320, Title="查询", Permission="sysConfig:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },

+ 2 - 2
Admin.NET/Admin.NET.Core/SeedData/SysTenantSeedData.cs

@@ -13,8 +13,8 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
     {
         return new[]
         {
-            new SysTenant{ Id=142307070918780, Name="系统默认", AdminName="Administrator", Host="www.dilon.vip", Email="zuohuaijun@163.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Admin.NET.db", Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysTenant{ Id=142307070918781, Name="测试租户", AdminName="TestAdmin", Host="www.dilon.top", Email="515096995@qq.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Test.db", Remark="测试租户", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysTenant{ Id=142307070918780, Name="系统默认", AdminName="Administrator", Host="www.dilon.vip", Email="zuohuaijun@163.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Admin.NET.db", ConfigId="Dilon", Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysTenant{ Id=142307070918781, Name="测试租户", AdminName="TestAdmin", Host="www.dilon.top", Email="515096995@qq.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Test.db", ConfigId="Test", Remark="测试租户", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 3 - 4
Admin.NET/Admin.NET.Core/Service/Notice/SysNoticeService.cs

@@ -148,11 +148,10 @@ public class SysNoticeService : IDynamicApiController, ITransient
     [HttpGet("/sysNotice/unReadList")]
     public async Task<List<SysNotice>> GetUnReadNoticeList()
     {
-        List<SysNoticeUser> list = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
+        var noticeUserList = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
             .Where(u => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
-            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc)
-            .ToListAsync();
-        return list.Select(t => t.SysNotice).ToList();
+            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc).ToListAsync();
+        return noticeUserList.Select(t => t.SysNotice).ToList();
     }
 
     /// <summary>

+ 8 - 5
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -75,16 +75,19 @@ public class SysTenantService : IDynamicApiController, ITransient
     [HttpPost("/sysTenant/add")]
     public async Task AddTenant(AddTenantInput input)
     {
-        var isExist = await _tenantRep.IsAnyAsync(u => u.Name == input.Name || u.AdminName == input.AdminName);
+        var isExist = await _tenantRep.IsAnyAsync(u => u.Name == input.Name ||
+            (u.AdminName == input.AdminName && input.TenantType == TenantTypeEnum.Id));
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1300);
 
-        var entity = input.Adapt<SysTenant>();
-        await _tenantRep.InsertAsync(entity);
-        await InitNewTenant(entity);
+        var tenant = input.Adapt<SysTenant>();
+        await _tenantRep.InsertAsync(tenant);
+
+        if (tenant.TenantType == TenantTypeEnum.Db) return;
+        await InitNewTenant(tenant);
     }
 
     /// <summary>
-    /// 新增租户初始化
+    /// 新增租户初始化(Id隔离)
     /// </summary>
     /// <param name="newTenant"></param>
     private async Task InitNewTenant(SysTenant newTenant)

+ 3 - 3
Web/src/views/login/component/account.vue

@@ -1,6 +1,6 @@
 <template>
 	<el-form ref="ruleFormRef" :model="ruleForm" size="large" :rules="rules" class="login-content-form">
-		<el-form-item class="login-animation1" v-show="tenantList.length > 0">
+		<el-form-item class="login-animation0" v-show="tenantList.length > 0">
 			<el-select v-model="ruleForm.tenantId" value-key="id" placeholder="租户名称" class="w100">
 				<template #prefix>
 					<el-icon>
@@ -33,7 +33,7 @@
 		</el-form-item>
 		<el-form-item class="login-animation3" prop="captcha" v-show="captchaEnabled">
 			<el-col :span="15">
-				<el-input type="text" maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')" v-model="ruleForm.code" clearable autocomplete="off">
+				<el-input type="text" maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')" v-model="ruleForm.code" clearable autocomplete="off" @keyup.enter="openVerify">
 					<template #prefix>
 						<el-icon>
 							<ele-Position />
@@ -238,7 +238,7 @@ export default defineComponent({
 .login-content-form {
 	margin-top: 20px;
 
-	@for $i from 1 through 4 {
+	@for $i from 0 through 4 {
 		.login-animation#{$i} {
 			opacity: 0;
 			animation-name: error-num;

+ 1 - 1
Web/src/views/login/component/mobile.vue

@@ -1,6 +1,6 @@
 <template>
 	<el-form size="large" class="login-content-form">
-		<el-form-item class="login-animation4">
+		<el-form-item class="login-animation1">
 			<el-input type="text" :placeholder="$t('message.mobile.placeholder1')" v-model="ruleForm.userName" clearable autocomplete="off">
 				<template #prefix>
 					<i class="iconfont icon-dianhua el-input__icon"></i>

+ 2 - 2
Web/src/views/login/index.vue

@@ -131,7 +131,7 @@ export default defineComponent({
 
 	.login-content {
 		width: 500px;
-		height: 500px;
+		height: 550px;
 		padding: 20px;
 		position: absolute;
 		right: 10%;
@@ -153,7 +153,7 @@ export default defineComponent({
 				font-size: 32px;
 				text-align: center;
 				//letter-spacing: 4px;
-				margin: 5px 0 30px;
+				margin: 5px 0 20px;
 				white-space: nowrap;
 				z-index: 5;
 				position: relative;

+ 1 - 1
Web/src/views/system/menu/index.vue

@@ -109,7 +109,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddMenu = () => {
 			state.editMenuTitle = '添加菜单';
-			editMenuRef.value.openDialog({});
+			editMenuRef.value.openDialog({ type: 2 });
 		};
 		// 打开编辑页面
 		const openEditMenu = (row: any) => {

+ 1 - 1
Web/src/views/system/org/index.vue

@@ -110,7 +110,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddOrg = () => {
 			state.editOrgTitle = '添加机构';
-			editOrgRef.value.openDialog({});
+			editOrgRef.value.openDialog({ status: 1 });
 		};
 		// 打开编辑页面
 		const openEditOrg = (row: any) => {

+ 1 - 1
Web/src/views/system/pos/index.vue

@@ -93,7 +93,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddPos = () => {
 			state.editPosTitle = '添加职位';
-			editPosRef.value.openDialog({});
+			editPosRef.value.openDialog({ status: 1 });
 		};
 		// 打开编辑页面
 		const openEditPos = (row: any) => {

+ 24 - 16
Web/src/views/system/tenant/component/editTenant.vue

@@ -3,6 +3,14 @@
 		<el-dialog v-model="isShowDialog" :title="title" draggable width="769px">
 			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="100px">
 				<el-row :gutter="35">
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="租户类型" :rules="[{ required: true, message: '租户类型不能为空', trigger: 'blur' }]">
+							<el-radio-group v-model="ruleForm.tenantType">
+								<el-radio :label="0">ID隔离</el-radio>
+								<el-radio :label="1">库隔离</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="租户名称" prop="name" :rules="[{ required: true, message: '租户名称不能为空', trigger: 'blur' }]">
 							<el-input v-model="ruleForm.name" placeholder="租户名称" clearable />
@@ -10,7 +18,7 @@
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="管理员" prop="adminName" :rules="[{ required: true, message: '管理员不能为空', trigger: 'blur' }]">
-							<el-input v-model="ruleForm.adminName" placeholder="管理员" clearable />
+							<el-input v-model="ruleForm.adminName" placeholder="管理员" clearable :disabled="ruleForm.tenantType == 1" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@@ -18,11 +26,6 @@
 							<el-input v-model="ruleForm.phone" placeholder="电话" clearable />
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="主机">
-							<el-input v-model="ruleForm.host" placeholder="主机" clearable />
-						</el-form-item>
-					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="邮箱">
 							<el-input v-model="ruleForm.email" placeholder="邮箱" clearable />
@@ -33,17 +36,14 @@
 							<el-input-number v-model="ruleForm.order" placeholder="排序" class="w100" />
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="租户类型" :rules="[{ required: true, message: '租户类型不能为空', trigger: 'blur' }]">
-							<el-radio-group v-model="ruleForm.tenantType">
-								<el-radio :label="0">ID隔离</el-radio>
-								<el-radio :label="1">库隔离</el-radio>
-							</el-radio-group>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="主机">
+							<el-input v-model="ruleForm.host" placeholder="主机" clearable />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="数据库类型">
-							<el-select v-model="ruleForm.dbType" placeholder="数据库类型" clearable style="width: 100%">
+							<el-select v-model="ruleForm.dbType" placeholder="数据库类型" clearable style="width: 100%" :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined">
 								<el-option label="MySql" :value="0" />
 								<el-option label="SqlServer" :value="1" />
 								<el-option label="Sqlite" :value="2" />
@@ -63,9 +63,14 @@
 							</el-select>
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="4" :md="24" :lg="24" :xl="24" class="mb20">
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="数据库标识">
+							<el-input v-model="ruleForm.configId" placeholder="数据库标识" clearable :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
 						<el-form-item label="连接字符串">
-							<el-input v-model="ruleForm.connection" placeholder="连接字符串" clearable type="textarea" />
+							<el-input v-model="ruleForm.connection" placeholder="连接字符串" clearable type="textarea" :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
@@ -86,7 +91,7 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, getCurrentInstance, ref } from 'vue';
+import { reactive, toRefs, defineComponent, getCurrentInstance, ref, watch } from 'vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysTenantApi } from '/@/api-services/api';
@@ -108,6 +113,9 @@ export default defineComponent({
 			isShowDialog: false,
 			ruleForm: {} as UpdateTenantInput,
 		});
+		watch(state, () => {
+			if (state.ruleForm.tenantType == 1) state.ruleForm.adminName = 'Administrator';
+		});
 		// 打开弹窗
 		const openDialog = (row: any) => {
 			state.ruleForm = row;

+ 6 - 4
Web/src/views/system/tenant/index.vue

@@ -22,7 +22,7 @@
 				<el-table-column prop="name" label="租户名称" show-overflow-tooltip />
 				<el-table-column prop="adminName" label="管理员" show-overflow-tooltip />
 				<el-table-column prop="phone" label="电话" show-overflow-tooltip />
-				<el-table-column prop="host" label="主机" show-overflow-tooltip />
+				<!-- <el-table-column prop="host" label="主机" show-overflow-tooltip /> -->
 				<el-table-column prop="email" label="邮箱" show-overflow-tooltip />
 				<el-table-column prop="tenantType" label="租户类型" align="center" show-overflow-tooltip>
 					<template #default="scope">
@@ -50,12 +50,14 @@
 						<el-tag v-else-if="scope.row.dbType === 900"> Custom </el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column prop="connection" label="数据库连接" show-overflow-tooltip />
+				<el-table-column prop="configId" label="数据库标识" show-overflow-tooltip />
+				<el-table-column prop="connection" label="数据库连接" width="300" show-overflow-tooltip />
 				<el-table-column prop="order" label="排序" width="70" align="center" show-overflow-tooltip />
 				<el-table-column prop="createTime" label="修改时间" align="center" show-overflow-tooltip />
 				<el-table-column prop="remark" label="备注" show-overflow-tooltip />
-				<el-table-column label="操作" width="110" fixed="right" align="center" show-overflow-tooltip>
+				<el-table-column label="操作" width="180" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
+						<el-button icon="ele-Coin" size="small" text type="danger" @click="openEditTenant(scope.row)" v-auth="'sysTenant:createDb'" :disabled="scope.row.tenantType == 0"> 生成库 </el-button>
 						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditTenant(scope.row)" v-auth="'sysTenant:update'"> 编辑 </el-button>
 						<el-dropdown>
 							<el-button icon="ele-MoreFilled" size="small" text type="primary" style="padding-left: 12px" />
@@ -145,7 +147,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddTenant = () => {
 			state.editTenantTitle = '添加租户';
-			editTenantRef.value.openDialog({});
+			editTenantRef.value.openDialog({ tenantType: 0 });
 		};
 		// 打开编辑页面
 		const openEditTenant = (row: any) => {

+ 4 - 2
Web/src/views/system/user/component/userCenter.vue

@@ -99,7 +99,7 @@
 									<el-input v-model="ruleFormPassword.passwordNew" type="password" autocomplete="off" />
 								</el-form-item>
 								<el-form-item label="确认密码" prop="passwordNew2" :rules="[{ validator: validatePassword, required: true, trigger: 'blur' }]">
-									<el-input type="password" />
+									<el-input v-model="passwordNew2" type="password" autocomplete="off" />
 								</el-form-item>
 								<el-form-item>
 									<el-button icon="ele-Refresh" @click="resetPassword" size="default">重 置</el-button>
@@ -168,6 +168,7 @@ export default defineComponent({
 				},
 			},
 			signFileList: [] as any,
+			passwordNew2: '',
 		});
 		onMounted(async () => {
 			state.loading = true;
@@ -233,7 +234,7 @@ export default defineComponent({
 		};
 		// 密码验证
 		const validatePassword = (_rule: any, value: any, callback: any) => {
-			if (value != state.ruleFormPassword.passwordNew) {
+			if (state.passwordNew2 != state.ruleFormPassword.passwordNew) {
 				callback(new Error('两次密码不一致!'));
 			} else {
 				callback();
@@ -243,6 +244,7 @@ export default defineComponent({
 		const resetPassword = () => {
 			state.ruleFormPassword.passwordOld = '';
 			state.ruleFormPassword.passwordNew = '';
+			state.passwordNew2 = '';
 		};
 		// 密码提交
 		const submitPassword = () => {