From eead9efc5efd5e75eea1d0c1ea6f1322454e3ae9 Mon Sep 17 00:00:00 2001
From: yj441106 <yj441106@163.com>
Date: Sun, 26 Mar 2023 15:22:51 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E9=87=8D=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/views/system/oauth2/client/client.data.ts | 197 -------------
 src/views/system/oauth2/client/form.vue       | 259 ++++++++++++++++++
 src/views/system/oauth2/token/form.vue        | 131 +++++++++
 3 files changed, 390 insertions(+), 197 deletions(-)
 delete mode 100644 src/views/system/oauth2/client/client.data.ts
 create mode 100644 src/views/system/oauth2/client/form.vue
 create mode 100644 src/views/system/oauth2/token/form.vue

diff --git a/src/views/system/oauth2/client/client.data.ts b/src/views/system/oauth2/client/client.data.ts
deleted file mode 100644
index 52ee8895..00000000
--- a/src/views/system/oauth2/client/client.data.ts
+++ /dev/null
@@ -1,197 +0,0 @@
-import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
-import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
-const { t } = useI18n() // 国际化
-
-const authorizedGrantOptions = getStrDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE)
-
-// 表单校验
-export const rules = reactive({
-  clientId: [required],
-  secret: [required],
-  name: [required],
-  status: [required],
-  accessTokenValiditySeconds: [required],
-  refreshTokenValiditySeconds: [required],
-  redirectUris: [required],
-  authorizedGrantTypes: [required]
-})
-
-// CrudSchema
-const crudSchemas = reactive<VxeCrudSchema>({
-  primaryKey: 'clientId',
-  primaryType: null,
-  action: true,
-  columns: [
-    {
-      title: '客户端端号',
-      field: 'clientId'
-    },
-    {
-      title: '客户端密钥',
-      field: 'secret'
-    },
-    {
-      title: '应用名',
-      field: 'name',
-      isSearch: true
-    },
-    {
-      title: '应用图标',
-      field: 'logo',
-      table: {
-        cellRender: {
-          name: 'XImg'
-        }
-      },
-      form: {
-        component: 'UploadImg'
-      }
-    },
-    {
-      title: t('common.status'),
-      field: 'status',
-      dictType: DICT_TYPE.COMMON_STATUS,
-      dictClass: 'number',
-      isSearch: true
-    },
-    {
-      title: '访问令牌的有效期',
-      field: 'accessTokenValiditySeconds',
-      form: {
-        component: 'InputNumber'
-      },
-      table: {
-        slots: {
-          default: 'accessTokenValiditySeconds_default'
-        }
-      }
-    },
-    {
-      title: '刷新令牌的有效期',
-      field: 'refreshTokenValiditySeconds',
-      form: {
-        component: 'InputNumber'
-      },
-      table: {
-        slots: {
-          default: 'refreshTokenValiditySeconds_default'
-        }
-      }
-    },
-    {
-      title: '授权类型',
-      field: 'authorizedGrantTypes',
-      table: {
-        width: 400,
-        slots: {
-          default: 'authorizedGrantTypes_default'
-        }
-      },
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: authorizedGrantOptions,
-          multiple: true,
-          filterable: true
-        }
-      }
-    },
-    {
-      title: '授权范围',
-      field: 'scopes',
-      isTable: false,
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: [],
-          multiple: true,
-          filterable: true,
-          allowCreate: true,
-          defaultFirstOption: true
-        }
-      }
-    },
-    {
-      title: '自动授权范围',
-      field: 'autoApproveScopes',
-      isTable: false,
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: [],
-          multiple: true,
-          filterable: true,
-          allowCreate: true,
-          defaultFirstOption: true
-        }
-      }
-    },
-    {
-      title: '可重定向的 URI 地址',
-      field: 'redirectUris',
-      isTable: false,
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: [],
-          multiple: true,
-          filterable: true,
-          allowCreate: true,
-          defaultFirstOption: true
-        }
-      }
-    },
-    {
-      title: '权限',
-      field: 'authorities',
-      isTable: false,
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: [],
-          multiple: true,
-          filterable: true,
-          allowCreate: true,
-          defaultFirstOption: true
-        }
-      }
-    },
-    {
-      title: '资源',
-      field: 'resourceIds',
-      isTable: false,
-      form: {
-        component: 'Select',
-        componentProps: {
-          options: [],
-          multiple: true,
-          filterable: true,
-          allowCreate: true,
-          defaultFirstOption: true
-        }
-      }
-    },
-    {
-      title: '附加信息',
-      field: 'additionalInformation',
-      isTable: false,
-      form: {
-        component: 'Input',
-        componentProps: {
-          type: 'textarea',
-          rows: 4
-        },
-        colProps: {
-          span: 24
-        }
-      }
-    },
-    {
-      title: t('common.createTime'),
-      field: 'createTime',
-      formatter: 'formatDate',
-      isForm: false
-    }
-  ]
-})
-export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
diff --git a/src/views/system/oauth2/client/form.vue b/src/views/system/oauth2/client/form.vue
new file mode 100644
index 00000000..0822e59f
--- /dev/null
+++ b/src/views/system/oauth2/client/form.vue
@@ -0,0 +1,259 @@
+<template>
+  <Dialog :title="modelTitle" v-model="modelVisible" width="800">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="120px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="客户端编号" prop="secret">
+        <el-input v-model="formData.clientId" placeholder="请输入客户端编号" />
+      </el-form-item>
+      <el-form-item label="客户端密钥" prop="secret">
+        <el-input v-model="formData.secret" placeholder="请输入客户端密钥" />
+      </el-form-item>
+      <el-form-item label="应用名" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入应用名" />
+      </el-form-item>
+      <el-form-item label="应用图标">
+        <UploadImg v-model="formData.logo" :limit="1" />
+      </el-form-item>
+      <el-form-item label="应用描述">
+        <el-input type="textarea" v-model="formData.description" placeholder="请输入应用名" />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio
+            v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
+            :key="dict.value"
+            :label="parseInt(dict.value)"
+            >{{ dict.label }}</el-radio
+          >
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="访问令牌的有效期" prop="accessTokenValiditySeconds">
+        <el-input-number v-model="formData.accessTokenValiditySeconds" placeholder="单位:秒" />
+      </el-form-item>
+      <el-form-item label="刷新令牌的有效期" prop="refreshTokenValiditySeconds">
+        <el-input-number v-model="formData.refreshTokenValiditySeconds" placeholder="单位:秒" />
+      </el-form-item>
+      <el-form-item label="授权类型" prop="authorizedGrantTypes">
+        <el-select
+          v-model="formData.authorizedGrantTypes"
+          multiple
+          filterable
+          placeholder="请输入授权类型"
+          style="width: 500px"
+        >
+          <el-option
+            v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="授权范围" prop="scopes">
+        <el-select
+          v-model="formData.scopes"
+          multiple
+          filterable
+          allow-create
+          placeholder="请输入授权范围"
+          style="width: 500px"
+        >
+          <el-option v-for="scope in formData.scopes" :key="scope" :label="scope" :value="scope" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="自动授权范围" prop="autoApproveScopes">
+        <el-select
+          v-model="formData.autoApproveScopes"
+          multiple
+          filterable
+          placeholder="请输入授权范围"
+          style="width: 500px"
+        >
+          <el-option v-for="scope in formData.scopes" :key="scope" :label="scope" :value="scope" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="可重定向的 URI 地址" prop="redirectUris">
+        <el-select
+          v-model="formData.redirectUris"
+          multiple
+          filterable
+          allow-create
+          placeholder="请输入可重定向的 URI 地址"
+          style="width: 500px"
+        >
+          <el-option
+            v-for="redirectUri in formData.redirectUris"
+            :key="redirectUri"
+            :label="redirectUri"
+            :value="redirectUri"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="权限" prop="authorities">
+        <el-select
+          v-model="formData.authorities"
+          multiple
+          filterable
+          allow-create
+          placeholder="请输入权限"
+          style="width: 500px"
+        >
+          <el-option
+            v-for="authority in formData.authorities"
+            :key="authority"
+            :label="authority"
+            :value="authority"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="资源" prop="resourceIds">
+        <el-select
+          v-model="formData.resourceIds"
+          multiple
+          filterable
+          allow-create
+          placeholder="请输入资源"
+          style="width: 500px"
+        >
+          <el-option
+            v-for="resourceId in formData.resourceIds"
+            :key="resourceId"
+            :label="resourceId"
+            :value="resourceId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="附加信息" prop="additionalInformation">
+        <el-input
+          type="textarea"
+          v-model="formData.additionalInformation"
+          placeholder="请输入附加信息,JSON 格式数据"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+        <el-button @click="modelVisible = false">取 消</el-button>
+      </div>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE, getDictOptions } from '@/utils/dict'
+import * as ClientApi from '@/api/system/oauth2/client'
+import UploadImg from '@/components/UploadFile'
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const modelVisible = ref(false) // 弹窗的是否展示
+const modelTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  clientId: undefined,
+  secret: undefined,
+  name: undefined,
+  logo: undefined,
+  description: undefined,
+  status: DICT_TYPE.COMMON_STATUS,
+  accessTokenValiditySeconds: 30 * 60,
+  refreshTokenValiditySeconds: 30 * 24 * 60,
+  redirectUris: [],
+  authorizedGrantTypes: [],
+  scopes: [],
+  autoApproveScopes: [],
+  authorities: [],
+  resourceIds: [],
+  additionalInformation: undefined
+})
+const formRules = reactive({
+  clientId: [{ required: true, message: '客户端编号不能为空', trigger: 'blur' }],
+  secret: [{ required: true, message: '客户端密钥不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '应用名不能为空', trigger: 'blur' }],
+  logo: [{ required: true, message: '应用图标不能为空', trigger: 'blur' }],
+  status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
+  accessTokenValiditySeconds: [
+    { required: true, message: '访问令牌的有效期不能为空', trigger: 'blur' }
+  ],
+  refreshTokenValiditySeconds: [
+    { required: true, message: '刷新令牌的有效期不能为空', trigger: 'blur' }
+  ],
+  redirectUris: [{ required: true, message: '可重定向的 URI 地址不能为空', trigger: 'blur' }],
+  authorizedGrantTypes: [{ required: true, message: '授权类型不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const openModal = async (type: string, id?: number) => {
+  modelVisible.value = true
+  modelTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await ClientApi.getOAuth2ClientApi(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as ClientApi.OAuth2ClientVO
+    if (formType.value === 'create') {
+      await ClientApi.createOAuth2ClientApi(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await ClientApi.updateOAuth2ClientApi(data)
+      message.success(t('common.updateSuccess'))
+    }
+    modelVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    clientId: undefined,
+    secret: undefined,
+    name: undefined,
+    logo: undefined,
+    description: undefined,
+    status: DICT_TYPE.COMMON_STATUS,
+    accessTokenValiditySeconds: 30 * 60,
+    refreshTokenValiditySeconds: 30 * 24 * 60,
+    redirectUris: [],
+    authorizedGrantTypes: [],
+    scopes: [],
+    autoApproveScopes: [],
+    authorities: [],
+    resourceIds: [],
+    additionalInformation: undefined
+  }
+  formRef.value?.resetFields()
+}
+</script>
diff --git a/src/views/system/oauth2/token/form.vue b/src/views/system/oauth2/token/form.vue
new file mode 100644
index 00000000..5372ca7e
--- /dev/null
+++ b/src/views/system/oauth2/token/form.vue
@@ -0,0 +1,131 @@
+<template>
+  <Dialog :title="modelTitle" v-model="modelVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="80px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="参数分类" prop="category">
+        <el-input v-model="formData.category" placeholder="请输入参数分类" />
+      </el-form-item>
+      <el-form-item label="参数名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入参数名称" />
+      </el-form-item>
+      <el-form-item label="参数键名" prop="key">
+        <el-input v-model="formData.key" placeholder="请输入参数键名" />
+      </el-form-item>
+      <el-form-item label="参数键值" prop="value">
+        <el-input v-model="formData.value" placeholder="请输入参数键值" />
+      </el-form-item>
+      <el-form-item label="是否可见" prop="visible">
+        <el-radio-group v-model="formData.visible">
+          <el-radio
+            v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+            :key="dict.value"
+            :label="dict.value"
+          >
+            {{ dict.label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="备注" prop="remark">
+        <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+        <el-button @click="modelVisible = false">取 消</el-button>
+      </div>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE, getDictOptions } from '@/utils/dict'
+import * as ConfigApi from '@/api/infra/config'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const modelVisible = ref(false) // 弹窗的是否展示
+const modelTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  category: '',
+  name: '',
+  key: '',
+  value: '',
+  visible: true,
+  remark: ''
+})
+const formRules = reactive({
+  category: [{ required: true, message: '参数分类不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }],
+  key: [{ required: true, message: '参数键名不能为空', trigger: 'blur' }],
+  value: [{ required: true, message: '参数键值不能为空', trigger: 'blur' }],
+  visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const openModal = async (type: string, id?: number) => {
+  modelVisible.value = true
+  modelTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await ConfigApi.getConfig(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as ConfigApi.ConfigVO
+    if (formType.value === 'create') {
+      await ConfigApi.createConfig(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await ConfigApi.updateConfig(data)
+      message.success(t('common.updateSuccess'))
+    }
+    modelVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    category: '',
+    name: '',
+    key: '',
+    value: '',
+    visible: true,
+    remark: ''
+  }
+  formRef.value?.resetFields()
+}
+</script>