- {{ 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