ClientForm.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <Dialog v-model="dialogVisible" :title="dialogTitle" max-height="500px" scroll>
  3. <el-form
  4. ref="formRef"
  5. v-loading="formLoading"
  6. :model="formData"
  7. :rules="formRules"
  8. label-width="160px"
  9. >
  10. <el-form-item label="客户端编号" prop="secret">
  11. <el-input v-model="formData.clientId" placeholder="请输入客户端编号" />
  12. </el-form-item>
  13. <el-form-item label="客户端密钥" prop="secret">
  14. <el-input v-model="formData.secret" placeholder="请输入客户端密钥" />
  15. </el-form-item>
  16. <el-form-item label="应用名" prop="name">
  17. <el-input v-model="formData.name" placeholder="请输入应用名" />
  18. </el-form-item>
  19. <el-form-item label="应用图标">
  20. <UploadImg v-model="formData.logo" :limit="1" />
  21. </el-form-item>
  22. <el-form-item label="应用描述">
  23. <el-input v-model="formData.description" placeholder="请输入应用名" type="textarea" />
  24. </el-form-item>
  25. <el-form-item label="状态" prop="status">
  26. <el-radio-group v-model="formData.status">
  27. <el-radio
  28. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  29. :key="dict.value"
  30. :label="dict.value"
  31. >
  32. {{ dict.label }}
  33. </el-radio>
  34. </el-radio-group>
  35. </el-form-item>
  36. <el-form-item label="访问令牌的有效期" prop="accessTokenValiditySeconds">
  37. <el-input-number v-model="formData.accessTokenValiditySeconds" placeholder="单位:秒" />
  38. </el-form-item>
  39. <el-form-item label="刷新令牌的有效期" prop="refreshTokenValiditySeconds">
  40. <el-input-number v-model="formData.refreshTokenValiditySeconds" placeholder="单位:秒" />
  41. </el-form-item>
  42. <el-form-item label="授权类型" prop="authorizedGrantTypes">
  43. <el-select
  44. v-model="formData.authorizedGrantTypes"
  45. filterable
  46. multiple
  47. placeholder="请输入授权类型"
  48. style="width: 500px"
  49. >
  50. <el-option
  51. v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE)"
  52. :key="dict.value"
  53. :label="dict.label"
  54. :value="dict.value"
  55. />
  56. </el-select>
  57. </el-form-item>
  58. <el-form-item label="授权范围" prop="scopes">
  59. <el-select
  60. v-model="formData.scopes"
  61. filterable
  62. multiple
  63. allow-create
  64. placeholder="请输入授权范围"
  65. style="width: 500px"
  66. >
  67. <el-option v-for="scope in formData.scopes" :key="scope" :label="scope" :value="scope" />
  68. </el-select>
  69. </el-form-item>
  70. <el-form-item label="自动授权范围" prop="autoApproveScopes">
  71. <el-select
  72. v-model="formData.autoApproveScopes"
  73. filterable
  74. multiple
  75. placeholder="请输入授权范围"
  76. style="width: 500px"
  77. >
  78. <el-option v-for="scope in formData.scopes" :key="scope" :label="scope" :value="scope" />
  79. </el-select>
  80. </el-form-item>
  81. <el-form-item label="可重定向的 URI 地址" prop="redirectUris">
  82. <el-select
  83. v-model="formData.redirectUris"
  84. allow-create
  85. filterable
  86. multiple
  87. placeholder="请输入可重定向的 URI 地址"
  88. style="width: 500px"
  89. >
  90. <el-option
  91. v-for="redirectUri in formData.redirectUris"
  92. :key="redirectUri"
  93. :label="redirectUri"
  94. :value="redirectUri"
  95. />
  96. </el-select>
  97. </el-form-item>
  98. <el-form-item label="权限" prop="authorities">
  99. <el-select
  100. v-model="formData.authorities"
  101. allow-create
  102. filterable
  103. multiple
  104. placeholder="请输入权限"
  105. style="width: 500px"
  106. >
  107. <el-option
  108. v-for="authority in formData.authorities"
  109. :key="authority"
  110. :label="authority"
  111. :value="authority"
  112. />
  113. </el-select>
  114. </el-form-item>
  115. <el-form-item label="资源" prop="resourceIds">
  116. <el-select
  117. v-model="formData.resourceIds"
  118. allow-create
  119. filterable
  120. multiple
  121. placeholder="请输入资源"
  122. style="width: 500px"
  123. >
  124. <el-option
  125. v-for="resourceId in formData.resourceIds"
  126. :key="resourceId"
  127. :label="resourceId"
  128. :value="resourceId"
  129. />
  130. </el-select>
  131. </el-form-item>
  132. <el-form-item label="附加信息" prop="additionalInformation">
  133. <el-input
  134. v-model="formData.additionalInformation"
  135. placeholder="请输入附加信息,JSON 格式数据"
  136. type="textarea"
  137. />
  138. </el-form-item>
  139. </el-form>
  140. <template #footer>
  141. <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
  142. <el-button @click="dialogVisible = false">取 消</el-button>
  143. </template>
  144. </Dialog>
  145. </template>
  146. <script lang="ts" setup>
  147. import { DICT_TYPE, getDictOptions, getIntDictOptions } from '@/utils/dict'
  148. import { CommonStatusEnum } from '@/utils/constants'
  149. import * as ClientApi from '@/api/system/oauth2/client'
  150. defineOptions({ name: 'SystemOAuth2ClientForm' })
  151. const { t } = useI18n() // 国际化
  152. const message = useMessage() // 消息弹窗
  153. const dialogVisible = ref(false) // 弹窗的是否展示
  154. const dialogTitle = ref('') // 弹窗的标题
  155. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  156. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  157. const formData = ref({
  158. id: undefined,
  159. clientId: undefined,
  160. secret: undefined,
  161. name: undefined,
  162. logo: undefined,
  163. description: undefined,
  164. status: CommonStatusEnum.ENABLE,
  165. accessTokenValiditySeconds: 30 * 60,
  166. refreshTokenValiditySeconds: 30 * 24 * 60,
  167. redirectUris: [],
  168. authorizedGrantTypes: [],
  169. scopes: [],
  170. autoApproveScopes: [],
  171. authorities: [],
  172. resourceIds: [],
  173. additionalInformation: undefined
  174. })
  175. const formRules = reactive({
  176. clientId: [{ required: true, message: '客户端编号不能为空', trigger: 'blur' }],
  177. secret: [{ required: true, message: '客户端密钥不能为空', trigger: 'blur' }],
  178. name: [{ required: true, message: '应用名不能为空', trigger: 'blur' }],
  179. logo: [{ required: true, message: '应用图标不能为空', trigger: 'blur' }],
  180. status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
  181. accessTokenValiditySeconds: [
  182. { required: true, message: '访问令牌的有效期不能为空', trigger: 'blur' }
  183. ],
  184. refreshTokenValiditySeconds: [
  185. { required: true, message: '刷新令牌的有效期不能为空', trigger: 'blur' }
  186. ],
  187. redirectUris: [{ required: true, message: '可重定向的 URI 地址不能为空', trigger: 'blur' }],
  188. authorizedGrantTypes: [{ required: true, message: '授权类型不能为空', trigger: 'blur' }]
  189. })
  190. const formRef = ref() // 表单 Ref
  191. /** 打开弹窗 */
  192. const open = async (type: string, id?: number) => {
  193. dialogVisible.value = true
  194. dialogTitle.value = t('action.' + type)
  195. formType.value = type
  196. resetForm()
  197. // 修改时,设置数据
  198. if (id) {
  199. formLoading.value = true
  200. try {
  201. formData.value = await ClientApi.getOAuth2Client(id)
  202. } finally {
  203. formLoading.value = false
  204. }
  205. }
  206. }
  207. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  208. /** 提交表单 */
  209. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  210. const submitForm = async () => {
  211. // 校验表单
  212. if (!formRef) return
  213. const valid = await formRef.value.validate()
  214. if (!valid) return
  215. // 提交请求
  216. formLoading.value = true
  217. try {
  218. const data = formData.value as unknown as ClientApi.OAuth2ClientVO
  219. if (formType.value === 'create') {
  220. await ClientApi.createOAuth2Client(data)
  221. message.success(t('common.createSuccess'))
  222. } else {
  223. await ClientApi.updateOAuth2Client(data)
  224. message.success(t('common.updateSuccess'))
  225. }
  226. dialogVisible.value = false
  227. // 发送操作成功的事件
  228. emit('success')
  229. } finally {
  230. formLoading.value = false
  231. }
  232. }
  233. /** 重置表单 */
  234. const resetForm = () => {
  235. formData.value = {
  236. id: undefined,
  237. clientId: undefined,
  238. secret: undefined,
  239. name: undefined,
  240. logo: undefined,
  241. description: undefined,
  242. status: CommonStatusEnum.ENABLE,
  243. accessTokenValiditySeconds: 30 * 60,
  244. refreshTokenValiditySeconds: 30 * 24 * 60,
  245. redirectUris: [],
  246. authorizedGrantTypes: [],
  247. scopes: [],
  248. autoApproveScopes: [],
  249. authorities: [],
  250. resourceIds: [],
  251. additionalInformation: undefined
  252. }
  253. formRef.value?.resetFields()
  254. }
  255. </script>