mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-12-07 22:57:15 +08:00
feat(system/client) :客户端管理扩展登录配置
This commit is contained in:
@@ -295,12 +295,17 @@ export interface ClientResp {
|
|||||||
activeTimeout: string
|
activeTimeout: string
|
||||||
timeout: string
|
timeout: string
|
||||||
status: string
|
status: string
|
||||||
|
isConcurrent: boolean
|
||||||
|
maxLoginCount: number
|
||||||
|
replacedRange: string
|
||||||
|
overflowLogoutMode: string
|
||||||
createUser: string
|
createUser: string
|
||||||
createTime: string
|
createTime: string
|
||||||
updateUser: string
|
updateUser: string
|
||||||
updateTime: string
|
updateTime: string
|
||||||
createUserString: string
|
createUserString: string
|
||||||
updateUserString: string
|
updateUserString: string
|
||||||
|
disabled: boolean
|
||||||
}
|
}
|
||||||
export interface ClientDetailResp {
|
export interface ClientDetailResp {
|
||||||
id: string
|
id: string
|
||||||
@@ -309,7 +314,11 @@ export interface ClientDetailResp {
|
|||||||
authType: string
|
authType: string
|
||||||
activeTimeout: string
|
activeTimeout: string
|
||||||
timeout: string
|
timeout: string
|
||||||
status: string
|
status: number
|
||||||
|
isConcurrent: boolean
|
||||||
|
maxLoginCount: number
|
||||||
|
replacedRange: string
|
||||||
|
overflowLogoutMode: string
|
||||||
createUser: string
|
createUser: string
|
||||||
createTime: string
|
createTime: string
|
||||||
updateUser: string
|
updateUser: string
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
:style="appStore.menuDark ? appStore.themeCSSVar : undefined"
|
:style="appStore.menuDark ? appStore.themeCSSVar : undefined"
|
||||||
>
|
>
|
||||||
<Logo :collapsed="appStore.menuCollapse" />
|
<Logo :collapsed="appStore.menuCollapse" />
|
||||||
<Menu :menus="twoLevelMenus" :menu-style="{ width: '200px', flex: 1 }" />
|
<Menu :menus="twoLevelMenus" :menu-style="{ flex: 1 }" />
|
||||||
<WwAds class="ads" />
|
<WwAds class="ads" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -83,7 +83,6 @@ const checkAndShowNotices = () => {
|
|||||||
// 如果有token,检查未读公告
|
// 如果有token,检查未读公告
|
||||||
if (token) {
|
if (token) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log(noticePopupRef.value)
|
|
||||||
noticePopupRef.value?.open()
|
noticePopupRef.value?.open()
|
||||||
}, 1000) // 延迟1秒显示,让页面先加载完成
|
}, 1000) // 延迟1秒显示,让页面先加载完成
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,32 @@ const visible = ref(false)
|
|||||||
const isUpdate = computed(() => !!dataId.value)
|
const isUpdate = computed(() => !!dataId.value)
|
||||||
const title = computed(() => (isUpdate.value ? '修改客户端' : '新增客户端'))
|
const title = computed(() => (isUpdate.value ? '修改客户端' : '新增客户端'))
|
||||||
const formRef = ref<InstanceType<typeof GiForm>>()
|
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||||
const { client_type, auth_type_enum } = useDict('auth_type_enum', 'client_type')
|
const { client_type, auth_type_enum, replaced_range_enum, logout_mode_enum } = useDict('auth_type_enum', 'client_type', 'replaced_range_enum', 'logout_mode_enum')
|
||||||
|
|
||||||
const [form, resetForm] = useResetReactive({
|
const [form, resetForm] = useResetReactive({
|
||||||
activeTimeout: 1800,
|
activeTimeout: 1800,
|
||||||
timeout: 86400,
|
timeout: 86400,
|
||||||
isConcurrent: 1,
|
isConcurrent: true,
|
||||||
isShare: 1,
|
maxLoginCount: -1,
|
||||||
|
replacedRange: 'ALL_DEVICE_TYPE',
|
||||||
|
overflowLogoutMode: 'KICKOUT',
|
||||||
status: 1,
|
status: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听 isConcurrent 的变化,处理字段互斥逻辑
|
||||||
|
watch(
|
||||||
|
() => form.isConcurrent,
|
||||||
|
(newVal) => {
|
||||||
|
if (!newVal) {
|
||||||
|
form.maxLoginCount = -1
|
||||||
|
// replacedRange 只有在 isConcurrent=false 时才有意义
|
||||||
|
} else if (newVal) {
|
||||||
|
// 当 isConcurrent=true 时,清空 maxLoginCount
|
||||||
|
form.maxLoginCount = -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
const columns: ColumnItem[] = reactive([
|
const columns: ColumnItem[] = reactive([
|
||||||
{
|
{
|
||||||
label: '客户端类型',
|
label: '客户端类型',
|
||||||
@@ -87,7 +103,7 @@ const columns: ColumnItem[] = reactive([
|
|||||||
{
|
{
|
||||||
label: () => (
|
label: () => (
|
||||||
<a-tooltip content="-1 代表永不过期">
|
<a-tooltip content="-1 代表永不过期">
|
||||||
Token 有效期
|
Token 有效期
|
||||||
<icon-question-circle />
|
<icon-question-circle />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
),
|
),
|
||||||
@@ -104,6 +120,75 @@ const columns: ColumnItem[] = reactive([
|
|||||||
},
|
},
|
||||||
rules: [{ required: true, message: '请输入 Token 有效期' }],
|
rules: [{ required: true, message: '请输入 Token 有效期' }],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '是否允许同一账号多地同时登录',
|
||||||
|
field: 'isConcurrent',
|
||||||
|
type: 'switch',
|
||||||
|
span: 12,
|
||||||
|
props: {
|
||||||
|
type: 'round',
|
||||||
|
checkedValue: true,
|
||||||
|
uncheckedValue: false,
|
||||||
|
checkedText: '允许',
|
||||||
|
uncheckedText: '不允许',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () => (
|
||||||
|
<a-tooltip content="-1 代表不限">
|
||||||
|
最大登录数量
|
||||||
|
<icon-question-circle />
|
||||||
|
</a-tooltip>
|
||||||
|
),
|
||||||
|
field: 'maxLoginCount',
|
||||||
|
type: 'input-number',
|
||||||
|
span: 12,
|
||||||
|
slots: {
|
||||||
|
append: () => (
|
||||||
|
<span style={{ width: '80px', textAlign: 'center' }}>个</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入最大登录数量',
|
||||||
|
min: -1,
|
||||||
|
},
|
||||||
|
disabled: () => {
|
||||||
|
return !form.isConcurrent
|
||||||
|
},
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
validator: (value: number, callback: (errorMessage?: string) => void) => {
|
||||||
|
if (value === 0) {
|
||||||
|
callback('最大登录数量不能为0,请输入-1或正整数')
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '顶人下线的范围',
|
||||||
|
field: 'replacedRange',
|
||||||
|
type: 'select',
|
||||||
|
span: 12,
|
||||||
|
props: {
|
||||||
|
options: replaced_range_enum,
|
||||||
|
placeholder: '请选择顶人下线的范围',
|
||||||
|
},
|
||||||
|
disabled: () => {
|
||||||
|
return form.isConcurrent
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '溢出人数的注销方式',
|
||||||
|
field: 'overflowLogoutMode',
|
||||||
|
type: 'select',
|
||||||
|
span: 12,
|
||||||
|
props: {
|
||||||
|
options: logout_mode_enum,
|
||||||
|
placeholder: '请选择溢出人数的注销方式',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
field: 'status',
|
field: 'status',
|
||||||
|
|||||||
@@ -17,6 +17,19 @@
|
|||||||
<a-tag v-if="dataDetail?.status === 1" color="green">启用</a-tag>
|
<a-tag v-if="dataDetail?.status === 1" color="green">启用</a-tag>
|
||||||
<a-tag v-else color="red">禁用</a-tag>
|
<a-tag v-else color="red">禁用</a-tag>
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="是否允许多地登录" :span="2">
|
||||||
|
<a-tag v-if="dataDetail?.isConcurrent" color="blue">允许</a-tag>
|
||||||
|
<a-tag v-else color="orange">不允许</a-tag>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="最大登录数量">
|
||||||
|
{{ dataDetail?.maxLoginCount === -1 ? '不限' : dataDetail?.maxLoginCount }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="顶人下线范围">
|
||||||
|
<GiCellTag :value="dataDetail?.replacedRange" :dict="replaced_range_enum" />
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="溢出注销方式" :span="2">
|
||||||
|
<GiCellTag :value="dataDetail?.overflowLogoutMode" :dict="logout_mode_enum" />
|
||||||
|
</a-descriptions-item>
|
||||||
<a-descriptions-item label="创建人">{{ dataDetail?.createUserString }}</a-descriptions-item>
|
<a-descriptions-item label="创建人">{{ dataDetail?.createUserString }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="创建时间">{{ dataDetail?.createTime }}</a-descriptions-item>
|
<a-descriptions-item label="创建时间">{{ dataDetail?.createTime }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="更新人">{{ dataDetail?.updateUserString }}</a-descriptions-item>
|
<a-descriptions-item label="更新人">{{ dataDetail?.updateUserString }}</a-descriptions-item>
|
||||||
@@ -29,11 +42,14 @@
|
|||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
import { type ClientDetailResp, getClient as getDetail } from '@/apis/system/client'
|
import { type ClientDetailResp, getClient as getDetail } from '@/apis/system/client'
|
||||||
import { useDict } from '@/hooks/app'
|
import { useDict } from '@/hooks/app'
|
||||||
|
import GiCellTag from '@/components/GiCell/GiCellTag.vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
client_type,
|
client_type,
|
||||||
auth_type_enum,
|
auth_type_enum,
|
||||||
} = useDict('client_type', 'auth_type_enum')
|
replaced_range_enum,
|
||||||
|
logout_mode_enum,
|
||||||
|
} = useDict('client_type', 'auth_type_enum', 'replaced_range_enum', 'logout_mode_enum')
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import type { LabelValue } from '@arco-design/web-vue/es/tree-select/interface'
|
import type { LabelValue } from '@arco-design/web-vue/es/tree-select/interface'
|
||||||
import type { TableInstance } from '@arco-design/web-vue'
|
import { type TableInstance, Tag } from '@arco-design/web-vue'
|
||||||
import AddModal from './AddModal.vue'
|
import AddModal from './AddModal.vue'
|
||||||
import DetailDrawer from './DetailDrawer.vue'
|
import DetailDrawer from './DetailDrawer.vue'
|
||||||
import { type ClientQuery, type ClientResp, deleteClient, listClient } from '@/apis/system/client'
|
import { type ClientQuery, type ClientResp, deleteClient, listClient } from '@/apis/system/client'
|
||||||
@@ -79,7 +79,9 @@ defineOptions({ name: 'SystemClient' })
|
|||||||
const {
|
const {
|
||||||
client_type,
|
client_type,
|
||||||
auth_type_enum,
|
auth_type_enum,
|
||||||
} = useDict('client_type', 'auth_type_enum')
|
replaced_range_enum,
|
||||||
|
logout_mode_enum,
|
||||||
|
} = useDict('client_type', 'auth_type_enum', 'replaced_range_enum', 'logout_mode_enum')
|
||||||
|
|
||||||
const queryForm = reactive<ClientQuery>({
|
const queryForm = reactive<ClientQuery>({
|
||||||
clientType: '',
|
clientType: '',
|
||||||
@@ -89,7 +91,7 @@ const queryForm = reactive<ClientQuery>({
|
|||||||
})
|
})
|
||||||
const formatAuthType = (data: string[]) => {
|
const formatAuthType = (data: string[]) => {
|
||||||
return data.map((item: string) => {
|
return data.map((item: string) => {
|
||||||
return auth_type_enum.value.find((d: LabelValue) => d.value === item).label
|
return auth_type_enum.value?.find((d: LabelValue) => d.value === item)?.label
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,15 +157,43 @@ const columns: TableInstance['columns'] = [
|
|||||||
return <GiCellStatus status={record.status} />
|
return <GiCellStatus status={record.status} />
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '是否允许多地登录',
|
||||||
|
dataIndex: 'isConcurrent',
|
||||||
|
align: 'center',
|
||||||
|
render: ({ record }) => {
|
||||||
|
return <Tag>{record.isConcurrent ? '允许' : '不允许'}</Tag>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '最大登录数量',
|
||||||
|
dataIndex: 'maxLoginCount',
|
||||||
|
align: 'center',
|
||||||
|
render: ({ record }) => {
|
||||||
|
return record.maxLoginCount === -1 ? '不限' : record.maxLoginCount
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '顶人下线范围',
|
||||||
|
dataIndex: 'replacedRange',
|
||||||
|
align: 'center',
|
||||||
|
render: ({ record }) => {
|
||||||
|
return <GiCellTag value={record.replacedRange} dict={replaced_range_enum.value} />
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '溢出注销方式',
|
||||||
|
dataIndex: 'overflowLogoutMode',
|
||||||
|
align: 'center',
|
||||||
|
render: ({ record }) => {
|
||||||
|
return <GiCellTag value={record.overflowLogoutMode} dict={logout_mode_enum.value} />
|
||||||
|
},
|
||||||
|
},
|
||||||
{ title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false },
|
{ title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false },
|
||||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
|
||||||
{ title: '修改人', dataIndex: 'updateUserString', width: 140, ellipsis: true, tooltip: true, show: false },
|
|
||||||
{ title: '修改时间', dataIndex: 'updateTime', width: 180, show: false },
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
slotName: 'action',
|
slotName: 'action',
|
||||||
width: 160,
|
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: !isMobile() ? 'right' : undefined,
|
fixed: !isMobile() ? 'right' : undefined,
|
||||||
show: has.hasPermOr(['system:client:get', 'system:client:update', 'system:client:delete']),
|
show: has.hasPermOr(['system:client:get', 'system:client:update', 'system:client:delete']),
|
||||||
|
|||||||
Reference in New Issue
Block a user