😎1、优化登录是获取系统配置 2、优化前端表单修改记录组件 3、优化前端表单效验 4、优化组织结构新增和更新逻辑

This commit is contained in:
zuohuaijun 2025-10-10 14:32:17 +08:00
parent 53a68874dc
commit 085c8c8dba
6 changed files with 51 additions and 19 deletions

View File

@ -47,7 +47,7 @@
<PackageReference Include="NewLife.Redis" Version="6.3.2025.1001" /> <PackageReference Include="NewLife.Redis" Version="6.3.2025.1001" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" /> <PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" />
<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" /> <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
<PackageReference Include="QRCoder" Version="1.6.0" /> <PackageReference Include="QRCoder" Version="1.7.0" />
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" /> <PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" /> <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.12.0" /> <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.12.0" />

View File

@ -119,7 +119,7 @@ public class SysOrgService : IDynamicApiController, ITransient
if (!_userManager.SuperAdmin && input.Pid == 0) if (!_userManager.SuperAdmin && input.Pid == 0)
throw Oops.Oh(ErrorCodeEnum.D2009); throw Oops.Oh(ErrorCodeEnum.D2009);
if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code)) if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name || u.Code == input.Code))
throw Oops.Oh(ErrorCodeEnum.D2002); throw Oops.Oh(ErrorCodeEnum.D2002);
if (!_userManager.SuperAdmin && input.Pid != 0) if (!_userManager.SuperAdmin && input.Pid != 0)
@ -189,7 +189,7 @@ public class SysOrgService : IDynamicApiController, ITransient
if (input.Id == input.Pid) if (input.Id == input.Pid)
throw Oops.Oh(ErrorCodeEnum.D2001); throw Oops.Oh(ErrorCodeEnum.D2001);
if (await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id)) if (await _sysOrgRep.IsAnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id))
throw Oops.Oh(ErrorCodeEnum.D2002); throw Oops.Oh(ErrorCodeEnum.D2002);
// 父Id不能为自己的子节点 // 父Id不能为自己的子节点

View File

@ -2,7 +2,7 @@
"name": "admin.net.pro", "name": "admin.net.pro",
"type": "module", "type": "module",
"version": "2.4.33", "version": "2.4.33",
"lastBuildTime": "2025.10.08", "lastBuildTime": "2025.10.10",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架", "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun", "author": "zuohuaijun",
"license": "MIT", "license": "MIT",
@ -49,7 +49,7 @@
"jsplumb": "^2.15.6", "jsplumb": "^2.15.6",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"magic-string": "^0.30.19", "magic-string": "^0.30.19",
"md-editor-v3": "^6.0.1", "md-editor-v3": "^6.1.0",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"monaco-editor": "^0.54.0", "monaco-editor": "^0.54.0",
"mqtt": "^5.14.0", "mqtt": "^5.14.0",
@ -82,7 +82,7 @@
"vue-signature-pad": "^3.0.2", "vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2", "vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.9.41", "vxe-pc-ui": "^4.9.41",
"vxe-table": "^4.16.20", "vxe-table": "^4.16.21",
"xe-utils": "^3.7.9", "xe-utils": "^3.7.9",
"xlsx-js-style": "^1.2.0" "xlsx-js-style": "^1.2.0"
}, },
@ -90,7 +90,7 @@
"@iconify/vue": "^5.0.0", "@iconify/vue": "^5.0.0",
"@plugin-web-update-notification/vite": "^2.0.2", "@plugin-web-update-notification/vite": "^2.0.2",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^22.18.8", "@types/node": "^22.18.9",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8", "@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.46.0", "@typescript-eslint/eslint-plugin": "^8.46.0",

View File

@ -1,14 +1,14 @@
<template> <template>
<el-popover placement="bottom" width="300" trigger="hover"> <el-popover placement="bottom" width="300" trigger="hover">
<template #reference> <template #reference>
<el-text type="primary" class="cursor-pointer"> <el-text type="primary" class="cursor-default">
<el-icon><ele-InfoFilled /></el-icon>{{ t('message.list.detail') }} <el-icon><ele-InfoFilled /></el-icon>{{ t('message.list.detail') }}
</el-text> </el-text>
</template> </template>
<el-descriptions direction="vertical" :column="2" border> <el-descriptions direction="vertical" :column="2" border>
<el-descriptions-item width="140"> <el-descriptions-item width="140">
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-UserFilled /></el-icon>{{ t('message.list.creator') }} <el-icon><ele-UserFilled /></el-icon>{{ t('message.list.creator') }}
</el-text> </el-text>
</template> </template>
@ -16,7 +16,7 @@
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-Calendar /></el-icon>{{ t('message.list.createTime') }} <el-icon><ele-Calendar /></el-icon>{{ t('message.list.createTime') }}
</el-text> </el-text>
</template> </template>
@ -24,7 +24,7 @@
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-UserFilled /></el-icon>{{ t('message.list.modifier') }} <el-icon><ele-UserFilled /></el-icon>{{ t('message.list.modifier') }}
</el-text> </el-text>
</template> </template>
@ -32,7 +32,7 @@
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-Calendar /></el-icon>{{ t('message.list.modifyTime') }} <el-icon><ele-Calendar /></el-icon>{{ t('message.list.modifyTime') }}
</el-text> </el-text>
</template> </template>
@ -41,7 +41,7 @@
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-OfficeBuilding /></el-icon>{{ t('message.list.organizationName') }} <el-icon><ele-OfficeBuilding /></el-icon>{{ t('message.list.organizationName') }}
</el-text> </el-text>
</template> </template>
@ -49,7 +49,7 @@
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-School /></el-icon>{{ t('message.list.tenantName') }} <el-icon><ele-School /></el-icon>{{ t('message.list.tenantName') }}
</el-text> </el-text>
</template> </template>
@ -58,7 +58,7 @@
<el-descriptions-item v-if="'remark' in props.data"> <el-descriptions-item v-if="'remark' in props.data">
<template #label> <template #label>
<el-text> <el-text truncated class="one-line">
<el-icon><ele-Tickets /></el-icon>{{ t('message.list.remark') }} <el-icon><ele-Tickets /></el-icon>{{ t('message.list.remark') }}
</el-text> </el-text>
</template> </template>
@ -76,3 +76,13 @@ const props = defineProps<{
data: ModifyRecord; data: ModifyRecord;
}>(); }>();
</script> </script>
<style lang="scss" scoped>
.one-line {
width: 120px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

View File

@ -1,5 +1,6 @@
import type { FormItemRule } from 'element-plus'; import type { FormItemRule } from 'element-plus';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { nextTick, Ref, watch } from 'vue';
const TRIGGER_INPUT: FormItemRule['trigger'] = 'change'; const TRIGGER_INPUT: FormItemRule['trigger'] = 'change';
const TRIGGER_BLUR: FormItemRule['trigger'] = 'blur'; const TRIGGER_BLUR: FormItemRule['trigger'] = 'blur';
@ -17,6 +18,27 @@ export function useFormRulePresets() {
trigger, trigger,
}); });
const validatorIf = (shouldError: () => boolean, formRef?: Ref<any>, label: string = '此项') => {
let field = '';
watch(
() => shouldError(),
() => nextTick(() => formRef?.value?.validateField(field).catch(() => {})),
{ immediate: false, deep: true }
);
return {
validator: (_: any, __: any, callback: (error?: Error) => void) => {
field = _.field;
if (shouldError()) {
callback(new Error(`${label}为必填`));
} else {
callback();
}
},
trigger: ['blur', 'change'] as const,
};
};
const maxLen = (len: number, label = '此项', trigger = TRIGGER_INPUT): FormItemRule => ({ const maxLen = (len: number, label = '此项', trigger = TRIGGER_INPUT): FormItemRule => ({
max: len, max: len,
message: `${label}长度不能超过 ${len} 个字符`, message: `${label}长度不能超过 ${len} 个字符`,
@ -373,6 +395,7 @@ export function useFormRulePresets() {
return { return {
required, required,
requiredIf, requiredIf,
validatorIf,
maxLen, maxLen,
minLen, minLen,
pattern, pattern,

View File

@ -95,6 +95,7 @@ import { initBackEndControlRoutes } from '/@/router/backEnd';
import { Local, Session } from '/@/utils/storage'; import { Local, Session } from '/@/utils/storage';
import { formatAxis } from '/@/utils/formatTime'; import { formatAxis } from '/@/utils/formatTime';
import { NextLoading } from '/@/utils/loading'; import { NextLoading } from '/@/utils/loading';
import { loadSysInfo } from '/@/utils/sysInfo';
import { sm2 } from 'sm-crypto-v2'; import { sm2 } from 'sm-crypto-v2';
import { useRoutesList } from '/@/stores/routesList'; import { useRoutesList } from '/@/stores/routesList';
import { useThemeConfig } from '/@/stores/themeConfig'; import { useThemeConfig } from '/@/stores/themeConfig';
@ -161,11 +162,9 @@ onMounted(async () => {
const accessToken = route.query.token; const accessToken = route.query.token;
if (accessToken) await saveTokenAndInitRoutes(accessToken); if (accessToken) await saveTokenAndInitRoutes(accessToken);
// //
if (themeConfig.value.captcha == undefined) { if (themeConfig.value.captcha == undefined) {
setTimeout(() => { await loadSysInfo(Local.get('tid') ?? 0);
window.location.reload();
}, 1000);
} }
// //