♻️ Refactoring code. 增加终端管理

This commit is contained in:
aeizzz 2023-02-09 13:55:24 +08:00
parent e1ed32a2e2
commit dea62337d2
9 changed files with 498 additions and 1 deletions

39
src/api/admin/client.ts Normal file
View File

@ -0,0 +1,39 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/admin/client/page',
method: 'get',
params: query
})
}
export function addObj(obj?: Object) {
return request({
url: '/admin/client',
method: 'post',
data: obj
})
}
export function getObj(id?: string) {
return request({
url: '/admin/client/' + id,
method: 'get'
})
}
export function delObj(id?: string) {
return request({
url: '/admin/client/' + id,
method: 'delete'
})
}
export function putObj(obj?: Object) {
return request({
url: '/admin/client',
method: 'put',
data: obj
})
}

View File

@ -321,3 +321,5 @@ body,
padding-left: #{$i}px !important;
}
}

View File

@ -5,3 +5,4 @@
@import './media/media.scss';
@import './waves.scss';
@import './dark.scss';
@import "./pigx.scss";

7
src/theme/pigx.scss Normal file
View File

@ -0,0 +1,7 @@
.el-form-item__content {
.el-select{
width: 100% !important;
}
}

View File

@ -0,0 +1,237 @@
<template>
<el-dialog v-model="visible" :close-on-click-modal="false"
:title="form.id ? $t('common.editBtn') : $t('common.addBtn')" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.clientId')" prop="clientId">
<el-input v-model="form.clientId" :placeholder="t('client.inputClientIdTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.clientSecret')" prop="clientSecret">
<el-input v-model="form.clientSecret" :placeholder="t('client.inputClientSecretTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.scope')" prop="scope">
<el-input v-model="form.scope" :placeholder="t('client.inputScopeTip')"/>
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item :label="t('client.authorizedGrantTypes')" prop="authorizedGrantTypes">
<el-checkbox-group v-model="form.authorizedGrantTypes">
<el-checkbox v-for="(item, index) in grant_types" :key="index"
:label="item.value">{{item.label}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.webServerRedirectUri')" prop="webServerRedirectUri">
<el-input v-model="form.webServerRedirectUri" :placeholder="t('client.inputWebServerRedirectUriTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.authorities')" prop="authorities">
<el-input v-model="form.authorities" :placeholder="t('client.inputAuthoritiesTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.accessTokenValidity')" prop="accessTokenValidity">
<el-input v-model="form.accessTokenValidity" :placeholder="t('client.inputAccessTokenValidityTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.refreshTokenValidity')" prop="refreshTokenValidity">
<el-input v-model="form.refreshTokenValidity" :placeholder="t('client.inputRefreshTokenValidityTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.autoapprove')" prop="autoapprove">
<el-radio-group v-model="form.autoapprove">
<el-radio v-for="(item, index) in common_status" :key="index" :label="item.value" border>{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item :label="t('client.additionalInformation')" prop="additionalInformation">
<el-input type="textarea" v-model="form.additionalInformation" :placeholder="t('client.inputAdditionalInformationTip')"/>
</el-form-item>
</el-col>
</el-row>
<el-collapse v-model="collapseActive">
<el-collapse-item title="安全属性" name="1">
<template #title>
<el-icon class="header-icon">
<info-filled />
</el-icon>
</template>
<el-row>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.captchaFlag')" prop="captchaFlag">
<el-radio-group v-model="form.captchaFlag">
<el-radio v-for="(item, index) in captcha_flag_types" :key="index" :label="item.value" border>{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.encFlag')" prop="encFlag">
<el-radio-group v-model="form.encFlag">
<el-radio v-for="(item, index) in enc_flag_types" :key="index" :label="item.value" border>{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('client.onlineQuantity')" prop="onlineQuantity">
<el-radio-group v-model="form.onlineQuantity">
<el-radio v-for="(item, index) in enc_flag_types" :key="index" :label="item.value" border>{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
</el-collapse>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button formDialogRef @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button formDialogRef type="primary" @click="onSubmit">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" name="SysOauthClientDetailsDialog" setup>
// /
import {useDict} from '/@/hooks/dict';
import {useMessage} from "/@/hooks/message";
import {addObj, getObj, putObj} from '/@/api/admin/client'
import {useI18n} from "vue-i18n"
const emit = defineEmits(['refresh']);
const {t} = useI18n();
//
const dataFormRef = ref();
const visible = ref(false)
//
const {grant_types,common_status,captcha_flag_types,enc_flag_types} = useDict('grant_types','common_status','captcha_flag_types','enc_flag_types')
//
const form = reactive({
id: '',
clientId: '',
clientSecret: '',
scope: '',
authorizedGrantTypes: [],
webServerRedirectUri: '',
authorities: '',
accessTokenValidity: '',
refreshTokenValidity: '',
additionalInformation: '',
autoapprove: '',
delFlag: '',
createBy: '',
updateBy: '',
createTime: '',
updateTime: '',
tenantId: '',
});
const collapseActive = ref(false)
//
const dataRules = ref({
clientId: [{required: true, message: '编号不能为空', trigger: 'blur'}],
clientSecret: [{required: true, message: '密钥不能为空', trigger: 'blur'}],
scope: [{required: true, message: '域不能为空', trigger: 'blur'}],
authorizedGrantTypes: [{required: true, message: '授权模式不能为空', trigger: 'blur'}],
accessTokenValidity: [{required: true, message: '令牌时效不能为空', trigger: 'blur'}],
refreshTokenValidity: [{required: true, message: '刷新时效不能为空', trigger: 'blur'}],
})
//
const openDialog = (id: string) => {
visible.value = true
form.id = ''
//
if (dataFormRef.value) {
dataFormRef.value.resetFields()
}
// sysOauthClientDetails
if (id) {
form.id = id
getsysOauthClientDetailsData(id)
}
};
//
const onSubmit = () => {
dataFormRef.value.validate((valid: boolean) => {
if (!valid) {
return false
}
//
if (form.id) {
putObj(form).then(() => {
useMessage().success(t('common.editSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
})
} else {
addObj(form).then(() => {
useMessage().success(t('common.addSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
})
}
})
}
//
const getsysOauthClientDetailsData = (id: string) => {
//
getObj(id).then((res: any) => {
Object.assign(form, res.data)
})
};
//
defineExpose({
openDialog
});
</script>

View File

@ -0,0 +1,45 @@
export default {
client: {
index: 'index',
importsysOauthClientDetailsTip: 'import SysOauthClientDetails',
id: 'id',
clientId: 'clientId',
resourceIds: 'resourceIds',
clientSecret: 'clientSecret',
scope: 'scope',
authorizedGrantTypes: 'authorizedGrantTypes',
webServerRedirectUri: 'webServerRedirectUri',
authorities: 'authorities',
accessTokenValidity: 'accessTokenValidity',
refreshTokenValidity: 'refreshTokenValidity',
additionalInformation: 'additionalInformation',
autoapprove: 'autoapprove',
delFlag: 'delFlag',
createBy: 'createBy',
updateBy: 'updateBy',
createTime: 'createTime',
updateTime: 'updateTime',
tenantId: 'tenantId',
captchaFlag: 'captchaFlag',
encFlag: 'encFlag',
onlineQuantity: 'onlineQuantity',
inputIdTip: 'input id',
inputClientIdTip: 'input clientId',
inputResourceIdsTip: 'input resourceIds',
inputClientSecretTip: 'input clientSecret',
inputScopeTip: 'input scope',
inputAuthorizedGrantTypesTip: 'input authorizedGrantTypes',
inputWebServerRedirectUriTip: 'input webServerRedirectUri',
inputAuthoritiesTip: 'input authorities',
inputAccessTokenValidityTip: 'input accessTokenValidity',
inputRefreshTokenValidityTip: 'input refreshTokenValidity',
inputAdditionalInformationTip: 'input additionalInformation',
inputAutoapproveTip: 'input autoapprove',
inputDelFlagTip: 'input delFlag',
inputCreateByTip: 'input createBy',
inputUpdateByTip: 'input updateBy',
inputCreateTimeTip: 'input createTime',
inputUpdateTimeTip: 'input updateTime',
inputTenantIdTip: 'input tenantId',
}
}

View File

@ -0,0 +1,43 @@
export default {
client: {
index: '序号',
importsysOauthClientDetailsTip: '导入终端信息表',
id: 'ID',
clientId: '编号',
resourceIds: '',
clientSecret: '密钥',
scope: '域',
authorizedGrantTypes: '授权模式',
webServerRedirectUri: '回调地址',
authorities: '权限',
accessTokenValidity: '令牌时效',
refreshTokenValidity: '刷新时效',
additionalInformation: '扩展信息',
autoapprove: '自动放行',
createBy: '创建人',
updateBy: '修改人',
createTime: '上传时间',
updateTime: '更新时间',
tenantId: '所属租户',
captchaFlag: '验证码开关',
encFlag: '前端密码加密',
onlineQuantity: '允许同时在线',
inputIdTip: '请输入ID',
inputClientIdTip: '请输入编号',
inputResourceIdsTip: '请输入',
inputClientSecretTip: '请输入密钥',
inputScopeTip: '请输入域',
inputAuthorizedGrantTypesTip: '请输入授权模式',
inputWebServerRedirectUriTip: '请输入回调地址',
inputAuthoritiesTip: '请输入权限',
inputAccessTokenValidityTip: '请输入令牌时效',
inputRefreshTokenValidityTip: '请输入刷新时效',
inputAdditionalInformationTip: '请输入扩展信息',
inputAutoapproveTip: '请输入自动放行',
inputCreateByTip: '请输入创建人',
inputUpdateByTip: '请输入修改人',
inputCreateTimeTip: '请输入上传时间',
inputUpdateTimeTip: '请输入更新时间',
inputTenantIdTip: '请输入所属租户',
}
}

View File

@ -0,0 +1,123 @@
<template>
<div class="layout-padding">
<el-card class="layout-padding-auto">
<el-row>
<div class="mb8" style="width: 100%">
<el-button v-auth="'sys_client_add'" class="ml10" formDialogRef icon="folder-add" type="primary"
@click="formDialogRef.openDialog()">
{{ $t('common.addBtn') }}
</el-button>
<el-button class="ml10" formDialogRef icon="Download" type="primary"
@click="exportExcel">
{{ $t('common.exportBtn') }}
</el-button>
<el-button v-auth="'sys_client_del'" :disabled="multiple" class="ml10" formDialogRef icon="Delete"
type="primary" @click="handleDelete(undefined)">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table v-loading="state.loading" :data="state.dataList" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column align="center" type="selection" width="60"/>
<el-table-column :label="t('client.index')" type="index" width="80"/>
<el-table-column :label="t('client.clientId')" prop="clientId" show-overflow-tooltip/>
<el-table-column :label="t('client.clientSecret')" prop="clientSecret" show-overflow-tooltip/>
<el-table-column :label="t('client.scope')" prop="scope" show-overflow-tooltip/>
<el-table-column :label="t('client.authorizedGrantTypes')" prop="authorizedGrantTypes" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="grant_types" :value="scope.row.authorizedGrantTypes"></dict-tag>
</template>
</el-table-column>
<el-table-column :label="t('client.accessTokenValidity')" prop="accessTokenValidity" show-overflow-tooltip/>
<el-table-column :label="t('client.refreshTokenValidity')" prop="refreshTokenValidity" show-overflow-tooltip/>
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-button v-auth="'sys_client_add'" text type="primary"
@click="formDialogRef.openDialog(scope.row.clientId)">{{ $t('common.editBtn') }}
</el-button>
<el-button v-auth="'sys_client_del'" text type="primary" @click="handleDelete(scope.row)">{{
$t('common.delBtn')
}}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle"/>
</el-card>
<!-- 编辑新增 -->
<form-dialog ref="formDialogRef" @refresh="getDataList()"/>
</div>
</template>
<script lang="ts" name="systemSysOauthClientDetails" setup>
import {BasicTableProps, useTable} from "/@/hooks/table";
import {delObj, fetchList} from "/@/api/admin/client";
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useDict} from '/@/hooks/dict';
import {useI18n} from "vue-i18n";
//
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const {t} = useI18n()
//
const {grant_types} = useDict('grant_types')
//
const formDialogRef = ref()
//
const queryRef = ref()
const showSearch = ref(true)
//
const selectObjs = ref([])
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
downBlobFile
} = useTable(state)
//
const handleSelectionChange = (val: any) => {
selectObjs.value = val
multiple.value = !val.length
}
// excel
const exportExcel = () => {
downBlobFile('/admin/client/export', state.queryForm, 'client.xlsx')
}
//
const handleDelete = (row: any) => {
if (!row) {
selectObjs.value.forEach((val: any) => {
handleDelete(val)
});
return
}
useMessageBox().confirm(t('common.delConfirmText') + row.id)
.then(() => {
delObj(row.id).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
})
};
</script>

View File

@ -1,5 +1,5 @@
<template>
<el-drawer v-model="visible" title="编辑" :size="1200" :with-header="false">
<el-drawer v-model="visible" title="编辑" :size="1200" :with-header="false" :close-on-click-modal="false">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="属性设置" name="field">
<vxe-table ref="fieldTable" border row-key class="sortable-row-gen" :data="fieldList"