feat: 角色增加复制功能

This commit is contained in:
写意 2025-04-06 07:56:48 +08:00
parent de9bde949d
commit 6cbc2ddc14
11 changed files with 266 additions and 3 deletions

View File

@ -42,4 +42,8 @@ public class UpdateRoleInput : AddRoleInput
public class DeleteRoleInput : BaseIdInput public class DeleteRoleInput : BaseIdInput
{ {
}
public class CopyRoleInput : BaseIdInput
{
} }

View File

@ -59,4 +59,21 @@ public class SysRoleApiService : ITransient
{ {
await _sysRoleApiRep.DeleteAsync(u => u.RoleId == roleId); await _sysRoleApiRep.DeleteAsync(u => u.RoleId == roleId);
} }
/// <summary>
/// 根据角色Id复制角色接口
/// </summary>
/// <param name="roleId"></param>
/// <param name="newRoleId"></param>
/// <returns></returns>
public async Task CopyRoleApiByRoleId(long roleId, long newRoleId)
{
var roleApiList = await _sysRoleApiRep.GetListAsync(u => u.RoleId == roleId);
roleApiList.ForEach(u =>
{
u.Id = 0;
u.RoleId = newRoleId;
});
await _sysRoleApiRep.InsertRangeAsync(roleApiList);
}
} }

View File

@ -65,4 +65,21 @@ public class SysRoleMenuService : ITransient
{ {
await _sysRoleMenuRep.DeleteAsync(u => u.RoleId == roleId); await _sysRoleMenuRep.DeleteAsync(u => u.RoleId == roleId);
} }
/// <summary>
/// 根据角色Id复制角色菜单
/// </summary>
/// <param name="roleId"></param>
/// <param name="newRoleId"></param>
/// <returns></returns>
public async Task CopyRoleMenuByRoleId(long roleId, long newRoleId)
{
var roleMenuList = await _sysRoleMenuRep.GetListAsync(u => u.RoleId == roleId);
roleMenuList.ForEach(u =>
{
u.Id = 0;
u.RoleId = newRoleId;
});
await _sysRoleMenuRep.InsertRangeAsync(roleMenuList);
}
} }

View File

@ -72,4 +72,21 @@ public class SysRoleOrgService : ITransient
{ {
await _sysRoleOrgRep.DeleteAsync(u => u.RoleId == roleId); await _sysRoleOrgRep.DeleteAsync(u => u.RoleId == roleId);
} }
/// <summary>
/// 根据角色Id复制角色机构
/// </summary>
/// <param name="roleId"></param>
/// <param name="newRoleId"></param>
/// <returns></returns>
public async Task CopyRoleOrgByRoleId(long roleId, long newRoleId)
{
var roleOrgList = await _sysRoleOrgRep.GetListAsync(u => u.RoleId == roleId);
roleOrgList.ForEach(u =>
{
u.Id = 0;
u.RoleId = newRoleId;
});
await _sysRoleOrgRep.InsertRangeAsync(roleOrgList);
}
} }

View File

@ -159,6 +159,48 @@ public class SysRoleService : IDynamicApiController, ITransient
// 级联删除角色接口数据 // 级联删除角色接口数据
await _sysRoleApiService.DeleteRoleApiByRoleId(sysRole.Id); await _sysRoleApiService.DeleteRoleApiByRoleId(sysRole.Id);
// 级联删除角色表格数据
await _sysRoleTableService.DeleteRolTableByRoleId(sysRole.Id);
}
/// <summary>
/// 复制角色 🔖
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[UnitOfWork]
[ApiDescriptionSettings(Name = "Copy"), HttpPost]
[DisplayName("复制角色")]
public async Task CopyRole(CopyRoleInput input)
{
// 查找角色
var sysRole = await _sysRoleRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
// 新增角色
var newRoleId = YitIdHelper.NextId();
sysRole.Id = newRoleId;
sysRole.Code = $"{sysRole.Code} - copy";
sysRole.Name = $"{sysRole.Name} - copy";
sysRole.CreateTime = DateTime.Now;
sysRole.CreateUserId = null;
sysRole.CreateUserName = null;
sysRole.UpdateTime = null;
sysRole.UpdateUserId = null;
sysRole.UpdateUserName = null;
await _sysRoleRep.InsertAsync(sysRole);
// 复制角色数据范围
await _sysRoleOrgService.CopyRoleOrgByRoleId(input.Id, newRoleId);
// 复制角色菜单数据
await _sysRoleMenuService.CopyRoleMenuByRoleId(input.Id, newRoleId);
// 复制角色接口数据
await _sysRoleApiService.CopyRoleApiByRoleId(input.Id, newRoleId);
// 复制角色表格数据
await _sysRoleTableService.CopyRolTableByRoleId(input.Id, newRoleId);
} }
/// <summary> /// <summary>

View File

@ -59,6 +59,7 @@ public class SysRoleTableService : ITransient
sysRoleTableList.Add(sysRoleTable); sysRoleTableList.Add(sysRoleTable);
} }
} }
await _sysRoleTableRep.InsertRangeAsync(sysRoleTableList); await _sysRoleTableRep.InsertRangeAsync(sysRoleTableList);
} }
@ -139,10 +140,12 @@ public class SysRoleTableService : ITransient
}; };
columnList.Add(column); columnList.Add(column);
} }
table.Columns = columnList; table.Columns = columnList;
roleTableList.Add(table); roleTableList.Add(table);
} }
} }
return roleTableList; return roleTableList;
} }
@ -155,4 +158,31 @@ public class SysRoleTableService : ITransient
{ {
return string.IsNullOrWhiteSpace(propertyName) ? null : propertyName[..1].ToLower() + propertyName[1..]; return string.IsNullOrWhiteSpace(propertyName) ? null : propertyName[..1].ToLower() + propertyName[1..];
} }
/// <summary>
/// 根据角色Id删除角色表格
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public async Task DeleteRolTableByRoleId(long roleId)
{
await _sysRoleTableRep.DeleteAsync(u => u.RoleId == roleId);
}
/// <summary>
/// 根据角色Id复制角色表格
/// </summary>
/// <param name="roleId"></param>
/// <param name="newRoleId"></param>
/// <returns></returns>
public async Task CopyRolTableByRoleId(long roleId, long newRoleId)
{
var roleTableList = await _sysRoleTableRep.GetListAsync(u => u.RoleId == roleId);
roleTableList.ForEach(u =>
{
u.Id = 0;
u.RoleId = newRoleId;
});
await _sysRoleTableRep.InsertRangeAsync(roleTableList);
}
} }

View File

@ -25,6 +25,7 @@ import { AdminNETResultListRoleOutput } from '../models';
import { AdminNETResultListRoleTableOutput } from '../models'; import { AdminNETResultListRoleTableOutput } from '../models';
import { AdminNETResultListString } from '../models'; import { AdminNETResultListString } from '../models';
import { AdminNETResultSqlSugarPagedListPageRoleOutput } from '../models'; import { AdminNETResultSqlSugarPagedListPageRoleOutput } from '../models';
import { CopyRoleInput } from '../models';
import { DeleteRoleInput } from '../models'; import { DeleteRoleInput } from '../models';
import { PageRoleInput } from '../models'; import { PageRoleInput } from '../models';
import { RoleApiInput } from '../models'; import { RoleApiInput } from '../models';
@ -132,6 +133,54 @@ export const SysRoleApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions, options: localVarRequestOptions,
}; };
}, },
/**
*
* @summary 🔖
* @param {CopyRoleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysRoleCopyPost: async (body?: CopyRoleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysRole/copy`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/** /**
* *
* @summary 🔖 * @summary 🔖
@ -949,6 +998,20 @@ export const SysRoleApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs); return axios.request(axiosRequestArgs);
}; };
}, },
/**
*
* @summary 🔖
* @param {CopyRoleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysRoleCopyPost(body?: CopyRoleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
const localVarAxiosArgs = await SysRoleApiAxiosParamCreator(configuration).apiSysRoleCopyPost(body, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/** /**
* *
* @summary 🔖 * @summary 🔖
@ -1201,6 +1264,16 @@ export const SysRoleApiFactory = function (configuration?: Configuration, basePa
async apiSysRoleAllTableColumnListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListRoleTableOutput>> { async apiSysRoleAllTableColumnListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListRoleTableOutput>> {
return SysRoleApiFp(configuration).apiSysRoleAllTableColumnListGet(options).then((request) => request(axios, basePath)); return SysRoleApiFp(configuration).apiSysRoleAllTableColumnListGet(options).then((request) => request(axios, basePath));
}, },
/**
*
* @summary 🔖
* @param {CopyRoleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysRoleCopyPost(body?: CopyRoleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysRoleApiFp(configuration).apiSysRoleCopyPost(body, options).then((request) => request(axios, basePath));
},
/** /**
* *
* @summary 🔖 * @summary 🔖
@ -1392,6 +1465,17 @@ export class SysRoleApi extends BaseAPI {
public async apiSysRoleAllTableColumnListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListRoleTableOutput>> { public async apiSysRoleAllTableColumnListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListRoleTableOutput>> {
return SysRoleApiFp(this.configuration).apiSysRoleAllTableColumnListGet(options).then((request) => request(this.axios, this.basePath)); return SysRoleApiFp(this.configuration).apiSysRoleAllTableColumnListGet(options).then((request) => request(this.axios, this.basePath));
} }
/**
*
* @summary 🔖
* @param {CopyRoleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysRoleApi
*/
public async apiSysRoleCopyPost(body?: CopyRoleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysRoleApiFp(this.configuration).apiSysRoleCopyPost(body, options).then((request) => request(this.axios, this.basePath));
}
/** /**
* *
* @summary 🔖 * @summary 🔖

View File

@ -0,0 +1,30 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
*
*
* @export
* @interface CopyRoleInput
*/
export interface CopyRoleInput {
/**
* Id
*
* @type {number}
* @memberof CopyRoleInput
*/
id: number;
}

View File

@ -162,6 +162,7 @@ export * from './column-relation';
export * from './compare-info'; export * from './compare-info';
export * from './const-output'; export * from './const-output';
export * from './constructor-info'; export * from './constructor-info';
export * from './copy-role-input';
export * from './create-entity-input'; export * from './create-entity-input';
export * from './create-pay-transaction-native-output'; export * from './create-pay-transaction-native-output';
export * from './create-pay-transaction-output'; export * from './create-pay-transaction-output';

View File

@ -349,6 +349,9 @@ export default {
currentProgress:"当前进度", currentProgress:"当前进度",
welcomein:'欢迎使用 Admin.NET 通用权限开发框架', welcomein:'欢迎使用 Admin.NET 通用权限开发框架',
emailRequired:"邮箱不能为空", emailRequired:"邮箱不能为空",
emailNotMatch:"邮箱与账号必须要相同" emailNotMatch:"邮箱与账号必须要相同",
confirmCopyRole: '确定复制角色:【{roleName}】?',
authAccount: '授权账号',
successCopy: '复制成功',
} }
}; };

View File

@ -58,11 +58,14 @@
<el-tooltip :content="$t('message.list.delete')" placement="top"> <el-tooltip :content="$t('message.list.delete')" placement="top">
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysRole/delete'"></el-button> <el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysRole/delete'"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip :content="$t('message.list.copy')" placement="top">
<el-button icon="ele-CopyDocument" text type="primary" @click="handleCopy(row)" v-auth="'sysRole/add'"></el-button>
</el-tooltip>
<el-button icon="ele-Menu" size="small" text type="primary" @click="openGrantMenu(row)" v-auth="'sysRole/grantMenu'">{{ $t('message.list.authMenu') }}</el-button> <el-button icon="ele-Menu" size="small" text type="primary" @click="openGrantMenu(row)" v-auth="'sysRole/grantMenu'">{{ $t('message.list.authMenu') }}</el-button>
<el-button icon="ele-OfficeBuilding" size="small" text type="primary" @click="openGrantData(row)" v-auth="'sysRole/grantDataScope'">{{ $t('message.list.authData') }}</el-button> <el-button icon="ele-OfficeBuilding" size="small" text type="primary" @click="openGrantData(row)" v-auth="'sysRole/grantDataScope'">{{ $t('message.list.authData') }}</el-button>
<el-button icon="ele-Grid" size="small" text type="primary" @click="openGrantTable(row)" v-auth="'sysRole/grantTable'">{{ $t('message.list.fieldBlacklist') }}</el-button> <el-button icon="ele-Grid" size="small" text type="primary" @click="openGrantTable(row)" v-auth="'sysRole/grantTable'">{{ $t('message.list.fieldBlacklist') }}</el-button>
<el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)" v-auth="'sysRole/grantApi'">{{ $t('message.list.apiBlacklist') }}</el-button> <el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)" v-auth="'sysRole/grantApi'">{{ $t('message.list.apiBlacklist') }}</el-button>
<el-button icon="ele-User" size="small" text type="primary" @click="openGrantUser(row)" v-auth="'sysRole/grantApi'"> 授权账号 </el-button> <el-button icon="ele-User" size="small" text type="primary" @click="openGrantUser(row)" v-auth="'sysRole/grantApi'">{{ $t('message.list.authAccount') }}</el-button>
</template> </template>
</vxe-grid> </vxe-grid>
</el-card> </el-card>
@ -136,7 +139,7 @@ const options = useVxeTable<PageRoleOutput>(
{ field: 'orderNo', title: i18n.t('message.list.orderNo'), width: 80, showOverflow: 'tooltip' }, { field: 'orderNo', title: i18n.t('message.list.orderNo'), width: 80, showOverflow: 'tooltip' },
{ field: 'status', title: i18n.t('message.list.status'), width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } }, { field: 'status', title: i18n.t('message.list.status'), width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
{ field: 'record', title: i18n.t('message.list.record'), width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } }, { field: 'record', title: i18n.t('message.list.record'), width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
{ field: 'buttons', title: i18n.t('message.list.operation'), fixed: 'right', width: 520, showOverflow: true, slots: { default: 'row_buttons' } }, { field: 'buttons', title: i18n.t('message.list.operation'), fixed: 'right', width: 540, showOverflow: true, slots: { default: 'row_buttons' } },
], ],
}, },
// vxeGrid()vxe-table // vxeGrid()vxe-table
@ -204,6 +207,21 @@ const handleDelete = (row: any) => {
.catch(() => {}); .catch(() => {});
}; };
//
const handleCopy = (row: any) => {
ElMessageBox.confirm(i18n.t('message.list.confirmCopyRole', { roleName: row.name }), i18n.t('message.list.hint'), {
confirmButtonText: i18n.t('message.list.confirmButtonText'),
cancelButtonText: i18n.t('message.list.cancelButtonText'),
type: 'warning',
})
.then(async () => {
await getAPI(SysRoleApi).apiSysRoleCopyPost({ id: row.id });
await handleQuery();
ElMessage.success(i18n.t('message.list.successCopy'));
})
.catch(() => {});
};
// //
const gridEvents: VxeGridListeners<PageRoleOutput> = { const gridEvents: VxeGridListeners<PageRoleOutput> = {
// pager-config // pager-config