zouzs преди 2 седмици
родител
ревизия
5d51768265
променени са 3 файла, в които са добавени 407 реда и са изтрити 4 реда
  1. 50 0
      src/api/system/logininfor.ts
  2. 351 0
      src/views/system/logininfor/index.vue
  3. 6 4
      src/views/system/operlog/index.vue

+ 50 - 0
src/api/system/logininfor.ts

@@ -0,0 +1,50 @@
+import { http } from "@/utils/http";
+import { baseUrlApi } from "../utils";
+
+export interface operlogList<T = any> {
+  code: number;
+  msg: string;
+  rows: T;
+  total?: number;
+}
+
+export interface BasicResponseModel<T = any> {
+  code: number;
+  msg: string;
+  data: T;
+}
+
+/**
+ * 获取登录日志列表
+ * @param query
+ */
+export const getSystemLogininforList = (query?: object) => {
+  return http.request<operlogList>(
+    "get",
+    baseUrlApi("system/logininfor/list"),
+    {
+      params: query
+    }
+  );
+};
+
+/**
+ * 删除登录日志
+ * @param id
+ */
+export const deleteSystemLogininfor = (id: string) => {
+  return http.request<BasicResponseModel>(
+    "delete",
+    baseUrlApi(`system/logininfor/${id}`)
+  );
+};
+
+/**
+ * 清空登录日志
+ */
+export const cleanSystemLogininfor = () => {
+  return http.request<BasicResponseModel>(
+    "delete",
+    baseUrlApi("system/logininfor/clean")
+  );
+};

+ 351 - 0
src/views/system/logininfor/index.vue

@@ -0,0 +1,351 @@
+<script setup lang="ts">
+import {
+  type PlusColumn,
+  type OptionsRow,
+  PlusPage,
+  PlusDialog,
+  PlusDescriptions,
+  PlusPageInstance,
+  useTable
+} from "plus-pro-components";
+import { computed, reactive, type Ref, ref, toRefs } from "vue";
+import { useDict, useDictValue } from "@/utils/dict";
+import { ElMessage, ElMessageBox } from "element-plus";
+import {
+  cleanSystemLogininfor,
+  deleteSystemLogininfor,
+  getSystemLogininforList
+} from "@/api/system/logininfor";
+
+defineOptions({
+  name: "Logininfor"
+});
+
+const { sys_common_status } = useDict("sys_common_status", "sys_oper_type");
+
+const plusPageInstance = ref<PlusPageInstance | null>(null);
+
+const getList = async (query: Record<string, any>) => {
+  let res = await getSystemLogininforList(query);
+  return {
+    data: res.rows,
+    total: res.total
+  };
+};
+
+// 重新请求列表接口
+const refresh = () => {
+  plusPageInstance.value?.getList();
+};
+
+const tableConfig: PlusColumn[] = [
+  {
+    label: "访问编号",
+    prop: "infoId",
+    valueType: "input",
+    hideInSearch: true
+  },
+  {
+    label: "用户名称",
+    prop: "userName",
+    valueType: "input"
+  },
+  {
+    label: "地址",
+    prop: "ipaddr",
+    valueType: "input",
+    hideInSearch: true
+  },
+  {
+    label: "登录状态",
+    prop: "status",
+    valueType: "tag",
+    options: computed(() => sys_common_status.value),
+    fieldProps: value => {
+      return {
+        type: sys_common_status.value.find(
+          (item: Ref) => item.value === value + ""
+        )?.class
+      };
+    },
+    formatter: (value, { column }) => {
+      return (column.options as OptionsRow[])?.find(
+        item => item.value === value + ""
+      )?.label;
+    },
+    hideInSearch: true
+  },
+  {
+    label: "登录状态",
+    prop: "status",
+    valueType: "select",
+    options: computed(() => sys_common_status.value),
+    hideInTable: true
+  },
+  {
+    label: "描述",
+    prop: "msg",
+    valueType: "input",
+    hideInSearch: true
+  },
+  {
+    label: "登录时间",
+    prop: "accessTime",
+    valueType: "date-picker",
+    fieldProps: {
+      type: "datetime",
+      rangeSeparator: "至",
+      startPlaceholder: "开始时间",
+      endPlaceholder: "结束时间",
+      valueFormat: "YYYY-MM-DD HH:mm:ss"
+    }
+  }
+];
+
+const { buttons } = useTable();
+
+buttons.value = [
+  {
+    // 修改
+    text: "详细",
+    code: "edit",
+    // props v0.1.16 版本新增函数类型
+    props: {
+      type: "primary"
+    },
+    onClick(params) {
+      form.value = params.row;
+      state.isCreate = false;
+      state.dialogVisible = true;
+    }
+  }
+];
+
+const multipleSelection = ref([]);
+
+const handleSelectionChange = (val: string[]) => {
+  multipleSelection.value = val;
+};
+
+const handleDelete = () => {
+  // 删除前确认
+  ElMessageBox.confirm("是否确认删除选中数据?", "删除确认", {
+    confirmButtonText: "确认",
+    cancelButtonText: "取消",
+    type: "warning",
+    draggable: true
+  })
+    .then(async () => {
+      try {
+        let infoIds = multipleSelection.value.map(
+          item => item.infoId
+        ) as string[];
+        let res = await deleteSystemLogininfor(infoIds.join(","));
+        if (res.code === 200) {
+          ElMessage.success("删除成功");
+          refresh();
+          multipleSelection.value = [];
+        } else {
+          ElMessage.error(res.msg);
+        }
+      } catch (e) {
+        ElMessage.error("删除失败");
+      }
+    })
+    .catch(() => {
+      // 取消删除
+    });
+};
+
+const handleClear = () => {
+  // 清空前确认
+  ElMessageBox.confirm("是否确认清空所有操作日志?", "清空确认", {
+    confirmButtonText: "确认",
+    cancelButtonText: "取消",
+    type: "warning",
+    draggable: true
+  })
+    .then(async () => {
+      try {
+        let res = await cleanSystemLogininfor();
+        if (res.code === 200) {
+          ElMessage.success("清空成功");
+          refresh();
+          multipleSelection.value = [];
+        } else {
+          ElMessage.error(res.msg);
+        }
+      } catch (e) {
+        ElMessage.error("清空失败");
+      }
+    })
+    .catch(() => {
+      // 取消清空
+    });
+};
+
+interface State {
+  dialogVisible: boolean;
+  detailsVisible: boolean;
+  confirmLoading: boolean;
+  selectedIds: number[];
+  isCreate: boolean;
+  form: Record<string, any>;
+  rules: Record<string, any>;
+}
+
+const state = reactive<State>({
+  dialogVisible: false,
+  detailsVisible: false,
+  confirmLoading: false,
+  selectedIds: [],
+  isCreate: true,
+  form: {},
+  rules: {
+    sysName: [{ required: true, message: "请输入系统名称", trigger: "blur" }],
+    sysCode: [{ required: true, message: "请输入系统编码", trigger: "blur" }]
+  }
+});
+
+const columns: PlusColumn[] = [
+  {
+    label: "操作模块",
+    prop: "sysName",
+    formatter: () => {
+      return `${form.value.title}/${useDictValue("sys_oper_type", form.value.businessType)}`;
+    },
+    descriptionsItemProps: {
+      span: 12
+    }
+  },
+  {
+    label: "请求地址",
+    prop: "operUrl",
+    descriptionsItemProps: {
+      span: 12
+    }
+  },
+  {
+    label: "登录信息",
+    prop: "operIp",
+    formatter: () => {
+      return `${form.value.operName}/${form.value.operIp}`;
+    },
+    descriptionsItemProps: {
+      span: 12
+    }
+  },
+  {
+    label: "请求方式",
+    prop: "requestMethod",
+    descriptionsItemProps: {
+      span: 12
+    }
+  },
+  {
+    label: "操作方法",
+    prop: "method",
+    descriptionsItemProps: {
+      span: 24
+    }
+  },
+  {
+    label: "操作参数",
+    prop: "operParam",
+    descriptionsItemProps: {
+      span: 24,
+      className: "break-all"
+    }
+  },
+  {
+    label: "返回参数",
+    prop: "jsonResult",
+    descriptionsItemProps: {
+      span: 24
+    }
+  },
+  {
+    label: "操作状态",
+    prop: "status",
+    formatter: () => {
+      return useDictValue("sys_common_status", form.value.status);
+    },
+    descriptionsItemProps: {
+      span: 8
+    }
+  },
+  {
+    label: "消耗时间",
+    prop: "costTime",
+    formatter: () => {
+      return `${form.value.costTime}毫秒`;
+    },
+    descriptionsItemProps: {
+      span: 8
+    }
+  },
+  {
+    label: "操作时间",
+    prop: "operTime",
+    descriptionsItemProps: {
+      span: 8
+    }
+  }
+];
+
+const { form, dialogVisible } = toRefs(state);
+</script>
+
+<template>
+  <div>
+    <PlusPage
+      ref="plusPageInstance"
+      :columns="tableConfig"
+      :request="getList"
+      :pageInfoMap="{ page: 'pageNum', pageSize: 'pageSize' }"
+      :table="{
+        adaptive: { offsetBottom: 50 },
+        isSelection: true,
+        onSelectionChange: handleSelectionChange,
+        rowKey: 'infoId'
+      }"
+      :search="{
+        showNumber: 3
+      }"
+    >
+      <template #table-title>
+        <el-row class="button-row">
+          <el-button
+            size="default"
+            :disabled="multipleSelection.length === 0"
+            type="danger"
+            @click="handleDelete"
+          >
+            删除
+          </el-button>
+          <el-button size="default" type="danger" @click="handleClear">
+            清空日志
+          </el-button>
+        </el-row>
+      </template>
+    </PlusPage>
+    <!-- 弹窗编辑 -->
+    <PlusDialog
+      v-model="dialogVisible"
+      :title="'操作日志详细'"
+      width="800"
+      :has-footer="false"
+    >
+      <PlusDescriptions
+        size="large"
+        :column="24"
+        :columns="columns"
+        :data="form"
+        :border="true"
+        label-width="90px"
+      />
+    </PlusDialog>
+  </div>
+</template>
+
+<style scoped lang="scss"></style>

+ 6 - 4
src/views/system/operlog/index.vue

@@ -8,7 +8,7 @@ import {
   PlusPageInstance,
   useTable
 } from "plus-pro-components";
-import { computed, reactive, ref, toRefs } from "vue";
+import { computed, reactive, ref, toRefs, type Ref } from "vue";
 import {
   cleanSystemOperlog,
   deleteSystemOperlog,
@@ -60,7 +60,8 @@ const tableConfig: PlusColumn[] = [
     options: computed(() => sys_oper_type.value),
     fieldProps: value => {
       return {
-        type: sys_oper_type.value.find(item => item.value === value + "")?.class
+        type: sys_oper_type.value.find((item: Ref) => item.value === value + "")
+          ?.class
       };
     },
     formatter: (value, { column }) => {
@@ -100,8 +101,9 @@ const tableConfig: PlusColumn[] = [
     options: computed(() => sys_common_status.value),
     fieldProps: value => {
       return {
-        type: sys_common_status.value.find(item => item.value === value + "")
-          ?.class
+        type: sys_common_status.value.find(
+          (item: Ref) => item.value === value + ""
+        )?.class
       };
     },
     formatter: (value, { column }) => {