😎1、恢复角色批量设置用户 2、调整首页等待条样式 3、增加获取指定机构子树API 4、升级依赖

This commit is contained in:
zuohuaijun 2025-03-07 23:59:21 +08:00
parent 9f18a5e7e5
commit df50d8de1c
6 changed files with 156 additions and 27 deletions

View File

@ -94,6 +94,19 @@ public class SysOrgService : IDynamicApiController, ITransient
}
}
/// <summary>
/// 获取指定层级机构树 🔖
/// </summary>
/// <param name="pid"></param>
/// <param name="level"></param>
/// <returns></returns>
[DisplayName("获取指定层级机构树")]
public async Task<List<SysOrg>> GetChildTree(long pid, int level)
{
var iSugarQueryable = _sysOrgRep.AsQueryable().OrderBy(u => new { u.OrderNo });
return await iSugarQueryable.Where(u => u.Level < level).ToTreeAsync(u => u.Children, u => u.Pid, pid);
}
/// <summary>
/// 增加机构 🔖
/// </summary>

View File

@ -24,7 +24,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.2.0" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.13.0" />
<PackageReference Include="Rezero.Api" Version="1.7.14" />
</ItemGroup>

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" media="print" href="/print-lock.css" />
<link rel="icon" id="favicon" href="data:;base64,=" />
<title>Loading...</title>
<title>loading</title>
<style>
.loading-wrapper {
position: fixed;
@ -25,23 +25,29 @@
.loading-wrapper.hide {
display: none;
}
.loader {
width: 120px;
height: 20px;
border-radius: 20px;
background:
repeating-linear-gradient(135deg, #010101 0 10px, #f9d62b 0 20px) 0/0% no-repeat,
repeating-linear-gradient(135deg, #ddd 0 10px, #eee 0 20px) 0/100%;
animation: l3 2s infinite;
width: 15px;
aspect-ratio: 1;
background: #000;
border-radius: 50%;
animation: l6 1s infinite linear alternate;
}
.loading-text {
margin-top: 20px;
font-size: 16px;
color: #666;
}
@keyframes l3 {
@keyframes l6 {
0% {
box-shadow:
15px 0,
-25px 0;
}
50% {
box-shadow:
15px 0,
-15px 0;
}
100% {
background-size: 100%;
box-shadow:
25px 0,
-15px 0;
}
}
</style>
@ -50,7 +56,6 @@
<body>
<div class="loading-wrapper">
<div class="loader"></div>
<div class="loading-text">Loading......</div>
</div>
<div id="app"></div>
<script src="/config.js"></script>

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2025.03.05",
"lastBuildTime": "2025.03.07",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@ -29,14 +29,14 @@
"@wangeditor/editor-for-vue": "^5.1.12",
"animate.css": "^4.1.1",
"async-validator": "^4.2.5",
"axios": "^1.8.1",
"axios": "^1.8.2",
"countup.js": "^2.8.0",
"cropperjs": "^1.6.2",
"crypto-js": "^4.2.0",
"echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"echarts-wordcloud": "^2.1.0",
"element-plus": "^2.9.5",
"element-plus": "^2.9.6",
"exceljs": "^4.4.0",
"ezuikit-js": "^8.1.7",
"gcoord": "^1.0.7",
@ -61,7 +61,7 @@
"screenfull": "^6.0.2",
"sm-crypto-v2": "^1.9.3",
"sortablejs": "^1.15.6",
"splitpanes": "^3.1.8",
"splitpanes": "^4.0.0",
"vcrontab-3": "^3.3.22",
"vform3-builds": "^3.0.10",
"vue": "^3.5.13",
@ -69,25 +69,25 @@
"vue-demi": "0.14.10",
"vue-draggable-plus": "^0.6.0",
"vue-grid-layout": "3.0.0-beta1",
"vue-i18n": "^11.1.1",
"vue-i18n": "^11.1.2",
"vue-json-pretty": "^2.4.0",
"vue-plugin-hiprint": "^0.0.59-beta2",
"vue-router": "^4.5.0",
"vue-signature-pad": "^3.0.2",
"vue3-flag-icons": "^0.0.3",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.4.2",
"vxe-pc-ui": "^4.4.7",
"vxe-table": "^4.10.0",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.7",
"xe-utils": "^3.7.2",
"xe-utils": "^3.7.4",
"xlsx-js-style": "^1.2.0"
},
"devDependencies": {
"@iconify/vue": "^4.3.0",
"@plugin-web-update-notification/vite": "^2.0.0",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.17.22",
"@types/node": "^20.17.23",
"@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.26.0",
@ -105,7 +105,7 @@
"sass": "^1.85.1",
"terser": "^5.39.0",
"typescript": "^5.8.2",
"vite": "^6.2.0",
"vite": "^6.2.1",
"vite-plugin-cdn-import": "^1.0.1",
"vite-plugin-compression2": "^1.3.3",
"vite-plugin-vue-setup-extend": "^0.4.0",

View File

@ -76,6 +76,61 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {number} pid
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysOrgChildTreePidLevelGet: async (pid: number, level: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'pid' is not null or undefined
if (pid === null || pid === undefined) {
throw new RequiredError('pid','Required parameter pid was null or undefined when calling apiSysOrgChildTreePidLevelGet.');
}
// verify required parameter 'level' is not null or undefined
if (level === null || level === undefined) {
throw new RequiredError('level','Required parameter level was null or undefined when calling apiSysOrgChildTreePidLevelGet.');
}
const localVarPath = `/api/sysOrg/childTree/{pid}/{level}`
.replace(`{${"pid"}}`, encodeURIComponent(String(pid)))
.replace(`{${"level"}}`, encodeURIComponent(String(level)));
// 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: 'GET', ...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;
}
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};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -262,6 +317,21 @@ export const SysOrgApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {number} pid
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysOrgChildTreePidLevelGet(pid: number, level: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSysOrg>>> {
const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).apiSysOrgChildTreePidLevelGet(pid, level, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -326,6 +396,17 @@ export const SysOrgApiFactory = function (configuration?: Configuration, basePat
async apiSysOrgAddPost(body?: AddOrgInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultInt64>> {
return SysOrgApiFp(configuration).apiSysOrgAddPost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {number} pid
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysOrgChildTreePidLevelGet(pid: number, level: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSysOrg>> {
return SysOrgApiFp(configuration).apiSysOrgChildTreePidLevelGet(pid, level, options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -380,6 +461,18 @@ export class SysOrgApi extends BaseAPI {
public async apiSysOrgAddPost(body?: AddOrgInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultInt64>> {
return SysOrgApiFp(this.configuration).apiSysOrgAddPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {number} pid
* @param {number} level
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysOrgApi
*/
public async apiSysOrgChildTreePidLevelGet(pid: number, level: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSysOrg>> {
return SysOrgApiFp(this.configuration).apiSysOrgChildTreePidLevelGet(pid, level, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖

View File

@ -62,6 +62,7 @@
<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-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>
</template>
</vxe-grid>
</el-card>
@ -71,6 +72,7 @@
<GrantTable ref="grantTableRef" />
<GrantData ref="grantDataRef" @handleQuery="handleQuery" />
<GrantApi ref="grantApiRef" />
<GrantUser v-model:visible="state.grantUserVisible" @change="closeGrantUser" />
</div>
</template>
@ -87,6 +89,7 @@ import GrantMenu from '/@/views/system/role/component/grantMenu.vue';
import GrantTable from '/@/views/system/role/component/grantTable.vue';
import GrantData from '/@/views/system/role/component/grantData.vue';
import GrantApi from '/@/views/system/role/component/grantApi.vue';
import GrantUser from '/@/components/selector/userSelectorDialog.vue';
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import { getAPI } from '/@/utils/axios-utils';
@ -110,6 +113,8 @@ const state = reactive({
},
visible: false,
title: '',
grantUserVisible: false, //
roleRow: {} as any, //
});
const i18n = useI18n();
@ -131,7 +136,7 @@ const options = useVxeTable<PageRoleOutput>(
{ 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: '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: 440, showOverflow: true, slots: { default: 'row_buttons' } },
{ field: 'buttons', title: i18n.t('message.list.operation'), fixed: 'right', width: 520, showOverflow: true, slots: { default: 'row_buttons' } },
],
},
// vxeGrid()vxe-table
@ -232,4 +237,17 @@ const openGrantData = (row: any) => {
const openGrantApi = (row: any) => {
grantApiRef.value?.openDrawer(row);
};
//
const openGrantUser = (row: any) => {
state.roleRow = row;
state.grantUserVisible = true;
};
//
const closeGrantUser = (data: any) => {
var userIds = data.map((u: any) => u.id);
getAPI(SysRoleApi).apiSysRoleGrantUserPost({ id: state.roleRow.id, userIdList: userIds });
state.grantUserVisible = false;
};
</script>