From 113f17cd18dc98b4c5d7e4817aeedb85fd423b70 Mon Sep 17 00:00:00 2001 From: xingyu <xingyu4j@vip.qq.com> Date: Tue, 21 Mar 2023 23:11:45 +0800 Subject: [PATCH] feat: views --- src/components/Modal/src/props.ts | 2 +- src/components/Table/src/hooks/useRender.ts | 5 + src/utils/http/axios/Axios.ts | 6 +- src/views/system/dict/DictDataModel.vue | 2 +- src/views/system/dict/DictTypeModel.vue | 2 +- .../system/oauth2/client/ClientModel.vue | 58 +++++ src/views/system/oauth2/client/client.data.ts | 207 ++++++++++++++++++ src/views/system/oauth2/client/index.vue | 80 ++++++- .../system/operatelog/operateLog.data.ts | 2 +- 9 files changed, 356 insertions(+), 8 deletions(-) create mode 100644 src/views/system/oauth2/client/ClientModel.vue create mode 100644 src/views/system/oauth2/client/client.data.ts diff --git a/src/components/Modal/src/props.ts b/src/components/Modal/src/props.ts index fbfec2b2..92e207fc 100644 --- a/src/components/Modal/src/props.ts +++ b/src/components/Modal/src/props.ts @@ -75,7 +75,7 @@ export const basicProps = Object.assign({}, modalProps, { visible: { type: Boolean }, - width: [String, Number] as PropType<string | number>, + width: { type: [String, Number] as PropType<string | number>, default: '40%' }, wrapClassName: { type: String }, diff --git a/src/components/Table/src/hooks/useRender.ts b/src/components/Table/src/hooks/useRender.ts index 11110fd6..b9f46d61 100644 --- a/src/components/Table/src/hooks/useRender.ts +++ b/src/components/Table/src/hooks/useRender.ts @@ -14,6 +14,11 @@ export const useRender = { }) } }, + renderText: (text, val) => { + if (text) { + return text + ' ' + val + } + }, renderTag: (text, color?) => { if (!color) { return h(Tag, { color }, () => text) diff --git a/src/utils/http/axios/Axios.ts b/src/utils/http/axios/Axios.ts index e42fa204..23693c8c 100644 --- a/src/utils/http/axios/Axios.ts +++ b/src/utils/http/axios/Axios.ts @@ -125,9 +125,9 @@ export class VAxios { requestList = [] // TODO console.info('刷新令牌end', res) - return new Promise((resolve) => { - resolve(this.axiosInstance(config)) - }) + // return new Promise((resolve) => { + // resolve(this.axiosInstance(config)) + // }) // res = await Promise.all([this.axiosInstance(config)])[0] } catch (e) { console.info(e) diff --git a/src/views/system/dict/DictDataModel.vue b/src/views/system/dict/DictDataModel.vue index 728146bb..d4bdfbb7 100644 --- a/src/views/system/dict/DictDataModel.vue +++ b/src/views/system/dict/DictDataModel.vue @@ -3,7 +3,7 @@ <BasicForm @register="registerForm" /> </BasicModal> </template> -<script lang="ts" setup name="PostModal"> +<script lang="ts" setup name="DictDataModal"> import { ref, computed, unref } from 'vue' import { BasicModal, useModalInner } from '@/components/Modal' import { BasicForm, useForm } from '@/components/Form' diff --git a/src/views/system/dict/DictTypeModel.vue b/src/views/system/dict/DictTypeModel.vue index 0d7c849e..2b395af1 100644 --- a/src/views/system/dict/DictTypeModel.vue +++ b/src/views/system/dict/DictTypeModel.vue @@ -3,7 +3,7 @@ <BasicForm @register="registerForm" /> </BasicModal> </template> -<script lang="ts" setup name="PostModal"> +<script lang="ts" setup name="DictTypeModal"> import { ref, computed, unref } from 'vue' import { BasicModal, useModalInner } from '@/components/Modal' import { BasicForm, useForm } from '@/components/Form' diff --git a/src/views/system/oauth2/client/ClientModel.vue b/src/views/system/oauth2/client/ClientModel.vue new file mode 100644 index 00000000..e2214c5d --- /dev/null +++ b/src/views/system/oauth2/client/ClientModel.vue @@ -0,0 +1,58 @@ +<template> + <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit"> + <BasicForm @register="registerForm" /> + </BasicModal> +</template> +<script lang="ts" setup name="ClientModel"> +import { ref, computed, unref } from 'vue' +import { BasicModal, useModalInner } from '@/components/Modal' +import { BasicForm, useForm } from '@/components/Form' +import { formSchema } from './client.data' +import { createOAuth2ClientApi, getOAuth2ClientApi, updateOAuth2ClientApi } from '@/api/system/oauth2/client' + +const emit = defineEmits(['success', 'register']) +const isUpdate = ref(true) +const rowId = ref() + +const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ + labelWidth: 160, + baseColProps: { span: 24 }, + schemas: formSchema, + showActionButtonGroup: false, + actionColOptions: { + span: 23 + } +}) + +const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { + resetFields() + setModalProps({ confirmLoading: false }) + isUpdate.value = !!data?.isUpdate + + if (unref(isUpdate)) { + const res = await getOAuth2ClientApi(data.record.id) + rowId.value = res.id + setFieldsValue({ + ...res + }) + } +}) + +const getTitle = computed(() => (!unref(isUpdate) ? '新增应用' : '编辑应用')) + +async function handleSubmit() { + try { + const values = await validate() + setModalProps({ confirmLoading: true }) + if (unref(isUpdate)) { + await updateOAuth2ClientApi(values) + } else { + await createOAuth2ClientApi(values) + } + closeModal() + emit('success') + } finally { + setModalProps({ confirmLoading: false }) + } +} +</script> diff --git a/src/views/system/oauth2/client/client.data.ts b/src/views/system/oauth2/client/client.data.ts new file mode 100644 index 00000000..1f8a8d39 --- /dev/null +++ b/src/views/system/oauth2/client/client.data.ts @@ -0,0 +1,207 @@ +import { BasicColumn, FormSchema, useRender } from '@/components/Table' +import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' + +export const columns: BasicColumn[] = [ + { + title: '客户端编号', + dataIndex: 'clientId', + width: 200 + }, + { + title: '客户端密钥', + dataIndex: 'secret', + width: 100 + }, + { + title: '应用名', + dataIndex: 'name', + width: 100 + }, + { + title: '应用图标', + dataIndex: 'logo', + width: 120, + customRender: ({ text }) => { + return useRender.renderImg(text) + } + }, + { + title: '状态', + dataIndex: 'status', + width: 180, + customRender: ({ text }) => { + return useRender.renderDict(text, DICT_TYPE.COMMON_STATUS) + } + }, + { + title: '访问令牌的有效期', + dataIndex: 'accessTokenValiditySeconds', + width: 100, + customRender: ({ text }) => { + return useRender.renderText(text, '秒') + } + }, + { + title: '刷新令牌的有效期', + dataIndex: 'refreshTokenValiditySeconds', + width: 100, + customRender: ({ text }) => { + return useRender.renderText(text, '秒') + } + }, + { + title: '授权类型', + dataIndex: 'authorizedGrantTypes', + width: 180, + customRender: ({ text }) => { + return useRender.renderTags(text) + } + }, + { + title: '创建时间', + dataIndex: 'createTime', + width: 180, + customRender: ({ text }) => { + return useRender.renderDate(text) + } + } +] + +export const searchFormSchema: FormSchema[] = [ + { + label: '应用名', + field: 'name', + component: 'Input', + colProps: { span: 8 } + }, + { + label: '状态', + field: 'status', + component: 'Select', + componentProps: { + options: getIntDictOptions(DICT_TYPE.COMMON_STATUS) + }, + colProps: { span: 8 } + } +] + +export const formSchema: FormSchema[] = [ + { + label: '编号', + field: 'id', + show: false, + component: 'Input' + }, + { + label: '客户端编号', + field: 'secret', + required: true, + component: 'Input' + }, + { + label: '客户端密钥', + field: 'secret', + required: true, + component: 'Input' + }, + { + label: '应用名', + field: 'name', + required: true, + component: 'Input' + }, + // TODO UPLOAD + { + label: '应用图标', + field: 'logo', + required: true, + component: 'Input' + }, + { + label: '应用描述', + field: 'description', + component: 'InputTextArea' + }, + { + label: '状态', + field: 'status', + component: 'Select', + defaultValue: 0, + componentProps: { + options: getIntDictOptions(DICT_TYPE.COMMON_STATUS) + } + }, + { + label: '访问令牌的有效期', + field: 'accessTokenValiditySeconds', + required: true, + component: 'InputNumber' + }, + { + label: '刷新令牌的有效期', + field: 'refreshTokenValiditySeconds', + required: true, + component: 'InputNumber' + }, + { + label: '授权类型', + field: 'authorizedGrantTypes', + required: true, + component: 'Select', + componentProps: { + options: getStrDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE), + mode: 'multiple' + } + }, + { + label: '授权范围', + field: 'scopes', + component: 'Select', + componentProps: { + mode: 'tags', + options: [] + } + }, + { + label: '自动授权范围', + field: 'autoApproveScopes', + component: 'Select', + componentProps: { + mode: 'tags', + options: [] + } + }, + { + label: '可重定向的 URI 地址', + field: 'redirectUris', + required: true, + component: 'Select', + componentProps: { + mode: 'tags', + options: [] + } + }, + { + label: '权限', + field: 'authorities', + component: 'Select', + componentProps: { + mode: 'tags', + options: [] + } + }, + { + label: '资源', + field: 'resourceIds', + component: 'Select', + componentProps: { + mode: 'tags', + options: [] + } + }, + { + label: '附加信息', + field: 'additionalInformation', + component: 'InputTextArea' + } +] diff --git a/src/views/system/oauth2/client/index.vue b/src/views/system/oauth2/client/index.vue index 3b64cfc4..b1659b75 100644 --- a/src/views/system/oauth2/client/index.vue +++ b/src/views/system/oauth2/client/index.vue @@ -1,3 +1,81 @@ <template> - <div>开发中</div> + <div> + <BasicTable @register="registerTable"> + <template #toolbar> + <a-button type="primary" @click="handleCreate"> 新增 </a-button> + </template> + <template #bodyCell="{ column, record }"> + <template v-if="column.key === 'action'"> + <TableAction + :actions="[ + { + icon: 'clarity:note-edit-line', + label: '修改', + onClick: handleEdit.bind(null, record) + }, + { + icon: 'ant-design:delete-outlined', + color: 'error', + label: '删除', + popConfirm: { + title: '是否确认删除', + placement: 'left', + confirm: handleDelete.bind(null, record) + } + } + ]" + /> + </template> + </template> + </BasicTable> + <ClientModel @register="registerModal" @success="reload()" /> + </div> </template> +<script lang="ts" setup name="Client"> +import { BasicTable, useTable, TableAction } from '@/components/Table' +import { deleteOAuth2ClientApi, getOAuth2ClientPageApi } from '@/api/system/oauth2/client' +import { useModal } from '@/components/Modal' +import ClientModel from './ClientModel.vue' +import { columns, searchFormSchema } from './client.data' +import { useMessage } from '@/hooks/web/useMessage' + +const { createMessage } = useMessage() +const [registerModal, { openModal }] = useModal() +const [registerTable, { reload }] = useTable({ + title: '应用列表', + api: getOAuth2ClientPageApi, + columns, + formConfig: { + labelWidth: 120, + schemas: searchFormSchema + }, + useSearchForm: true, + showTableSetting: true, + showIndexColumn: false, + actionColumn: { + width: 160, + title: '操作', + dataIndex: 'action', + fixed: 'right' + } +}) + +function handleCreate() { + openModal(true, { + isUpdate: false + }) +} + +function handleEdit(record: Recordable) { + openModal(true, { + record, + isUpdate: true + }) +} + +async function handleDelete(record: Recordable) { + await deleteOAuth2ClientApi(record.id) + createMessage.success('删除成功') + reload() +} +</script> diff --git a/src/views/system/operatelog/operateLog.data.ts b/src/views/system/operatelog/operateLog.data.ts index 9a0b7051..ea2c32ef 100644 --- a/src/views/system/operatelog/operateLog.data.ts +++ b/src/views/system/operatelog/operateLog.data.ts @@ -58,7 +58,7 @@ export const columns: BasicColumn[] = [ dataIndex: 'duration', width: 180, customRender: ({ text }) => { - return h('span', text + 'ms') + return useRender.renderText(text, 'ms') } } ]