Преглед изворни кода

feat(系统模块): 添加在线用户功能

shizhongming пре 2 година
родитељ
комит
b0ec251034

+ 24 - 0
src/components/SmartTable/src/utils/TableCommon.tsx

@@ -34,6 +34,30 @@ export const tableBooleanColumn = (t: Function, title: string, field: string) =>
   };
 };
 
+export const tableBooleanColumnClass = (title: string, field: string) => {
+  const { t } = useI18n();
+
+  return {
+    title: title,
+    field: title,
+    width: 100,
+    formatter: ({ row }) => {
+      const value = row[field] as boolean | null;
+      if (value === null) {
+        return '';
+      }
+      return value ? t('common.form.yes') : t('common.form.no');
+    },
+    dynamicClass: ({ row }) => {
+      const value = row[field] as boolean | null;
+      if (value === null) {
+        return '';
+      }
+      return value ? 'text-color--success-bold' : 'text-color--danger-bold';
+    },
+  };
+};
+
 const tableDeleteYn = (t: Function) => {
   const createSlot = ({ row }: any) => {
     const value = row.deleteYn;

+ 21 - 0
src/modules/system/views/onlineUser/OnlineUserListView.api.ts

@@ -0,0 +1,21 @@
+import { ApiServiceEnum, defHttp } from '@/utils/http/axios';
+
+enum Api {
+  listOnlineUser = 'auth/listOnlineUser',
+  offline = 'auth/offline',
+}
+
+export const listOnlineUserApi = (params) =>
+  defHttp.post({
+    service: ApiServiceEnum.SMART_AUTH,
+    url: Api.listOnlineUser,
+    data: params,
+  });
+
+export const offlineApi = (username, token) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_AUTH,
+    url: Api.offline,
+    data: { username, token },
+  });
+};

+ 99 - 0
src/modules/system/views/onlineUser/OnlineUserListView.config.ts

@@ -0,0 +1,99 @@
+import {
+  type SmartColumn,
+  type SmartSearchFormSchema,
+  tableBooleanColumnClass,
+} from '@/components/SmartTable';
+
+export const getTableColumns = (): SmartColumn[] => {
+  return [
+    {
+      title: '#',
+      type: 'expand',
+      fixed: 'left',
+      width: 80,
+      slots: {
+        content: 'table-expand',
+      },
+    },
+    {
+      title: '{system.views.user.table.username}',
+      field: 'username',
+      width: 120,
+      fixed: 'left',
+    },
+    {
+      title: '{system.views.user.table.fullName}',
+      field: 'fullName',
+      width: 120,
+      fixed: 'left',
+    },
+    {
+      title: '{system.views.user.table.email}',
+      field: 'email',
+      minWidth: 160,
+    },
+    {
+      title: '{system.views.user.table.mobile}',
+      field: 'mobile',
+      minWidth: 140,
+    },
+    {
+      title: '{common.table.operation}',
+      field: 'operation',
+      width: 120,
+      fixed: 'right',
+      slots: {
+        default: 'table-operation',
+      },
+    },
+  ];
+};
+
+export const getTableExpandColumns = (): SmartColumn[] => {
+  return [
+    {
+      title: '{system.views.onlineUser.title.authType}',
+      field: 'authType',
+      width: 120,
+    },
+    {
+      title: '{system.views.onlineUser.title.loginType}',
+      field: 'loginType',
+      width: 120,
+    },
+    {
+      title: '{system.views.onlineUser.title.loginTime}',
+      field: 'loginTime',
+      sortable: true,
+      width: 170,
+    },
+    {
+      title: '{system.views.onlineUser.title.loginIp}',
+      field: 'loginIp',
+      minWidth: 200,
+    },
+    {
+      ...tableBooleanColumnClass('{system.views.onlineUser.title.bindIp}', 'bindIp'),
+      width: 120,
+    },
+    {
+      title: '{common.table.operation}',
+      field: 'operation',
+      width: 120,
+      fixed: 'right',
+      slots: {
+        default: 'expand-table-operation',
+      },
+    },
+  ];
+};
+
+export const getSearchFormSchemas = (t: Function): SmartSearchFormSchema[] => {
+  return [
+    {
+      label: t('system.views.user.table.username'),
+      field: 'username',
+      component: 'Input',
+    },
+  ];
+};

+ 113 - 0
src/modules/system/views/onlineUser/OnlineUserListView.vue

@@ -0,0 +1,113 @@
+<template>
+  <div class="full-height page-container">
+    <SmartTable :size="getTableSize" @register="registerTable">
+      <template #table-expand="{ row }">
+        <SmartTable
+          :size="getTableSize"
+          class="expand-wrapper"
+          :data="row.userLoginDataList"
+          @register="registerExpandTable"
+        >
+          <template #expand-table-operation="data">
+            <SmartVxeTableAction :actions="getTableActions(data.row, true)" />
+          </template>
+        </SmartTable>
+      </template>
+      <template #table-operation="{ row }">
+        <SmartVxeTableAction :actions="getTableActions(row, false)" />
+      </template>
+    </SmartTable>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import type { ActionItem } from '@/components/SmartTable';
+
+  import { useI18n } from '@/hooks/web/useI18n';
+  import { useSmartTable, SmartTable, SmartVxeTableAction } from '@/components/SmartTable';
+  import { useSizeSetting } from '@/hooks/setting/UseSizeSetting';
+  import { message, Modal } from 'ant-design-vue';
+  import { createVNode } from 'vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
+
+  import {
+    getTableColumns,
+    getTableExpandColumns,
+    getSearchFormSchemas,
+  } from './OnlineUserListView.config';
+  import { listOnlineUserApi, offlineApi } from './OnlineUserListView.api';
+
+  const { t } = useI18n();
+  const { getTableSize } = useSizeSetting();
+
+  const getTableActions = (row, isExpand: boolean): ActionItem[] => {
+    return [
+      {
+        label: t('system.views.onlineUser.button.offline'),
+        auth: 'sys:auth:offline',
+        danger: true,
+        onClick: () => {
+          handleOffline(isExpand ? null : row.username, isExpand ? row.token : null);
+        },
+      },
+    ];
+  };
+
+  /**
+   * 执行登出操作
+   * @param username 用户名
+   * @param token token
+   */
+  const handleOffline = (username?: string, token?: string) => {
+    Modal.confirm({
+      title: t('common.notice.confirm'),
+      icon: createVNode(ExclamationCircleOutlined),
+      content: t('system.views.onlineUser.message.offlineConfirm'),
+      onOk: async () => {
+        await offlineApi(username, token);
+        message.success(t('system.views.onlineUser.message.offlineSuccess'));
+        reload();
+      },
+    });
+  };
+
+  const [registerTable, { reload }] = useSmartTable({
+    border: true,
+    height: 'auto',
+    highlightHoverRow: true,
+    columns: getTableColumns(),
+    useSearchForm: true,
+    searchFormConfig: {
+      layout: 'inline',
+      schemas: getSearchFormSchemas(t),
+      colon: true,
+      actionColOptions: {
+        span: undefined,
+      },
+      compact: true,
+    },
+    proxyConfig: {
+      ajax: {
+        query: ({ ajaxParameter }) => listOnlineUserApi(ajaxParameter),
+      },
+    },
+    columnConfig: {
+      resizable: true,
+    },
+    toolbarConfig: {
+      refresh: true,
+    },
+  });
+
+  const [registerExpandTable] = useSmartTable({
+    columns: getTableExpandColumns(),
+    border: true,
+    stripe: true,
+  });
+</script>
+
+<style scoped lang="less">
+  .expand-wrapper {
+    padding: 15px;
+  }
+</style>

+ 22 - 0
src/modules/system/views/onlineUser/lang/en_US.ts

@@ -0,0 +1,22 @@
+export default {
+  system: {
+    views: {
+      onlineUser: {
+        title: {
+          authType: 'Auth type',
+          loginType: 'Login type',
+          loginTime: 'Login time',
+          loginIp: 'Login IP',
+          bindIp: 'Bind IP',
+        },
+        button: {
+          offline: 'Offline',
+        },
+        message: {
+          offlineConfirm: 'Are you sure you want to go offline?',
+          offlineSuccess: 'Offline success',
+        },
+      },
+    },
+  },
+};

+ 22 - 0
src/modules/system/views/onlineUser/lang/zh_CN.ts

@@ -0,0 +1,22 @@
+export default {
+  system: {
+    views: {
+      onlineUser: {
+        title: {
+          authType: '认证类型',
+          loginType: '登录类型',
+          loginTime: '登录时间',
+          loginIp: '登录IP',
+          bindIp: '是否绑定IP',
+        },
+        button: {
+          offline: '下线',
+        },
+        message: {
+          offlineConfirm: '确定要下线吗?',
+          offlineSuccess: '下线成功',
+        },
+      },
+    },
+  },
+};