From 37c0035bfc9dd6cbe32a4876d595856322e22451 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Tue, 19 May 2026 15:31:04 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BC=98=E5=8C=96=E8=BF=90=E7=BB=B4=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=B8=AD=E6=B8=A0=E9=81=93=E5=88=97=E8=A1=A8=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=B8=A0=E9=81=93=E7=9A=84=E7=AD=9B=E9=80=89=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=97=AE=E9=A2=98=202.=E4=BC=98=E5=8C=96=E6=B8=A0?= =?UTF-8?q?=E9=81=93=E8=BF=90=E7=BB=B4=E7=AE=A1=E7=90=86=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../channel/SuperAdminChannelShell.vue | 14 +++++--- .../src/composables/useChannelDeptScope.ts | 33 ++++++++++++++++-- saiadmin-artd/src/locales/langs/en.json | 1 + saiadmin-artd/src/locales/langs/zh.json | 1 + saiadmin-artd/src/utils/channelLayout.ts | 34 +++++++++++++++++-- .../controller/system/SystemLogController.php | 2 ++ .../plugin/saiadmin/app/event/SystemUser.php | 16 +++++++++ .../app/model/system/SystemLoginLog.php | 11 ++++++ .../app/model/system/SystemOperLog.php | 11 ++++++ 9 files changed, 115 insertions(+), 8 deletions(-) diff --git a/saiadmin-artd/src/components/channel/SuperAdminChannelShell.vue b/saiadmin-artd/src/components/channel/SuperAdminChannelShell.vue index 81021bf..0878c93 100644 --- a/saiadmin-artd/src/components/channel/SuperAdminChannelShell.vue +++ b/saiadmin-artd/src/components/channel/SuperAdminChannelShell.vue @@ -25,8 +25,8 @@
-
- {{ bannerLabel }}:{{ selectedDeptLabel }} +
+ {{ bannerLabel }}:{{ selectedDisplayLabel }}
@@ -66,10 +66,10 @@ treeData, selectedDeptId, loadingChannels, - selectedDeptLabel, handleChannelClick, provideScope, isConfigScope, + isAllChannelScope, showDefaultTemplate } = useChannelDeptScope() @@ -82,11 +82,17 @@ const defaultLabel = isRoleChannelRoute(route) ? t('common.channelScope.defaultRoleTemplate') : t('common.channelScope.defaultTemplate') + const emptyNodeLabel = isAllChannelScope.value ? t('common.channelScope.allChannels') : defaultLabel return nodes.map((node) => - node.id === DEFAULT_CHANNEL_ID && !node.label ? { ...node, label: defaultLabel } : node + node.id === DEFAULT_CHANNEL_ID && !node.label ? { ...node, label: emptyNodeLabel } : node ) }) + const selectedDisplayLabel = computed(() => { + const item = displayTreeData.value.find((node) => node.id === selectedDeptId.value) + return item?.label ?? '' + }) + const bannerLabel = computed(() => { if (isConfigScope.value) { return t('common.channelScope.currentConfig') diff --git a/saiadmin-artd/src/composables/useChannelDeptScope.ts b/saiadmin-artd/src/composables/useChannelDeptScope.ts index 1d77edd..97aae02 100644 --- a/saiadmin-artd/src/composables/useChannelDeptScope.ts +++ b/saiadmin-artd/src/composables/useChannelDeptScope.ts @@ -1,8 +1,15 @@ import type { InjectionKey, Ref, ComputedRef } from 'vue' import { useRoute } from 'vue-router' import deptApi from '@/api/system/dept' +import { router } from '@/router' import { useUserStore } from '@/store/modules/user' -import { isConfigChannelRoute, isRoleChannelRoute, isSuperAdminUser } from '@/utils/channelLayout' +import { + isAllChannelScopeRoute, + isConfigChannelRoute, + isNoChannelLayoutRoute, + isRoleChannelRoute, + isSuperAdminUser +} from '@/utils/channelLayout' export interface ChannelTreeNode { id: number @@ -21,6 +28,7 @@ export interface ChannelDeptScopeContext { selectedDeptLabel: Ref deptQueryParams: ComputedRef<{ dept_id: number }> isConfigScope: ComputedRef + isAllChannelScope: ComputedRef showDefaultTemplate: ComputedRef } @@ -68,6 +76,7 @@ export function useChannelDeptScope() { const isConfigScope = computed(() => isConfigChannelRoute(route)) const isRoleScope = computed(() => isRoleChannelRoute(route)) + const isAllChannelScope = computed(() => isAllChannelScopeRoute(route)) const showDefaultTemplate = computed(() => isConfigScope.value || isRoleScope.value) const isSuperAdmin = computed(() => isSuperAdminUser()) @@ -90,6 +99,9 @@ export function useChannelDeptScope() { const deptQueryParams = computed(() => { const id = selectedDeptId.value + if (isAllChannelScope.value && id <= 0) { + return { dept_id: 0 } + } if (!showDefaultTemplate.value && id <= 0) { return { dept_id: 0 } } @@ -106,7 +118,7 @@ export function useChannelDeptScope() { label: String(item.label ?? item.name ?? item.id) })) if (isSuperAdmin.value) { - if (showDefaultTemplate.value) { + if (showDefaultTemplate.value || isAllChannelScope.value) { treeData.value = [{ id: DEFAULT_CHANNEL_ID, label: '' }, ...nodes] if (!treeData.value.some((n) => n.id === selectedDeptId.value)) { selectedDeptId.value = DEFAULT_CHANNEL_ID @@ -143,6 +155,7 @@ export function useChannelDeptScope() { selectedDeptLabel, deptQueryParams, isConfigScope, + isAllChannelScope, showDefaultTemplate } @@ -170,6 +183,11 @@ export function bindChannelDeptToSearchParams( } const apply = (deptId: number) => { + if (channel.isAllChannelScope.value && deptId <= 0) { + delete searchParams.dept_id + refresh() + return + } if (!channel.showDefaultTemplate.value && deptId <= 0) { return } @@ -197,6 +215,10 @@ export function useChannelDeptReload(loadFn: () => void | Promise) { watch( () => channel.selectedDeptId.value, (deptId) => { + if (channel.isAllChannelScope.value && deptId <= 0) { + void loadFn() + return + } if (!channel.showDefaultTemplate.value && deptId <= 0) { return } @@ -209,8 +231,15 @@ export function useChannelDeptReload(loadFn: () => void | Promise) { /** 请求参数:业务页附带 dept_id;渠道管理员固定本渠道 */ export function getChannelDeptRequestParams(): { dept_id?: number } { const channel = useInjectedChannelDept() + const route = getCurrentInstance() ? useRoute() : router.currentRoute.value + if (isNoChannelLayoutRoute(route)) { + return {} + } if (channel?.isSuperAdmin.value) { const deptId = channel.selectedDeptId.value + if (channel.isAllChannelScope.value && deptId <= 0) { + return {} + } if (!channel.showDefaultTemplate.value && deptId <= 0) { return {} } diff --git a/saiadmin-artd/src/locales/langs/en.json b/saiadmin-artd/src/locales/langs/en.json index 3ee0f14..165ae46 100644 --- a/saiadmin-artd/src/locales/langs/en.json +++ b/saiadmin-artd/src/locales/langs/en.json @@ -42,6 +42,7 @@ "listTitle": "Channels", "defaultTemplate": "Default template", "defaultRoleTemplate": "Default role template", + "allChannels": "All", "currentConfig": "Current config", "currentChannel": "Current channel", "currentRole": "Current roles" diff --git a/saiadmin-artd/src/locales/langs/zh.json b/saiadmin-artd/src/locales/langs/zh.json index 16be7b7..5a295e0 100644 --- a/saiadmin-artd/src/locales/langs/zh.json +++ b/saiadmin-artd/src/locales/langs/zh.json @@ -42,6 +42,7 @@ "listTitle": "渠道列表", "defaultTemplate": "默认配置模板", "defaultRoleTemplate": "默认角色模板", + "allChannels": "全部", "currentConfig": "当前配置", "currentChannel": "当前渠道", "currentRole": "当前角色范围" diff --git a/saiadmin-artd/src/utils/channelLayout.ts b/saiadmin-artd/src/utils/channelLayout.ts index bbfe953..3da80e0 100644 --- a/saiadmin-artd/src/utils/channelLayout.ts +++ b/saiadmin-artd/src/utils/channelLayout.ts @@ -7,6 +7,22 @@ const BUILTIN_CHANNEL_LAYOUT_PATHS = [ '/system/dept' ] +/** 运维页里不需要按渠道分栏的页面 */ +const NO_CHANNEL_LAYOUT_PATHS = [ + '/safeguard/dict', + '/safeguard/attachment', + '/safeguard/database', + '/safeguard/server', + '/safeguard/cache', + '/safeguard/email-log' +] + +/** 日志页:左侧首项为「全部」,dept_id=0 表示不按渠道过滤 */ +const ALL_CHANNEL_SCOPE_PATHS = [ + '/safeguard/login-log', + '/safeguard/oper-log' +] + export function isSuperAdminUser(): boolean { const userStore = useUserStore() return Number(userStore.info?.id ?? 0) === 1 @@ -28,6 +44,20 @@ export function isRoleChannelRoute(route: Pick): boolean { + if (route.meta?.channelScope === 'all') { + return true + } + return ALL_CHANNEL_SCOPE_PATHS.some((item) => route.path.startsWith(item)) +} + +export function isNoChannelLayoutRoute(route: Pick): boolean { + if (route.meta?.noChannelLayout === true) { + return true + } + return NO_CHANNEL_LAYOUT_PATHS.some((item) => route.path.startsWith(item)) +} + export function shouldWrapSuperAdminChannelLayout(route: RouteLocationNormalized): boolean { if (!isSuperAdminUser()) { return false @@ -35,10 +65,10 @@ export function shouldWrapSuperAdminChannelLayout(route: RouteLocationNormalized if (route.meta?.isFullPage) { return false } - if (route.meta?.noChannelLayout === true) { + const path = route.path + if (isNoChannelLayoutRoute(route)) { return false } - const path = route.path for (let i = 0; i < BUILTIN_CHANNEL_LAYOUT_PATHS.length; i++) { if (path.startsWith(BUILTIN_CHANNEL_LAYOUT_PATHS[i])) { return false diff --git a/server/plugin/saiadmin/app/controller/system/SystemLogController.php b/server/plugin/saiadmin/app/controller/system/SystemLogController.php index 54bfda1..55e9a24 100644 --- a/server/plugin/saiadmin/app/controller/system/SystemLogController.php +++ b/server/plugin/saiadmin/app/controller/system/SystemLogController.php @@ -32,6 +32,7 @@ class SystemLogController extends BaseController ['username', ''], ['status', ''], ['ip', ''], + ['dept_id', ''], ]); $logic = new SystemLoginLogLogic(); $query = $logic->search($where); @@ -71,6 +72,7 @@ class SystemLogController extends BaseController ['service_name', ''], ['router', ''], ['ip', ''], + ['dept_id', ''], ]); $logic = new SystemOperLogLogic(); $logic->init($this->adminInfo); diff --git a/server/plugin/saiadmin/app/event/SystemUser.php b/server/plugin/saiadmin/app/event/SystemUser.php index f85ef3f..d0408f2 100644 --- a/server/plugin/saiadmin/app/event/SystemUser.php +++ b/server/plugin/saiadmin/app/event/SystemUser.php @@ -9,6 +9,7 @@ namespace plugin\saiadmin\app\event; use plugin\saiadmin\app\cache\ReflectionCache; use plugin\saiadmin\app\model\system\SystemLoginLog; use plugin\saiadmin\app\model\system\SystemOperLog; +use plugin\saiadmin\app\model\system\SystemUser as SystemUserModel; class SystemUser { @@ -32,6 +33,10 @@ class SystemUser if (isset($item['admin_id'])) { $data['created_by'] = $item['admin_id']; $data['updated_by'] = $item['admin_id']; + $deptId = SystemUserModel::where('id', $item['admin_id'])->value('dept_id'); + if ($deptId !== null && $deptId !== '' && $deptId > 0) { + $data['dept_id'] = $deptId; + } } SystemLoginLog::create($data); } @@ -49,6 +54,9 @@ class SystemUser return false; } $info = getCurrentInfo(); + if (!$info) { + return false; + } $ip = $request->getRealIp(); $module = $request->plugin; $rule = trim($request->uri()); @@ -60,6 +68,14 @@ class SystemUser $data['ip'] = $ip; $data['ip_location'] = self::getIpLocation($ip); $data['request_data'] = $this->filterParams($request->all()); + if (isset($info['dept_id']) && $info['dept_id'] > 0) { + $data['dept_id'] = $info['dept_id']; + } elseif (isset($info['id'])) { + $deptId = SystemUserModel::where('id', $info['id'])->value('dept_id'); + if ($deptId !== null && $deptId !== '' && $deptId > 0) { + $data['dept_id'] = $deptId; + } + } SystemOperLog::create($data); return true; } diff --git a/server/plugin/saiadmin/app/model/system/SystemLoginLog.php b/server/plugin/saiadmin/app/model/system/SystemLoginLog.php index 1aaba87..f2c0ee4 100644 --- a/server/plugin/saiadmin/app/model/system/SystemLoginLog.php +++ b/server/plugin/saiadmin/app/model/system/SystemLoginLog.php @@ -23,6 +23,7 @@ use plugin\saiadmin\basic\think\BaseModel; * @property $status 登录状态 * @property $message 提示消息 * @property $login_time 登录时间 + * @property $dept_id 所属渠道 * @property $remark 备注 * @property $created_by 创建者 * @property $updated_by 更新者 @@ -47,4 +48,14 @@ class SystemLoginLog extends BaseModel $query->whereTime('login_time', 'between', $value); } + /** + * 渠道搜索 + */ + public function searchDeptIdAttr($query, $value): void + { + if ($value !== '' && $value !== null && $value > 0) { + $query->where('dept_id', '=', $value); + } + } + } \ No newline at end of file diff --git a/server/plugin/saiadmin/app/model/system/SystemOperLog.php b/server/plugin/saiadmin/app/model/system/SystemOperLog.php index 4c95df3..fdf27a1 100644 --- a/server/plugin/saiadmin/app/model/system/SystemOperLog.php +++ b/server/plugin/saiadmin/app/model/system/SystemOperLog.php @@ -23,6 +23,7 @@ use plugin\saiadmin\basic\think\BaseModel; * @property $ip 请求IP地址 * @property $ip_location IP所属地 * @property $request_data 请求数据 + * @property $dept_id 所属渠道 * @property $remark 备注 * @property $created_by 创建者 * @property $updated_by 更新者 @@ -39,4 +40,14 @@ class SystemOperLog extends BaseModel protected $table = 'sa_system_oper_log'; + /** + * 渠道搜索 + */ + public function searchDeptIdAttr($query, $value): void + { + if ($value !== '' && $value !== null && $value > 0) { + $query->where('dept_id', '=', $value); + } + } + } \ No newline at end of file