✨ feat: 获取Redis中活跃用户
This commit is contained in:
parent
88857fd01d
commit
42647df377
|
@ -261,7 +261,7 @@ docker compose up -d
|
|||
- [x] 系统监控后端返回403停止请求
|
||||
- [x] 优化用户配置权限逻辑,配置后热更新逻辑等
|
||||
- [x] 完善后端注释,有需要添加ReadMe文档
|
||||
- [ ] Redis中获取活跃用户
|
||||
- [x] 获取Redis中活跃用户
|
||||
|
||||
## 前后端接口规范
|
||||
|
||||
|
|
|
@ -110,3 +110,8 @@ export const updateUserinfo = (data: any) => {
|
|||
export const updateUserPassword = (data: any) => {
|
||||
return http.request<BaseResult<object>>('put', 'user/private/update/password', { data }, { headers: { 'Content-Type': 'multipart/form-data' } });
|
||||
};
|
||||
|
||||
/* 查询缓存中的已登录的用户 */
|
||||
export const getCacheLoggedInPage = (data: any) => {
|
||||
return http.request<BaseResult<any>>('get', `user/getCacheUserPage/${data.currentPage}/${data.pageSize}`, { data });
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { loadUserinfoById } from '@/api/v1/system/adminUser';
|
||||
import userAvatarIcon from '@/assets/svg/user_avatar.svg?component';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
userId: { type: String as PropType<String> },
|
||||
|
@ -60,8 +60,8 @@ onMounted(() => {
|
|||
<el-descriptions-item :label="$t('email')">{{ userinfo.email }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('phone')">{{ userinfo.phone }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('sex')">
|
||||
<el-tag v-if="userinfo.sex === 1">男</el-tag>
|
||||
<el-tag v-if="userinfo.sex === 0" type="danger">女</el-tag>
|
||||
<el-tag v-if="userinfo.sex === 1">{{ $t('man') }}</el-tag>
|
||||
<el-tag v-if="userinfo.sex === 0" type="danger">{{ $t('female') }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
|
||||
<el-descriptions-item :label="$t('personDescription')" span="3">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import UserinfoDialog from '@/components/Table/Userinfo/UserinfoDialog.vue';
|
||||
import { addDialog } from '@/components/ReDialog/index';
|
||||
import UserinfoDialog from '@/components/Table/Userinfo/UserinfoDialog.vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
|
||||
/**
|
||||
* * 查看用户信息
|
||||
|
@ -7,7 +8,7 @@ import { addDialog } from '@/components/ReDialog/index';
|
|||
*/
|
||||
export const selectUserinfo = async (userId: string) => {
|
||||
addDialog({
|
||||
title: '查看用户信息',
|
||||
title: $t('view_user_info'),
|
||||
draggable: true,
|
||||
contentRenderer: (): JSX.Element => <UserinfoDialog userId={userId} />,
|
||||
});
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { pageSizes } from '@/enums/baseConstant';
|
||||
import { getCacheLoggedInPage } from '@/api/v1/system/adminUser';
|
||||
import { storePagination } from '@/store/useStorePagination';
|
||||
|
||||
export const useLoggedInStore = defineStore('loggedInStore', {
|
||||
state() {
|
||||
return {
|
||||
datalist: [],
|
||||
loading: false,
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 30,
|
||||
total: 1,
|
||||
pageSizes,
|
||||
},
|
||||
};
|
||||
},
|
||||
getters: {},
|
||||
actions: {
|
||||
/* 查詢已登錄用戶 */
|
||||
async fetchLoggedInPage() {
|
||||
// 整理请求参数
|
||||
const data = { ...this.pagination };
|
||||
delete data.pageSizes;
|
||||
delete data.total;
|
||||
|
||||
// 获取调度任务执行日志列表
|
||||
const result = await getCacheLoggedInPage(data);
|
||||
|
||||
// 公共页面函数hook
|
||||
const pagination = storePagination.bind(this);
|
||||
return pagination(result);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -46,7 +46,6 @@ export const useQuartzExecuteLogStore = defineStore('quartzExecuteLogStore', {
|
|||
const data = { ...this.pagination, ...this.form };
|
||||
delete data.pageSizes;
|
||||
delete data.total;
|
||||
delete data.background;
|
||||
|
||||
// 获取调度任务执行日志列表
|
||||
const result = await getScheduleExecuteLogPage(data);
|
||||
|
|
|
@ -10,7 +10,7 @@ import AccountManagementIcon from '~icons/ri/profile-line';
|
|||
import AccountManagement from '@/views/account-settings/components/account-management.vue';
|
||||
|
||||
export const columns: TableColumnList = [
|
||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
||||
{ type: 'index', index: (index: number) => index + 1, label: $t("index"), width: 60 },
|
||||
// 用户名
|
||||
{ label: $t('userLoginLog_username'), prop: 'username', width: 180 },
|
||||
// 登录Ip
|
||||
|
|
|
@ -8,7 +8,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 模板名称
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 邮箱
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// icon 类名
|
||||
|
|
|
@ -8,7 +8,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
{ label: $t('i18n.keyName'), prop: 'keyName' },
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
{ label: $t('i18n_typeName'), prop: 'typeName' },
|
||||
|
|
|
@ -21,9 +21,9 @@ const timer = ref(null);
|
|||
const { t } = useI18n();
|
||||
|
||||
const ruleForm = reactive({
|
||||
username: '1319900154@qq.com',
|
||||
username: 'admin@qq.com',
|
||||
password: 'admin123',
|
||||
emailCode: '1',
|
||||
emailCode: '',
|
||||
type: currentPage.value,
|
||||
});
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { getTopMenu, initRouter } from '@/router/utils';
|
|||
import Motion from '../utils';
|
||||
import { ElMessage, FormInstance } from 'element-plus';
|
||||
import { currentPage, formRules } from '@/views/login/utils';
|
||||
import { $t } from '../../../plugins/i18n';
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
@ -93,7 +94,7 @@ onBeforeUnmount(() => {
|
|||
<!-- 邮箱登录 -->
|
||||
<Motion :delay="300">
|
||||
<el-form-item>
|
||||
<el-button class="w-full" size="default" @click="currentPage = 'email'">邮箱登录</el-button>
|
||||
<el-button class="w-full" size="default" @click="currentPage = 'email'">{{ $t('email_login') }}</el-button>
|
||||
</el-form-item>
|
||||
</Motion>
|
||||
</el-form>
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 消息标题
|
||||
|
|
|
@ -8,7 +8,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 消息标题
|
||||
|
|
|
@ -8,7 +8,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 是否启用
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<script lang="ts" setup>
|
||||
import { useLoggedInStore } from '@/store/monitor/loggedIn';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { PureTableBar } from '@/components/RePureTableBar';
|
||||
import PureTable from '@pureadmin/table';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { columns } from '@/views/monitor/logged-in/utils/columns';
|
||||
import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
||||
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
||||
import Airplane from '@/assets/svg/airplane.svg';
|
||||
import { onForcedOffline } from '@/views/system/admin-user/utils';
|
||||
|
||||
const tableRef = ref();
|
||||
const loggedInStore = useLoggedInStore();
|
||||
const { datalist, loading, pagination } = storeToRefs(loggedInStore);
|
||||
|
||||
const onSearch = async () => {
|
||||
loggedInStore.loading = true;
|
||||
await loggedInStore.fetchLoggedInPage();
|
||||
loggedInStore.loading = false;
|
||||
};
|
||||
|
||||
/** 当前页改变时 */
|
||||
const onCurrentPageChange = async (value: number) => {
|
||||
loggedInStore.pagination.currentPage = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/** 当分页发生变化 */
|
||||
const onPageSizeChange = async (value: number) => {
|
||||
loggedInStore.pagination.pageSize = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<PureTableBar :columns="columns" :title="$t('logged_in_user')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||
<template v-slot="{ size, dynamicColumns }">
|
||||
<pure-table
|
||||
ref="tableRef"
|
||||
:adaptiveConfig="{ offsetBottom: 96 }"
|
||||
:columns="dynamicColumns"
|
||||
:data="datalist"
|
||||
:header-cell-style="{
|
||||
background: 'var(--el-fill-color-light)',
|
||||
color: 'var(--el-text-color-primary)',
|
||||
}"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:size="size"
|
||||
adaptive
|
||||
align-whole="center"
|
||||
border
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
showOverflowTooltip
|
||||
table-layout="auto"
|
||||
@page-size-change="onPageSizeChange"
|
||||
@page-current-change="onCurrentPageChange"
|
||||
>
|
||||
<template #username="{ row }">
|
||||
<el-button v-show="row.username" link type="primary" @click="selectUserinfo(row.createUser)">
|
||||
{{ row.username }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<template #operation="{ row }">
|
||||
<el-button :icon="useRenderIcon(Airplane)" :size="size" link type="primary" @click="onForcedOffline(row)">
|
||||
{{ $t('forced_offline') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,25 @@
|
|||
import { $t } from '@/plugins/i18n';
|
||||
|
||||
export const columns: TableColumnList = [
|
||||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
{ label: $t('adminUser_nickname'), prop: 'nickname', minWidth: 120 },
|
||||
{ label: $t('adminUser_username'), prop: 'username', slot: 'username', minWidth: 120 },
|
||||
{ label: $t('adminUser_email'), prop: 'email', minWidth: 120 },
|
||||
{ label: $t('adminUser_phone'), prop: 'phone', minWidth: 120 },
|
||||
{ label: $t('adminUser_summary'), prop: 'personDescription', minWidth: 150 },
|
||||
{ label: $t('lastLoginIp'), prop: 'ipAddress', minWidth: 100 },
|
||||
{ label: $t('lastLoginIpAddress'), prop: 'ipRegion', minWidth: 100 },
|
||||
{ label: $t('expires'), prop: 'expires', minWidth: 120 },
|
||||
{ label: $t('readMeDay'), prop: 'readMeDay', width: 100 },
|
||||
{
|
||||
label: $t('table.operation'),
|
||||
fixed: 'right',
|
||||
width: 120,
|
||||
slot: 'operation',
|
||||
},
|
||||
];
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 任务名称
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 用户名
|
||||
|
|
|
@ -7,7 +7,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 分组名称
|
||||
|
|
|
@ -6,7 +6,7 @@ export const columns: TableColumnList = [
|
|||
{
|
||||
type: 'index',
|
||||
index: (index: number) => index + 1,
|
||||
label: '序号',
|
||||
label: $t("index"),
|
||||
width: 60,
|
||||
},
|
||||
// 任务名称
|
||||
|
|
|
@ -18,7 +18,7 @@ export async function onSearch() {
|
|||
}
|
||||
|
||||
/** 添加部门 */
|
||||
export function onAdd(parentId: number = 0) {
|
||||
export function onAdd(parentId: string = '0') {
|
||||
addDialog({
|
||||
title: `${$t('addNew')}${$t('dept')}`,
|
||||
props: {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue';
|
|||
import { FormInstance, genFileId, UploadProps, UploadRawFile } from 'element-plus';
|
||||
import { addRules, FormProps, uploadRules } from '@/views/system/files/utils';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { useFilesStore } from '@/store/monitor/files';
|
||||
import { useFilesStore } from '@/store/system/files';
|
||||
import { UploadFilled } from '@element-plus/icons-vue';
|
||||
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
|
@ -28,10 +28,7 @@ const upload = ref();
|
|||
const form = ref(props.formInline);
|
||||
const filesStore = useFilesStore();
|
||||
|
||||
/**
|
||||
* * 修改时替换之前文件
|
||||
* @param files
|
||||
*/
|
||||
/* 修改时替换之前文件 */
|
||||
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||
upload.value!.clearFiles();
|
||||
const file = files[0] as UploadRawFile;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { PureTableBar } from '@/components/RePureTableBar';
|
|||
import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
import { useFilesStore } from '@/store/monitor/files';
|
||||
import { useFilesStore } from '@/store/system/files';
|
||||
import { auth, columns, onAdd, onDelete, onDeleteBatch, onDownload, onDownloadBatch, onSearch, onUpdate, selectRows } from '@/views/system/files/utils';
|
||||
import PureTable from '@pureadmin/table';
|
||||
import { FormInstance } from 'element-plus';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { addDialog } from '@/components/ReDialog/index';
|
||||
import FilesDialog from '@/views/system/files/components/files-dialog.vue';
|
||||
import { useFilesStore } from '@/store/monitor/files';
|
||||
import { h, ref, VNode } from 'vue';
|
||||
import { useFilesStore } from '@/store/system/files';
|
||||
import { h, ref } from 'vue';
|
||||
import { messageBox } from '@/utils/message';
|
||||
import type { FormItemProps } from '@/views/system/files/utils/types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
|
@ -11,7 +11,7 @@ import type { UploadFiles } from 'element-plus';
|
|||
|
||||
// 选择的row列表
|
||||
export const selectRows = ref([]);
|
||||
export const formRef = ref<VNode | null>(null);
|
||||
export const formRef = ref();
|
||||
const filesStore = useFilesStore();
|
||||
|
||||
/** 搜索初始化系统文件 */
|
||||
|
@ -28,17 +28,29 @@ export function onAdd() {
|
|||
|
||||
props: {
|
||||
formInline: {
|
||||
filename: undefined,
|
||||
fileType: undefined,
|
||||
filepath: undefined,
|
||||
downloadCount: 0,
|
||||
files: [],
|
||||
isAdd: false,
|
||||
isUpload: false,
|
||||
},
|
||||
},
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => {
|
||||
const dialog = h(FilesDialog, {}, []);
|
||||
const dialog = h(FilesDialog, {
|
||||
ref: formRef,
|
||||
formInline: {
|
||||
filename: undefined,
|
||||
fileType: undefined,
|
||||
filepath: undefined,
|
||||
downloadCount: 0,
|
||||
files: [],
|
||||
isUpload: false,
|
||||
},
|
||||
});
|
||||
formRef.value = dialog;
|
||||
return dialog;
|
||||
},
|
||||
|
@ -83,7 +95,17 @@ export function onUpdate(row: any) {
|
|||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => {
|
||||
const dialog = h(FilesDialog, { ref: formRef }, []);
|
||||
const dialog = h(FilesDialog, {
|
||||
ref: formRef,
|
||||
formInline: {
|
||||
filename: row.filename,
|
||||
fileType: row.fileType,
|
||||
filepath: row.filepath,
|
||||
downloadCount: row.downloadCount,
|
||||
isUpload: true,
|
||||
files: undefined,
|
||||
},
|
||||
});
|
||||
formRef.value = dialog;
|
||||
return dialog;
|
||||
},
|
||||
|
|
|
@ -40,8 +40,8 @@ function onAdd(parentId: any = 0) {
|
|||
icon: '',
|
||||
id: '',
|
||||
extraIcon: '',
|
||||
enterTransition: 'fade-transform',
|
||||
leaveTransition: 'fade-transform',
|
||||
enterTransition: '',
|
||||
leaveTransition: '',
|
||||
activePath: '',
|
||||
redirect: '',
|
||||
roles: [],
|
||||
|
@ -58,7 +58,35 @@ function onAdd(parentId: any = 0) {
|
|||
draggable: true,
|
||||
closeOnClickModal: false,
|
||||
fullscreenIcon: true,
|
||||
contentRenderer: () => h(EditForm, { ref: dialogFormRef }),
|
||||
contentRenderer: () =>
|
||||
h(EditForm, {
|
||||
ref: dialogFormRef,
|
||||
formInline: {
|
||||
menuType: 0,
|
||||
higherMenuOptions: formatHigherMenuOptions(cloneDeep(menuStore.datalist)),
|
||||
parentId,
|
||||
title: '',
|
||||
name: '',
|
||||
path: '',
|
||||
component: '',
|
||||
rank: 99,
|
||||
icon: '',
|
||||
id: '',
|
||||
extraIcon: '',
|
||||
enterTransition: '',
|
||||
leaveTransition: '',
|
||||
activePath: '',
|
||||
redirect: '',
|
||||
roles: [],
|
||||
frameSrc: '',
|
||||
frameLoading: true,
|
||||
keepAlive: false,
|
||||
hiddenTag: false,
|
||||
fixedTag: false,
|
||||
showLink: true,
|
||||
showParent: true,
|
||||
},
|
||||
}),
|
||||
beforeSure: (done, { options }) => {
|
||||
const menuFormRef = dialogFormRef.value.menuFormRef;
|
||||
const curData = options.props.formInline as FormItemProps;
|
||||
|
@ -115,7 +143,36 @@ function onUpdate(row?: FormItemProps) {
|
|||
fullscreen: deviceDetection(),
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => h(EditForm, { ref: dialogFormRef }),
|
||||
contentRenderer: () =>
|
||||
h(EditForm, {
|
||||
ref: dialogFormRef,
|
||||
formInline: {
|
||||
id: row?.id,
|
||||
menuType: row?.menuType,
|
||||
higherMenuOptions: formatHigherMenuOptions(cloneDeep(menuStore.datalist)),
|
||||
parentId: row?.parentId,
|
||||
title: row?.title,
|
||||
name: row?.name,
|
||||
path: row?.path,
|
||||
component: row?.component,
|
||||
rank: row?.rank,
|
||||
icon: row?.icon,
|
||||
frameSrc: row?.frameSrc,
|
||||
extraIcon: row?.extraIcon,
|
||||
// 因为要使用动画需要在前面加上 animate__ 修改时需要手动去除
|
||||
enterTransition: row?.enterTransition?.replace('animate__', ''),
|
||||
// 因为要使用动画需要在前面加上 animate__ 修改时需要手动去除
|
||||
leaveTransition: row?.leaveTransition?.replace('animate__', ''),
|
||||
activePath: row?.activePath,
|
||||
frameLoading: row?.frameLoading,
|
||||
keepAlive: row?.keepAlive,
|
||||
hiddenTag: row?.hiddenTag,
|
||||
fixedTag: row?.fixedTag,
|
||||
showLink: row?.showLink,
|
||||
showParent: row?.showParent,
|
||||
redirect: row?.redirect,
|
||||
},
|
||||
}),
|
||||
beforeSure: (done, { options }) => {
|
||||
const menuFormRef = dialogFormRef.value.menuFormRef;
|
||||
const curData = options.props.formInline as FormItemProps;
|
||||
|
|
|
@ -175,7 +175,7 @@ onMounted(() => {
|
|||
</el-button>
|
||||
|
||||
<el-dropdown v-if="hasAuth(auth.update)" class="ml-1" type="primary">
|
||||
<el-button :icon="useRenderIcon(More)" plain type="primary">更多操作</el-button>
|
||||
<el-button :icon="useRenderIcon(More)" plain type="primary">{{ $t('more_actions') }}</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<!-- 批量更新父级id -->
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
export const auth = {
|
||||
// 分页查询
|
||||
query: ['power::query', 'power::queryPage'],
|
||||
query: 'permission::page',
|
||||
// // 添加操作
|
||||
add: ['power::addPower'],
|
||||
add: ['permission::add'],
|
||||
// 更新操作
|
||||
update: ['power::updatePower'],
|
||||
update: ['permission::update'],
|
||||
// 删除操作
|
||||
delete: ['power::delete'],
|
||||
delete: ['permission::delete'],
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue