瀏覽代碼

feat(系统模块): 添加秘钥管理功能

shizhongming 2 年之前
父節點
當前提交
d8c4712b53

+ 78 - 0
src/modules/system/views/authSecret/SmartAuthSecretKeyListView.api.ts

@@ -0,0 +1,78 @@
+import { ApiServiceEnum, defHttp } from '@/utils/http/axios';
+
+enum Api {
+  list = '/sys/auth/secret/listBySystem',
+  getById = '/sys/auth/secret/getById',
+  batchSaveUpdate = '/sys/auth/secret/batchSaveUpdate',
+  delete = '/sys/auth/secret/batchDeleteById',
+  saveUpdate = 'sys/auth/secret/saveUpdate',
+  download = 'sys/auth/secret/download',
+}
+
+export const listApi = (params) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.list,
+    data: {
+      ...params,
+    },
+  });
+};
+
+export const batchSaveUpdateApi = (modelList: any[]) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.batchSaveUpdate,
+    data: modelList,
+  });
+};
+
+export const deleteApi = (removeRecords: Recordable[]) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.delete,
+    data: removeRecords.map((item) => item.id),
+  });
+};
+
+export const getByIdApi = (id: number) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.getById,
+    data: id,
+  });
+};
+
+export const saveUpdateApi = (model) => {
+  const { publicKeyFileList, privateKeyFileList } = model;
+  const publicKeyFile = publicKeyFileList[0].originFileObj;
+  const privateKeyFile = privateKeyFileList[0].originFileObj;
+  const data = {
+    ...model,
+  };
+  delete data.publicKeyFileList;
+  delete data.privateKeyFileList;
+  return defHttp.uploadFile(
+    {
+      service: ApiServiceEnum.SMART_SYSTEM,
+      url: Api.saveUpdate,
+    },
+    {
+      data,
+      file: [
+        { name: 'publicKeyFile', file: publicKeyFile },
+        { name: 'privateKeyFile', file: privateKeyFile },
+      ],
+    },
+  );
+};
+
+export const download = (id) => {
+  return defHttp.download({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.download,
+    data: {
+      id,
+    },
+  });
+};

+ 208 - 0
src/modules/system/views/authSecret/SmartAuthSecretKeyListView.config.ts

@@ -0,0 +1,208 @@
+import type { SmartColumn, SmartSearchFormSchema } from '@/components/SmartTable';
+import type { FormSchema } from '@/components/Form';
+import { tableUseYnClass } from '@/components/SmartTable';
+
+/**
+ * 表格列表
+ */
+export const getTableColumns = (): SmartColumn[] => {
+  return [
+    {
+      type: 'checkbox',
+      width: 60,
+      align: 'center',
+      fixed: 'left',
+    },
+    {
+      field: 'id',
+      visible: false,
+      title: 'ID',
+      width: 120,
+    },
+    {
+      field: 'keyName',
+      title: '{smart.auth.secret.title.keyName}',
+      width: 120,
+      fixed: 'left',
+    },
+    {
+      field: 'fileStorageId',
+      title: '{smart.auth.secret.title.fileStorageId}',
+      width: 120,
+      formatter: ({ row }) => {
+        return row.fileStorage?.storageName;
+      },
+    },
+    {
+      field: 'seq',
+      title: '{common.table.seq}',
+      width: 120,
+      sortable: true,
+    },
+    {
+      ...tableUseYnClass(),
+      width: 100,
+      sortable: true,
+    },
+    {
+      field: 'alias',
+      title: '{smart.auth.secret.title.alias}',
+      width: 120,
+    },
+    {
+      field: 'remark',
+      title: '{common.table.remark}',
+      width: 120,
+    },
+    {
+      field: 'createTime',
+      title: '{common.table.createTime}',
+      width: 160,
+    },
+    {
+      field: 'createBy',
+      title: '{common.table.createUser}',
+      width: 120,
+    },
+    {
+      field: 'updateTime',
+      title: '{common.table.updateTime}',
+      width: 160,
+    },
+    {
+      field: 'updateBy',
+      title: '{common.table.updateUser}',
+      width: 120,
+    },
+    {
+      title: '{common.table.operation}',
+      field: 'operation',
+      width: 120,
+      fixed: 'right',
+      slots: {
+        default: 'table-operation',
+      },
+    },
+  ];
+};
+
+/**
+ * 添加修改表单
+ */
+export const getFormSchemas = (t: Function): FormSchema[] => {
+  return [
+    {
+      field: 'id',
+      label: 'ID',
+      component: 'Input',
+      componentProps: {},
+      show: false,
+    },
+    {
+      field: 'keyName',
+      label: t('smart.auth.secret.title.keyName'),
+      component: 'Input',
+      componentProps: {},
+      required: true,
+    },
+    {
+      field: 'fileStorageId',
+      label: t('system.views.file.title.fileStorageId'),
+      component: 'SmartApiSelectTable',
+      componentProps: {
+        modelClassName: 'com.smart.file.manager.model.SmartFileStoragePO',
+        valueFieldName: 'id',
+        labelFieldName: 'storageName',
+        params: {
+          sortName: 'seq',
+          parameter: {
+            'deleteYn@<>': true,
+            'useYn@=': true,
+          },
+        },
+      },
+      required: true,
+    },
+    {
+      field: 'seq',
+      label: t('common.table.seq'),
+      component: 'InputNumber',
+      componentProps: {},
+      required: true,
+      defaultValue: 1,
+    },
+    {
+      field: 'storePassword',
+      label: t('smart.auth.secret.title.storePassword'),
+      component: 'InputPassword',
+      componentProps: {},
+      required: true,
+    },
+    {
+      field: 'keyPassword',
+      label: t('smart.auth.secret.title.keyPassword'),
+      component: 'InputPassword',
+      componentProps: {},
+      required: true,
+    },
+    {
+      field: 'alias',
+      label: t('smart.auth.secret.title.alias'),
+      component: 'Input',
+      componentProps: {},
+      required: true,
+    },
+    {
+      field: 'publicKeyFileList',
+      label: t('smart.auth.secret.title.publicKeyFile'),
+      componentProps: {},
+      slot: 'form-publicKeyFile',
+      required: true,
+    },
+    {
+      field: 'privateKeyFileList',
+      label: t('smart.auth.secret.title.privateKeyFile'),
+      componentProps: {},
+      slot: 'form-privateKeyFile',
+      required: true,
+    },
+    {
+      field: 'remark',
+      label: t('common.table.remark'),
+      component: 'Input',
+      componentProps: {},
+    },
+  ];
+};
+
+export const getSearchFormSchemas = (t: Function): SmartSearchFormSchema[] => {
+  return [
+    {
+      field: 'keyName',
+      label: t('smart.auth.secret.title.keyName'),
+      component: 'Input',
+      searchSymbol: 'like',
+    },
+    {
+      field: 'useYn',
+      label: t('common.table.useYn'),
+      component: 'Select',
+      searchSymbol: '=',
+      componentProps: {
+        style: {
+          width: '120px',
+        },
+        options: [
+          {
+            label: t('common.form.use'),
+            value: 1,
+          },
+          {
+            label: t('common.form.noUse'),
+            value: 0,
+          },
+        ],
+      },
+    },
+  ];
+};

+ 191 - 0
src/modules/system/views/authSecret/SmartAuthSecretKeyListView.vue

@@ -0,0 +1,191 @@
+<template>
+  <div class="full-height page-container">
+    <LayoutSeparate first-size="240px" :show-line="false" class="full-height">
+      <template #first>
+        <div class="full-height system-container">
+          <SystemSimpleList
+            @current-change="handleSelectSystemChange"
+            :row-config="{ isHover: true, isCurrent: true }"
+            height="auto"
+          />
+        </div>
+      </template>
+      <template #second>
+        <SmartTable @register="registerTable" :size="getTableSize">
+          <template #table-operation="{ row }">
+            <SmartVxeTableAction :actions="getActions(row)" />
+          </template>
+          <template #form-publicKeyFile="{ model }">
+            <Upload
+              v-model:fileList="model.publicKeyFileList"
+              accept=".keystore"
+              :max-count="1"
+              :beforeUpload="() => false"
+            >
+              <a-button>Upload</a-button>
+            </Upload>
+          </template>
+          <template #form-privateKeyFile="{ model }">
+            <Upload
+              v-model:fileList="model.privateKeyFileList"
+              accept=".keystore"
+              :max-count="1"
+              :beforeUpload="() => false"
+            >
+              <a-button>Upload</a-button>
+            </Upload>
+          </template>
+        </SmartTable>
+      </template>
+    </LayoutSeparate>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, unref } from 'vue';
+  import { useI18n } from '@/hooks/web/useI18n';
+  import { useSizeSetting } from '@/hooks/setting/UseSizeSetting';
+  import { Upload } from 'ant-design-vue';
+  import {
+    ActionItem,
+    SmartTable,
+    SmartVxeTableAction,
+    useSmartTable,
+  } from '@/components/SmartTable';
+  import LayoutSeparate from '@/components/LayoutSeparate/src/LayoutSeparate';
+  import SystemSimpleList from '@/modules/system/components/system/SystemSimpleList.vue';
+  import { hasPermission } from '@/utils/auth';
+
+  import {
+    getTableColumns,
+    getFormSchemas,
+    getSearchFormSchemas,
+  } from './SmartAuthSecretKeyListView.config';
+  import {
+    listApi,
+    deleteApi,
+    getByIdApi,
+    saveUpdateApi,
+    download,
+  } from './SmartAuthSecretKeyListView.api';
+
+  const { t } = useI18n();
+  const { getTableSize } = useSizeSetting();
+
+  /**
+   * 系统变更时触发:更新数据
+   */
+  const currentSystemRef = ref<Recordable>({});
+  const handleSelectSystemChange = (system) => {
+    currentSystemRef.value = system;
+    query();
+  };
+
+  const getActions = (row: Recordable): ActionItem[] => {
+    return [
+      {
+        label: t('common.button.edit'),
+        auth: 'auth:secret:update',
+        onClick: () => {
+          editByRowModal(row);
+        },
+      },
+      {
+        label: t('common.button.download'),
+        auth: 'auth:secret:download',
+        onClick: () => {
+          download(row.id);
+        },
+      },
+    ];
+  };
+
+  const [registerTable, { editByRowModal, query }] = useSmartTable({
+    columns: getTableColumns(),
+    height: 'auto',
+    pagerConfig: true,
+    useSearchForm: true,
+    stripe: true,
+    highlightHoverRow: true,
+    columnConfig: {
+      resizable: true,
+    },
+    border: true,
+    authConfig: {
+      authHandler: hasPermission,
+      toolbar: {
+        ModalAdd: 'auth:secret:save',
+        delete: 'auth:secret:delete',
+      },
+    },
+    sortConfig: {
+      remote: true,
+      defaultSort: {
+        field: 'seq',
+        order: 'asc',
+      },
+    },
+    searchFormConfig: {
+      schemas: getSearchFormSchemas(t),
+      searchWithSymbol: true,
+      colon: true,
+      layout: 'inline',
+      actionColOptions: {
+        span: undefined,
+      },
+      compact: true,
+    },
+    addEditConfig: {
+      formConfig: {
+        schemas: getFormSchemas(t),
+        baseColProps: { span: 24 },
+        labelCol: { span: 6 },
+        wrapperCol: { span: 17 },
+        colon: true,
+      },
+    },
+    proxyConfig: {
+      ajax: {
+        query: (params) => {
+          const parameter = {
+            ...params.ajaxParameter,
+            systemId: unref(currentSystemRef)?.id,
+          };
+          return listApi(parameter);
+        },
+        save: ({ body: { insertRecords, updateRecords } }) => {
+          const dataList = [...insertRecords, ...updateRecords];
+          return saveUpdateApi({
+            ...dataList[0],
+            systemId: unref(currentSystemRef).id,
+          });
+        },
+        delete: ({ body: { removeRecords } }) => deleteApi(removeRecords),
+        getById: (params) => getByIdApi(params.id),
+      },
+    },
+    importConfig: {},
+    exportConfig: {},
+    toolbarConfig: {
+      zoom: true,
+      refresh: true,
+      column: {
+        columnOrder: true,
+      },
+      buttons: [
+        {
+          code: 'ModalAdd',
+        },
+        {
+          code: 'delete',
+        },
+      ],
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .system-container {
+    margin-right: 5px;
+    background: white;
+  }
+</style>

+ 31 - 0
src/modules/system/views/authSecret/lang/en_US.ts

@@ -0,0 +1,31 @@
+/**
+ * 秘钥管理 国际化信息
+ */
+export default {
+  trans: true,
+  key: 'smart.auth.secret',
+  data: {
+    title: {
+      keyName: 'Key name',
+      fileStorageId: 'File storage',
+      alias: 'Alias',
+      storePassword: 'Store password',
+      keyPassword: 'Key password',
+      publicKeyFile: 'Public key',
+      privateKeyFile: 'Private key',
+    },
+    validate: {
+      keyName: 'Please enter key name',
+      fileStorageId: 'Please enter file storage',
+      storePassword: 'Please enter store password',
+      keyPassword: 'Please enter key password',
+      alias: 'Please enter alias',
+      publicKeyFileId: 'Please enter public key',
+      privateKeyFileId: 'Please enter private key',
+    },
+    rules: {},
+    search: {
+      keyName: 'Please enter key name',
+    },
+  },
+};

+ 31 - 0
src/modules/system/views/authSecret/lang/zh_CN.ts

@@ -0,0 +1,31 @@
+/**
+ * 秘钥管理 国际化信息
+ */
+export default {
+  trans: true,
+  key: 'smart.auth.secret',
+  data: {
+    title: {
+      keyName: '秘钥名称',
+      fileStorageId: '文件存储器ID',
+      alias: '私钥别称',
+      storePassword: '密钥库密码',
+      keyPassword: '私钥密码',
+      publicKeyFile: '公钥',
+      privateKeyFile: '私钥',
+    },
+    validate: {
+      keyName: '请输入秘钥名称',
+      fileStorageId: '请输入文件存储器ID',
+      storePassword: '请输入密钥库密码',
+      keyPassword: '请输入私钥密码',
+      alias: '请输入私钥别称',
+      publicKeyFileId: '请输入公钥文件ID',
+      privateKeyFileId: '请输入私钥文件ID',
+    },
+    rules: {},
+    search: {
+      keyName: '请输入秘钥名称',
+    },
+  },
+};

+ 10 - 3
types/axios.d.ts

@@ -46,16 +46,23 @@ export interface Result<T = any> {
   exceptionNo?: number;
 }
 
+export interface UploadFileItemParams {
+  // File parameter interface field name
+  name?: string;
+  // file name
+  file: File | Blob;
+  // file name
+  filename?: string;
+}
+
 // multipart/form-data: upload file
 export interface UploadFileParams {
   // Other parameters
   data?: Recordable;
   // File parameter interface field name
-  name?: string;
   // file name
-  file: File | Blob;
+  file: UploadFileItemParams | UploadFileItemParams[];
   // file name
-  filename?: string;
   [key: string]: any;
 }