feat(dict): apply dynamic dictionaries across user, menu and log pages

This commit is contained in:
Leo 2025-09-27 00:54:38 +08:00
parent d50611c05b
commit 7c1bf63133
5 changed files with 153 additions and 187 deletions

View File

@ -51,10 +51,7 @@
v-model:value="searchForm.loginStatus"
placeholder="请选择登录状态"
clearable
:options="[
{ label: '成功', value: '0' },
{ label: '失败', value: '1' },
]"
:options="loginStatusOptions"
/>
</n-form-item>
</n-grid-item>
@ -196,12 +193,13 @@
</template>
<script setup lang="ts">
import { h, nextTick, onMounted, ref } from 'vue'
import { computed, h, nextTick, onMounted, ref } from 'vue'
import type { DataTableColumns, FormInst } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace, NTag } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace } from 'naive-ui'
import IconParkOutlineDelete from '~icons/icon-park-outline/delete'
import CoiEmpty from '@/components/common/CoiEmpty.vue'
import CoiPagination from '@/components/common/CoiPagination.vue'
import DictTag from '@/components/common/DictTag.vue'
import {
batchDeleteLoginLog,
deleteLoginLog,
@ -210,10 +208,21 @@ import {
import type { LoginLogVo } from '@/service/api/system/loginlog'
import { coiMsgBox, coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks/usePermission'
import { useDict, usePermission } from '@/hooks'
//
const { hasPermission } = usePermission()
const { dictOptions } = useDict(['sys_common_status'])
const loginStatusOptions = computed(() => {
const options = dictOptions.sys_common_status || []
return options
.filter(option => option.dictValue === '1' || option.dictValue === '2')
.map(option => ({
label: option.dictLabel,
value: option.dictValue === '1' ? '0' : '1',
}))
})
//
interface LoginLogSearchForm {
@ -320,17 +329,9 @@ const columns: DataTableColumns<LoginLogVo> = [
{
title: '登录状态',
key: 'loginStatus',
width: 100,
width: 110,
align: 'center',
render: (row) => {
const isSuccess = row.loginStatus === '0'
return h(NTag, {
type: isSuccess ? 'success' : 'error',
size: 'small',
}, {
default: () => isSuccess ? '操作成功' : '操作失败',
})
},
render: row => h(DictTag, { dictType: 'sys_common_status', value: row.loginStatus === '0' ? '1' : '2' }),
},
{
title: '登录信息',

View File

@ -40,10 +40,7 @@
v-model:value="searchForm.menuStatus"
placeholder="请选择菜单状态"
clearable
:options="[
{ label: '启用', value: '0' },
{ label: '停用', value: '1' },
]"
:options="getSelectOptions('sys_switch_status')"
/>
</n-form-item>
</n-grid-item>
@ -235,7 +232,7 @@
:style="formData.parentId === '0' ? { color: themeColors.primary, fontWeight: '500' } : {}"
@click="handleSelectParent('0', '最顶级菜单')"
>
<n-radio
<NRadio
:checked="formData.parentId === '0'"
style="pointer-events: none;"
/>
@ -263,7 +260,7 @@
@click="handleSelectParent(menu.value, menu.label)"
@mouseenter="handleMenuHover(menu)"
>
<n-radio
<NRadio
:checked="formData.parentId === menu.value"
style="pointer-events: none;"
/>
@ -303,7 +300,7 @@
:style="formData.parentId === submenu.value ? { color: themeColors.primary, fontWeight: '500' } : {}"
@click="handleSelectParent(submenu.value, submenu.label)"
>
<n-radio
<NRadio
:checked="formData.parentId === submenu.value"
style="pointer-events: none;"
/>
@ -325,20 +322,18 @@
<!-- 菜单类型 -->
<n-form-item label="菜单类型" path="menuType" class="mb-2">
<n-radio-group
<NRadioGroup
v-model:value="formData.menuType"
@update:value="handleMenuTypeChange"
>
<n-radio value="1">
目录
</n-radio>
<n-radio value="2">
菜单
</n-radio>
<n-radio value="3">
按钮
</n-radio>
</n-radio-group>
<NRadio
v-for="item in dictOptions.sys_menu_type || []"
:key="item.dictValue"
:value="item.dictValue"
>
{{ item.dictLabel }}
</NRadio>
</NRadioGroup>
</n-form-item>
<!-- 菜单图标 -->
@ -392,14 +387,14 @@
<n-grid :cols="2" :x-gap="10" class="mb-2">
<n-grid-item>
<n-form-item label="是否隐藏" path="isHide">
<n-radio-group v-model:value="formData.isHide">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isHide">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
<n-grid-item>
@ -438,14 +433,14 @@
<n-grid :cols="2" :x-gap="10" class="mb-2">
<n-grid-item>
<n-form-item label="是否缓存" path="isKeepAlive">
<n-radio-group v-model:value="formData.isKeepAlive">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isKeepAlive">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
<n-grid-item>
@ -462,26 +457,26 @@
<n-grid :cols="2" :x-gap="10" class="mb-2">
<n-grid-item>
<n-form-item label="是否展开" path="isSpread">
<n-radio-group v-model:value="formData.isSpread">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isSpread">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="是否固钉" path="isAffix">
<n-radio-group v-model:value="formData.isAffix">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isAffix">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
</n-grid>
@ -492,26 +487,26 @@
<n-grid :cols="2" :x-gap="10" class="mb-2">
<n-grid-item>
<n-form-item label="是否展开" path="isSpread">
<n-radio-group v-model:value="formData.isSpread">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isSpread">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="是否固钉" path="isAffix">
<n-radio-group v-model:value="formData.isAffix">
<n-radio value="0">
<NRadioGroup v-model:value="formData.isAffix">
<NRadio value="0">
</n-radio>
<n-radio value="1">
</NRadio>
<NRadio value="1">
</n-radio>
</n-radio-group>
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
</n-grid>
@ -535,7 +530,7 @@
<script setup lang="ts">
import { computed, h, nextTick, onMounted, ref } from 'vue'
import type { DataTableColumns, FormInst, FormRules } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace, NSwitch, NTag } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NRadio, NRadioGroup, NSpace, NSwitch, NTag } from 'naive-ui'
import IconParkOutlineDelete from '~icons/icon-park-outline/delete'
import IconParkOutlineEdit from '~icons/icon-park-outline/edit'
import IconParkOutlinePlus from '~icons/icon-park-outline/plus'
@ -543,8 +538,9 @@ import CoiDialog from '@/components/common/CoiDialog.vue'
import CoiEmpty from '@/components/common/CoiEmpty.vue'
import CoiIcon from '@/components/common/CoiIcon.vue'
import IconSelect from '@/components/common/IconSelect.vue'
import DictTag from '@/components/common/DictTag.vue'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks'
import { useDict, usePermission } from '@/hooks'
import { coiMsgBox, coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import {
addMenu,
@ -587,6 +583,11 @@ const selectedRows = ref<MenuVo[]>([])
const expandedKeys = ref<string[]>([])
const isAllExpanded = ref(true)
const { dictOptions, getSelectOptions, getDictLabel } = useDict([
'sys_menu_type',
'sys_switch_status',
])
//
const menuDialogRef = ref()
const formRef = ref<FormInst>()
@ -716,15 +717,7 @@ const columns: DataTableColumns<MenuVo> = [
key: 'menuType',
width: 100,
align: 'center',
render: (row) => {
const typeMap = {
1: { label: '目录', color: 'primary' },
2: { label: '菜单', color: 'info' },
3: { label: '按钮', color: 'warning' },
}
const type = typeMap[Number(row.menuType) as keyof typeof typeMap]
return h(NTag, { type: type.color }, { default: () => type.label })
},
render: row => h(DictTag, { dictType: 'sys_menu_type', value: row.menuType }),
},
{
title: '展开/折叠',
@ -818,6 +811,8 @@ const columns: DataTableColumns<MenuVo> = [
render: (row) => {
return h(NSwitch, {
value: row.menuStatus === '0',
checkedChildren: getDictLabel('sys_switch_status', '0', '启用'),
uncheckedChildren: getDictLabel('sys_switch_status', '1', '停用'),
onUpdateValue: value => handleStatusChange(row, value ? '0' : '1'),
})
},
@ -1315,7 +1310,8 @@ async function handleStatusChange(menu: MenuVo, status: string) {
//
updateMenuStatusInData(tableData.value, menu.menuId, status)
coiMsgSuccess('状态修改成功')
const statusLabel = getDictLabel('sys_switch_status', status, status === '0' ? '启用' : '停用')
coiMsgSuccess(`状态已更新为「${statusLabel}`)
}
catch {
coiMsgError('状态修改失败')

View File

@ -40,10 +40,7 @@
v-model:value="searchForm.operStatus"
placeholder="请选择操作状态"
clearable
:options="[
{ label: '操作成功', value: '0' },
{ label: '操作失败', value: '1' },
]"
:options="operStatusOptions"
/>
</n-form-item>
</n-grid-item>
@ -233,9 +230,7 @@
{{ currentLogDetail.costTime || '-' }}
</n-descriptions-item>
<n-descriptions-item label="操作状态">
<NTag :type="currentLogDetail.operStatus === '0' ? 'success' : 'error'" size="small">
{{ currentLogDetail.operStatus === '0' ? '操作成功' : '操作失败' }}
</NTag>
<DictTag dict-type="sys_common_status" :value="currentLogDetail.operStatus === '0' ? '1' : '2'" />
</n-descriptions-item>
<n-descriptions-item v-if="currentLogDetail.operParam" label="请求参数" :span="2">
<div class="json-container">
@ -255,7 +250,7 @@
</template>
<script setup lang="ts">
import { h, nextTick, onMounted, ref } from 'vue'
import { computed, h, nextTick, onMounted, ref } from 'vue'
import type { DataTableColumns, FormInst } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace, NTag } from 'naive-ui'
import IconParkOutlineDelete from '~icons/icon-park-outline/delete'
@ -263,6 +258,7 @@ import IconParkOutlinePreviewOpen from '~icons/icon-park-outline/preview-open'
import CoiDialog from '@/components/common/CoiDialog.vue'
import CoiEmpty from '@/components/common/CoiEmpty.vue'
import CoiPagination from '@/components/common/CoiPagination.vue'
import DictTag from '@/components/common/DictTag.vue'
import {
batchDeleteOperLog,
clearOperLog,
@ -273,10 +269,21 @@ import {
import type { OperLogSearchForm, OperLogVo } from '@/service/api/system/operlog'
import { coiMsgBox, coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks/usePermission'
import { useDict, usePermission } from '@/hooks'
//
const { hasButton } = usePermission()
const { dictOptions } = useDict(['sys_oper_type', 'sys_common_status'])
const operStatusOptions = computed(() => {
const options = dictOptions.sys_common_status || []
return options
.filter(option => option.dictValue === '1' || option.dictValue === '2')
.map(option => ({
label: option.dictLabel,
value: option.dictValue === '1' ? '0' : '1',
}))
})
//
const loading = ref(false)
@ -339,16 +346,9 @@ const columns: DataTableColumns<OperLogVo> = [
{
title: '操作类型',
key: 'operType',
width: 90,
width: 110,
align: 'center',
render: (row) => {
return h(NTag, {
type: 'primary',
size: 'small',
}, {
default: () => row.operType,
})
},
render: row => h(DictTag, { dictType: 'sys_oper_type', value: row.operType }),
},
{
title: '操作人员[登录名/用户名]',
@ -419,15 +419,7 @@ const columns: DataTableColumns<OperLogVo> = [
key: 'operStatus',
width: 90,
align: 'center',
render: (row) => {
const isSuccess = row.operStatus === '0'
return h(NTag, {
type: isSuccess ? 'success' : 'error',
size: 'small',
}, {
default: () => isSuccess ? '操作成功' : '操作失败',
})
},
render: row => h(DictTag, { dictType: 'sys_common_status', value: row.operStatus === '0' ? '1' : '2' }),
},
{
title: '操作时间',

View File

@ -61,10 +61,7 @@
v-model:value="searchForm.roleStatus"
placeholder="请选择角色状态"
clearable
:options="[
{ label: '启用', value: '0' },
{ label: '停用', value: '1' },
]"
:options="getSelectOptions('sys_switch_status')"
/>
</n-form-item>
</n-grid-item>
@ -269,14 +266,15 @@
<n-grid :cols="2" :x-gap="10">
<n-grid-item>
<n-form-item label="角色状态" path="roleStatus" class="mb-2">
<n-select
v-model:value="formData.roleStatus"
placeholder="请选择角色状态"
:options="[
{ label: '启用', value: '0' },
{ label: '停用', value: '1' },
]"
/>
<NRadioGroup v-model:value="formData.roleStatus">
<NRadio
v-for="item in dictOptions.sys_switch_status || []"
:key="item.dictValue"
:value="item.dictValue"
>
{{ item.dictLabel }}
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
<n-grid-item>
@ -420,13 +418,14 @@
<script setup lang="ts">
import { h, nextTick, onMounted, ref, watch } from 'vue'
import type { DataTableColumns, FormInst } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace, NSwitch, NTag, NTree } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NRadio, NRadioGroup, NSpace, NSwitch, NTag, NTree } from 'naive-ui'
import IconParkOutlineEditOne from '~icons/icon-park-outline/edit-one'
import IconParkOutlineDelete from '~icons/icon-park-outline/delete'
import IconParkOutlineKey from '~icons/icon-park-outline/key'
import CoiDialog from '@/components/common/CoiDialog.vue'
import CoiEmpty from '@/components/common/CoiEmpty.vue'
import CoiPagination from '@/components/common/CoiPagination.vue'
import DictTag from '@/components/common/DictTag.vue'
import {
addRole,
batchDeleteRoles,
@ -446,10 +445,11 @@ import {
import type { MenuPermissionData, MenuVo } from '@/service/api/system/menu'
import { coiMsgBox, coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks/usePermission'
import { useDict, usePermission } from '@/hooks'
//
const { hasButton } = usePermission()
const { dictOptions, getSelectOptions, getDictLabel } = useDict(['sys_switch_status'])
//
const loading = ref(false)
@ -546,28 +546,27 @@ const columns: DataTableColumns<RoleVo> = [
key: 'roleCode',
width: 150,
align: 'center',
render: (row) => {
return h(NTag, { type: 'primary', size: 'small' }, { default: () => row.roleCode })
},
render: row => h(NTag, { type: 'primary', size: 'small' }, { default: () => row.roleCode }),
},
{
title: '角色状态',
key: 'roleStatus',
width: 100,
width: 120,
align: 'center',
render: (row) => {
return h('div', { class: 'flex items-center justify-center' }, [
return h('div', { class: 'flex items-center justify-center gap-2' }, [
h(DictTag, { dictType: 'sys_switch_status', value: row.roleStatus }),
h(NPopconfirm, {
onPositiveClick: () => handleToggleStatus(row),
negativeText: '取消',
positiveText: '确定',
}, {
default: () => `确定要${row.roleStatus === '0' ? '停用' : '启用'}角色「${row.roleName}」吗?`,
default: () => `确定要将角色「${row.roleName}」状态切换为「${getDictLabel('sys_switch_status', row.roleStatus === '0' ? '1' : '0')}」吗?`,
trigger: () => h(NSwitch, {
value: row.roleStatus === '0',
size: 'small',
checkedChildren: '启用',
uncheckedChildren: '停用',
checkedChildren: getDictLabel('sys_switch_status', '0', '启用'),
uncheckedChildren: getDictLabel('sys_switch_status', '1', '停用'),
loading: false,
}),
}),
@ -966,7 +965,7 @@ async function handleBatchDelete() {
async function handleToggleStatus(role: RoleVo) {
try {
const newStatus = role.roleStatus === '0' ? '1' : '0'
const statusText = newStatus === '0' ? '启用' : '停用'
const statusText = getDictLabel('sys_switch_status', newStatus, newStatus === '0' ? '启用' : '停用')
const { isSuccess } = await updateRoleStatus(role.roleId, newStatus)
if (isSuccess) {

View File

@ -72,10 +72,7 @@
v-model:value="searchForm.userStatus"
placeholder="请选择用户状态"
clearable
:options="[
{ label: '启用', value: '0' },
{ label: '停用', value: '1' },
]"
:options="getSelectOptions('sys_switch_status')"
/>
</n-form-item>
</n-grid-item>
@ -313,11 +310,7 @@
<n-select
v-model:value="formData.userType"
placeholder="请选择用户类型"
:options="[
{ label: '系统用户', value: '1' },
{ label: '注册用户', value: '2' },
{ label: '微信用户', value: '3' },
]"
:options="getSelectOptions('sys_user_type')"
/>
</n-form-item>
</n-grid-item>
@ -327,11 +320,7 @@
<n-select
v-model:value="formData.sex"
placeholder="请选择性别"
:options="[
{ label: '男', value: '1' },
{ label: '女', value: '2' },
{ label: '未知', value: '3' },
]"
:options="getSelectOptions('sys_user_sex')"
/>
</n-form-item>
</n-grid-item>
@ -367,14 +356,15 @@
<n-grid-item>
<n-form-item label="用户状态" path="userStatus" class="mb-2">
<n-radio-group v-model:value="formData.userStatus">
<n-radio value="0">
启用
</n-radio>
<n-radio value="1">
停用
</n-radio>
</n-radio-group>
<NRadioGroup v-model:value="formData.userStatus">
<NRadio
v-for="item in dictOptions.sys_switch_status || []"
:key="item.dictValue"
:value="item.dictValue"
>
{{ item.dictLabel }}
</NRadio>
</NRadioGroup>
</n-form-item>
</n-grid-item>
@ -585,11 +575,8 @@
{{ currentAvatarUser?.avatar ? '用户头像' : '默认头像' }}
</p>
<div class="flex items-center justify-center gap-4 text-xs text-gray-400">
<span>用户类型: {{
currentAvatarUser?.userType === '1' ? '系统用户'
: currentAvatarUser?.userType === '2' ? '注册用户' : '微信用户'
}}</span>
<span>状态: {{ currentAvatarUser?.userStatus === '0' ? '启用' : '停用' }}</span>
<span>用户类型: {{ getDictLabel('sys_user_type', currentAvatarUser?.userType, '--') }}</span>
<span>状态: {{ getDictLabel('sys_switch_status', currentAvatarUser?.userStatus, '--') }}</span>
</div>
</div>
</div>
@ -704,7 +691,7 @@
<script setup lang="ts">
import { h, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import type { DataTableColumns, FormInst } from 'naive-ui'
import { NButton, NCheckbox, NDropdown, NIcon, NPopconfirm, NProgress, NSpace, NSwitch, NTag, NUpload, NUploadDragger } from 'naive-ui'
import { NButton, NCheckbox, NDropdown, NIcon, NPopconfirm, NProgress, NRadio, NRadioGroup, NSpace, NSwitch, NTag, NUpload, NUploadDragger } from 'naive-ui'
import IconParkOutlineEditOne from '~icons/icon-park-outline/edit-one'
import IconParkOutlineDelete from '~icons/icon-park-outline/delete'
import IconParkOutlineRefresh from '~icons/icon-park-outline/refresh'
@ -715,6 +702,7 @@ import IconParkOutlineFileCodeOne from '~icons/icon-park-outline/file-code-one'
import CoiDialog from '@/components/common/CoiDialog.vue'
import CoiEmpty from '@/components/common/CoiEmpty.vue'
import CoiPagination from '@/components/common/CoiPagination.vue'
import DictTag from '@/components/common/DictTag.vue'
import {
addUser,
batchDeleteUsers,
@ -739,7 +727,7 @@ import {
import type { RoleVo } from '@/service/api/system/role'
import { coiMsgBox, coiMsgError, coiMsgInfo, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks/usePermission'
import { useDict, usePermission } from '@/hooks'
//
const { hasButton } = usePermission()
@ -790,6 +778,12 @@ const uploadProgress = ref(0)
const progressInterval = ref<NodeJS.Timeout | null>(null)
const createdBlobUrls = ref<string[]>([])
const { dictOptions, getSelectOptions, getDictLabel } = useDict([
'sys_user_type',
'sys_user_sex',
'sys_switch_status',
])
//
const pagination = ref({
page: 1,
@ -956,33 +950,14 @@ const columns: DataTableColumns<UserVo> = [
key: 'userType',
width: 100,
align: 'center',
render: (row) => {
const typeMap: Record<string, { label: string, type: any }> = {
1: { label: '系统用户', type: 'primary' },
2: { label: '注册用户', type: 'info' },
3: { label: '微信用户', type: 'warning' },
}
const config = typeMap[row.userType] || { label: '未知', type: 'default' }
return h(NTag, { type: config.type, size: 'small' }, { default: () => config.label })
},
render: row => h(DictTag, { dictType: 'sys_user_type', value: row.userType }),
},
{
title: '性别',
key: 'sex',
width: 80,
align: 'center',
render: (row) => {
const sexMap: Record<string, { label: string, icon: string, color: string }> = {
1: { label: '男', icon: '♂', color: 'text-blue-500' },
2: { label: '女', icon: '♀', color: 'text-pink-500' },
3: { label: '未知', icon: '?', color: 'text-gray-400' },
}
const config = sexMap[row.sex || '3']
return h('div', { class: `flex items-center justify-center gap-1 ${config.color}` }, [
h('span', { class: 'text-lg' }, config.icon),
h('span', { class: 'text-xs' }, config.label),
])
},
render: row => h(DictTag, { dictType: 'sys_user_sex', value: row.sex }),
},
{
title: '用户状态',
@ -990,18 +965,21 @@ const columns: DataTableColumns<UserVo> = [
width: 100,
align: 'center',
render: (row) => {
const nextStatus = row.userStatus === '0' ? '1' : '0'
const enableLabel = getDictLabel('sys_switch_status', '0', '启用')
const disableLabel = getDictLabel('sys_switch_status', '1', '停用')
return h('div', { class: 'flex items-center justify-center' }, [
h(NPopconfirm, {
onPositiveClick: () => handleToggleStatus(row),
negativeText: '取消',
positiveText: '确定',
}, {
default: () => `确定要${row.userStatus === '0' ? '停用' : '启用'}用户「${row.userName}」吗?`,
default: () => `确定要将用户「${row.userName}」状态切换为「${getDictLabel('sys_switch_status', nextStatus)}」吗?`,
trigger: () => h(NSwitch, {
value: row.userStatus === '0',
size: 'small',
checkedChildren: '启用',
uncheckedChildren: '停用',
checkedChildren: enableLabel,
uncheckedChildren: disableLabel,
loading: false,
}),
}),
@ -1357,7 +1335,7 @@ async function handleBatchDelete() {
async function handleToggleStatus(user: UserVo) {
try {
const newStatus = user.userStatus === '0' ? '1' : '0'
const statusText = newStatus === '0' ? '启用' : '停用'
const statusText = getDictLabel('sys_switch_status', newStatus, newStatus === '0' ? '启用' : '停用')
const { isSuccess } = await updateUserStatus(user.userId, newStatus)
if (isSuccess) {