Procházet zdrojové kódy

Add 完成客户端管理模块

YueYunyun před 1 rokem
rodič
revize
8b6757113a

+ 1 - 0
.gitignore

@@ -65,3 +65,4 @@ build/
 /UI/dist
 /UI/**/dist.rar
 
+*.flattened-pom.xml

+ 14 - 14
SERVER/VberAdminPlusV3/.script/sql/admin.sql

@@ -581,19 +581,19 @@ values ('1080', '租户套餐导出', '122', '5', '#', '', '', 1, 0, 'F', '0', '
         'cloud-download', 'btn btn-light-info', 'handleExport', 100, 1, sysdate(), null, null, '');
 -- 客户端管理按钮
 insert into sys_menu
-values ('1081', '客户端管理查询', '110', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:query', 'eye', '', '',
+values ('1081', '客户端查询', '110', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:query', 'eye', '', '',
         100, 1, sysdate(), null, null, '');
 insert into sys_menu
-values ('1082', '客户端管理新增', '110', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:add', 'plus-square',
+values ('1082', '客户端新增', '110', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:add', 'plus-square',
         'btn btn-light-primary', 'handleCreate', 100, 1, sysdate(), null, null, '');
 insert into sys_menu
-values ('1083', '客户端管理修改', '110', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:edit', 'pencil-square',
+values ('1083', '客户端修改', '110', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:edit', 'pencil-square',
         'btn btn-light-success', 'handleUpdate@1', 100, 1, sysdate(), null, null, '');
 insert into sys_menu
-values ('1084', '客户端管理删除', '110', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:remove', 'dash-square',
+values ('1084', '客户端删除', '110', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:remove', 'dash-square',
         'btn btn-light-danger', 'handleDelete@0', 100, 1, sysdate(), null, null, '');
 insert into sys_menu
-values ('1085', '客户端管理导出', '110', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:export',
+values ('1085', '客户端导出', '110', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:client:export',
         'cloud-download', 'btn btn-light-info', 'handleExport', 100, 1, sysdate(), null, null, '');
 
 -- 在线用户按钮
@@ -859,29 +859,29 @@ insert into sys_dict_data
 values (28, '000000', 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', 100, 1, sysdate(), null, null,
         '停用状态');
 insert into sys_dict_data
-values (30, '000000', 0, '密码认证', 'password', 'sys_grant_type', 'el-check-tag', 'default', 'N', 100, 1, sysdate(),
+values (30, '000000', 0, '密码认证', 'password', 'sys_grant_type', '', 'primary', 'N', 100, 1, sysdate(),
         null, null, '密码认证');
 insert into sys_dict_data
-values (31, '000000', 0, '短信认证', 'sms', 'sys_grant_type', 'el-check-tag', 'default', 'N', 100, 1, sysdate(), null,
+values (31, '000000', 0, '短信认证', 'sms', 'sys_grant_type', '', 'primary', 'N', 100, 1, sysdate(), null,
         null, '短信认证');
 insert into sys_dict_data
-values (32, '000000', 0, '邮件认证', 'email', 'sys_grant_type', 'el-check-tag', 'default', 'N', 100, 1, sysdate(), null,
+values (32, '000000', 0, '邮件认证', 'email', 'sys_grant_type', '', 'primary', 'N', 100, 1, sysdate(), null,
         null, '邮件认证');
 insert into sys_dict_data
-values (33, '000000', 0, '小程序认证', 'xcx', 'sys_grant_type', 'el-check-tag', 'default', 'N', 100, 1, sysdate(), null,
+values (33, '000000', 0, '小程序认证', 'xcx', 'sys_grant_type', '', 'primary', 'N', 100, 1, sysdate(), null,
         null, '小程序认证');
 insert into sys_dict_data
-values (34, '000000', 0, '三方登录认证', 'social', 'sys_grant_type', 'el-check-tag', 'default', 'N', 100, 1, sysdate(),
+values (34, '000000', 0, '三方登录认证', 'social', 'sys_grant_type', '', 'primary', 'N', 100, 1, sysdate(),
         null, null, '三方登录认证');
 insert into sys_dict_data
-values (35, '000000', 0, 'PC', 'pc', 'sys_device_type', '', 'default', 'N', 100, 1, sysdate(), null, null, 'PC');
+values (35, '000000', 0, 'PC', 'pc', 'sys_device_type', '', 'primary', 'N', 100, 1, sysdate(), null, null, 'PC');
 insert into sys_dict_data
-values (36, '000000', 0, '安卓', 'android', 'sys_device_type', '', 'default', 'N', 100, 1, sysdate(), null, null,
+values (36, '000000', 0, '安卓', 'android', 'sys_device_type', '', 'primary', 'N', 100, 1, sysdate(), null, null,
         '安卓');
 insert into sys_dict_data
-values (37, '000000', 0, 'iOS', 'ios', 'sys_device_type', '', 'default', 'N', 100, 1, sysdate(), null, null, 'iOS');
+values (37, '000000', 0, 'iOS', 'ios', 'sys_device_type', '', 'primary', 'N', 100, 1, sysdate(), null, null, 'iOS');
 insert into sys_dict_data
-values (38, '000000', 0, '小程序', 'xcx', 'sys_device_type', '', 'default', 'N', 100, 1, sysdate(), null, null,
+values (38, '000000', 0, '小程序', 'xcx', 'sys_device_type', '', 'primary', 'N', 100, 1, sysdate(), null, null,
         '小程序');
 
 

+ 4 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-oss/.flattened-pom.xml

@@ -25,5 +25,9 @@
       <groupId>com.amazonaws</groupId>
       <artifactId>aws-java-sdk-s3</artifactId>
     </dependency>
+    <dependency>
+      <groupId>cn.hutool</groupId>
+      <artifactId>hutool-crypto</artifactId>
+    </dependency>
   </dependencies>
 </project>

+ 5 - 3
SERVER/VberAdminPlusV3/vber-modules/vber-system/src/main/java/com/vber/system/service/impl/SysClientServiceImpl.java

@@ -5,8 +5,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
 import com.vber.common.core.utils.MapstructUtils;
 import com.vber.common.core.utils.StringUtils;
 import com.vber.common.mybatis.core.page.PageQuery;
@@ -16,6 +14,8 @@ import com.vber.system.domain.bo.SysClientBo;
 import com.vber.system.domain.vo.SysClientVo;
 import com.vber.system.mapper.SysClientMapper;
 import com.vber.system.service.ISysClientService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.util.Collection;
@@ -76,9 +76,11 @@ public class SysClientServiceImpl implements ISysClientService {
     private LambdaQueryWrapper<SysClient> buildQueryWrapper(SysClientBo bo) {
         LambdaQueryWrapper<SysClient> lqw = Wrappers.lambdaQuery();
         lqw.eq(StringUtils.isNotBlank(bo.getClientId()), SysClient::getClientId, bo.getClientId());
-        lqw.eq(StringUtils.isNotBlank(bo.getClientKey()), SysClient::getClientKey, bo.getClientKey());
+        lqw.like(StringUtils.isNotBlank(bo.getClientKey()), SysClient::getClientKey, bo.getClientKey());
         lqw.eq(StringUtils.isNotBlank(bo.getClientSecret()), SysClient::getClientSecret, bo.getClientSecret());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysClient::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getDeviceType()), SysClient::getDeviceType, bo.getDeviceType());
+        lqw.like(StringUtils.isNotBlank(bo.getGrantType()), SysClient::getGrantType, bo.getGrantType());
         lqw.orderByAsc(SysClient::getId);
         return lqw;
     }

+ 68 - 0
UI/VAP_V3.VUE/src/api/system/_client.ts

@@ -0,0 +1,68 @@
+import Rs from '@/core/services/RequestService'
+
+class clientApi {
+    tableUrl = "/system/client/list"
+    exportUrl = "/system/client/export"
+
+    // 查询客户端列表
+    list = (query: any) => {
+        return Rs.get({
+            url: '/system/client/list',
+            params: query,
+            loading: false
+        })
+    }
+
+    // 查询客户端详细
+    get = (id: string) => {
+        return Rs.get({
+            url: '/system/client/' + id,
+            loading: false
+        })
+    }
+
+    // 新增或修改客户端
+    addOrUpdate = (data: any) => {
+        return new Promise((resolve) => {
+            if (data.id) {
+                this.update(data).then((res: any) => {
+                    message.msgSuccess("修改成功")
+                    resolve(res)
+                })
+            } else {
+                this.add(data).then((res: any) => {
+                    message.msgSuccess("新增成功")
+                    resolve(res)
+                })
+            }
+        })
+    }
+
+    // 新增客户端
+    add = (data: any) => {
+        return Rs.post({
+            url: '/system/client',
+            data: data,
+            successAlert: false,
+        })
+    }
+
+    // 修改客户端
+    update = (data: any) => {
+        return Rs.put({
+            url: '/system/client',
+            data: data,
+            successAlert: false,
+        })
+    }
+
+    // 删除客户端
+    del = (id: string | string[]) => {
+        return Rs.del({
+            url: '/system/client/' + id,
+        })
+    }
+
+}
+
+export default clientApi

+ 4 - 2
UI/VAP_V3.VUE/src/api/system/index.ts

@@ -9,7 +9,7 @@ import Dict from "./_dict"
 import Auth from "./_auth"
 import LoginLog from "./_loginLog"
 import operLog from "./_operLog"
-
+import client from "./_client"
 export interface ISystemApi {
 	menuApi: Menu
 	userApi: User
@@ -22,6 +22,7 @@ export interface ISystemApi {
 	authApi: Auth
 	loginLogApi: LoginLog
 	operLogApi: operLog
+	clientApi: client
 }
 
 export const apis: ISystemApi = {
@@ -35,7 +36,8 @@ export const apis: ISystemApi = {
 	dictApi: new Dict(),
 	authApi: new Auth(),
 	loginLogApi: new LoginLog(),
-	operLogApi: new operLog()
+	operLogApi: new operLog(),
+	clientApi: new client()
 }
 
 export default apis

+ 2 - 1
UI/VAP_V3.VUE/src/components/table/VbDataTable.vue

@@ -393,7 +393,8 @@ const defaultHandleFuns = {
 			download(
 				props.exportUrl,
 				{ ...innerQueryParams.value },
-				`${props.exportName ? props.exportName + "_" : ""}${new Date().getTime()}.xlsx`
+				`${props.exportName ? props.exportName + "_" : ""}${new Date().getTime()}.xlsx`,
+				{ method: "POST" }
 			)
 		} else {
 			message.alertError("导出接口方法未配置,请联系管理员")

+ 2 - 0
UI/VAP_V3.VUE/src/components/tag/VbTag.vue

@@ -83,6 +83,7 @@ onMounted(init)
 			<template v-if="values.includes(item.value)">
 				<span
 					v-if="item.type == 'default' || item.type == ''"
+					class="mx-1"
 					:key="item.value"
 					:index="index"
 					:class="item.class"
@@ -92,6 +93,7 @@ onMounted(init)
 				<el-tag
 					v-else
 					:disable-transitions="true"
+					class="mx-1"
 					:key="item.value + ''"
 					:index="index"
 					:type="item.type === 'primary' ? '' : item.type"

+ 292 - 0
UI/VAP_V3.VUE/src/views/system/client/index.vue

@@ -0,0 +1,292 @@
+<script setup lang="ts" name="Client">
+import apis from "@a"
+
+const tableRef = ref()
+const modalRef = ref()
+const opts = reactive({
+	columns: [
+		{ field: "id", name: "id", width: 100, isSort: true, visible: false },
+		{ field: "clientId", name: "客户端 ID", visible: true, isSort: false, width: 240 },
+		{ field: "clientKey", name: "客户端 KEY", visible: true, isSort: false, width: 120 },
+		{ field: "clientSecret", name: "客户端 SECRET", visible: true, width: 150, tooltip: true },
+		{ field: "grantType", name: "授权类型", visible: true, isSort: false, width: "auto" },
+		{ field: "deviceType", name: "设备类型", visible: true, isSort: true, width: 100 },
+		{ field: "activeTimeout", name: "活跃超时时间", visible: true, isSort: true, width: 120 },
+		{ field: "timeout", name: "超时时间", visible: true, isSort: false, width: 100 },
+		{ field: "status", name: "状态", visible: true, isSort: false, width: 80 },
+		{ field: "actions", name: `操作`, width: 150 }
+	],
+	queryParams: {
+		clientKey: undefined,
+		grantType: undefined,
+		deviceType: undefined
+	},
+	searchFormItems: [
+		{
+			field: "clientKey",
+			label: "客户端KEY",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入客户端KEY",
+			component: "I",
+			listeners: {
+				keyup: (e: KeyboardEvent) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			},
+			span: 5
+		},
+		{
+			field: "grantType",
+			label: "授权类型",
+			class: "w-100",
+			required: false,
+			component: "Dict",
+			props: {
+				placeholder: "请选择授权类型",
+				dictType: "sys_grant_type",
+				valueIsNumber: false,
+				type: "select"
+			},
+			span: 5
+		},
+		{
+			field: "deviceType",
+			label: "设备类型",
+			class: "w-100",
+			required: false,
+			component: "Dict",
+			props: {
+				placeholder: "请选择设备类型",
+				dictType: "sys_device_type",
+				valueIsNumber: false,
+				type: "select"
+			},
+			span: 5
+		}
+	] as any,
+	permission: "system:client",
+	handleBtns: [],
+	handleFuns: {
+		handleUpdate: () => {
+			const row = tableRef.value.getSelected()
+			handleUpdate(row)
+		},
+		handleDelete: () => {
+			const rows = tableRef.value.getSelecteds()
+			handleDelete(rows)
+		}
+	},
+	customBtns: [],
+	tableListFun: apis.system.clientApi.list,
+	getEntityFun: apis.system.clientApi.get,
+	deleteEntityFun: apis.system.clientApi.del,
+	exportUrl: apis.system.clientApi.exportUrl,
+	exportName: "Client",
+	modalTitle: "客户端",
+	formItems: [
+		// {
+		// 	field: "clientId",
+		// 	label: "客户端编号",
+		// 	class: "w-100",
+		// 	required: true,
+		// 	placeholder: "请输入客户端编号",
+		// 	component: "I"
+		// },
+		{
+			field: "clientKey",
+			label: "客户端KEY",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入客户端KEY",
+			component: "I"
+		},
+		{
+			field: "clientSecret",
+			label: "客户端秘钥",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入客户端秘钥",
+			component: "I"
+		},
+		{
+			field: "grantTypeList",
+			label: "授权类型",
+			class: "w-100",
+			required: true,
+			component: "Dict",
+			props: {
+				dictType: "sys_grant_type",
+				type: "checkbox",
+				valueIsNumber: false
+			}
+		},
+		{
+			field: "deviceType",
+			label: "设备类型",
+			class: "w-100",
+			required: true,
+			component: "Dict",
+			props: {
+				dictType: "sys_device_type",
+				type: "radio",
+				valueIsNumber: false
+			}
+		},
+		{
+			field: "activeTimeout",
+			label: "活跃超时时间",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入活跃超时时间",
+			component: "I"
+		},
+		{
+			field: "timeout",
+			label: "超时时间",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入超时时间",
+			component: "I"
+		},
+		{
+			field: "status",
+			label: "状态",
+			class: "w-100",
+			required: true,
+			component: "Dict",
+			props: {
+				dictType: "sys_normal_disable",
+				type: "radio",
+				valueIsNumber: false
+			}
+		}
+	] as any,
+	resetForm: () => {
+		form.value = emptyFormData.value
+	},
+	labelWidth: "90px",
+	emptyFormData: {
+		id: undefined,
+		clientId: undefined,
+		clientKey: undefined,
+		clientSecret: undefined,
+		grantTypeList: undefined,
+		deviceType: undefined,
+		activeTimeout: undefined,
+		timeout: undefined,
+		status: undefined
+	}
+})
+const { queryParams, emptyFormData } = toRefs(opts)
+const form = ref<any>(emptyFormData.value)
+
+/** 搜索按钮操作 */
+function handleQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	addDateRange(query, query.dateRangeCreateTime)
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	tableRef.value?.query(query)
+}
+
+/** 重置按钮操作 */
+function resetQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	query.dateRangeCreateTime = [] as any
+	addDateRange(query, query.dateRangeCreateTime)
+	query.dateRangeUpdateTime = [] as any
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	//
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row: any) {
+	tableRef.value.defaultHandleFuns.handleUpdate("", row)
+	form.value.grantTypeList = form.value.grantType.split(",")
+}
+
+/** 删除按钮操作 */
+function handleDelete(rows: any[]) {
+	tableRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+
+/** 提交按钮 */
+function submitForm() {
+	form.value.grantType = form.value.grantTypeList.join(",")
+	apis.system.clientApi.addOrUpdate(form.value).then(() => {
+		handleQuery()
+	})
+}
+</script>
+<template>
+	<div class="app-container">
+		<VbDataTable
+			ref="tableRef"
+			keyField="id"
+			:columns="opts.columns"
+			:handle-perm="opts.permission"
+			:handle-btns="opts.handleBtns"
+			:handle-funs="opts.handleFuns"
+			:search-form-items="opts.searchFormItems"
+			:custom-btns="opts.customBtns"
+			:remote-fun="opts.tableListFun"
+			:get-entity-fun="opts.getEntityFun"
+			:delete-entity-fun="opts.deleteEntityFun"
+			:export-url="opts.exportUrl"
+			:export-name="opts.exportName"
+			:modal="modalRef"
+			:reset-form-fun="opts.resetForm"
+			v-model:form-data="form"
+			v-model:query-params="queryParams"
+			:check-multiple="true"
+			:reset-search-form-fun="resetQuery"
+			:custom-search-fun="handleQuery">
+			<template #grantType="{ row }">
+				<DictTag
+					type="sys_grant_type"
+					:value-is-number="false"
+					:value="row.grantType ? row.grantType.split(',') : []"></DictTag>
+			</template>
+			<template #deviceType="{ row }">
+				<DictTag type="sys_device_type" :value-is-number="false" :value="row.deviceType"></DictTag>
+			</template>
+			<template #status="{ row }">
+				<DictTag type="sys_normal_disable" :value-is-number="false" :value="row.status"></DictTag>
+			</template>
+			<template #actions="{ row }">
+				<vb-tooltip content="修改" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleUpdate(row)"
+						v-hasPermission="'system:client:edit'">
+						<template #icon>
+							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+				<vb-tooltip content="删除" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleDelete([row])"
+						v-hasPermission="'system:client:remove'">
+						<template #icon>
+							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+			</template>
+		</VbDataTable>
+		<VbModal
+			v-model:modal="modalRef"
+			:title="opts.modalTitle"
+			:form-data="form"
+			:form-items="opts.formItems"
+			:label-width="opts.labelWidth"
+			append-to-body
+			@confirm="submitForm"></VbModal>
+	</div>
+</template>