Quellcode durchsuchen

修复PgSQL时,库表管理->编辑列 报列名重复、操作不支持错误
库表管理,增加表时,字段类型非字符串时,长度默认为0(sqlsugar内部处理)
el-dialog 样式优化

夜鹰 vor 4 Monaten
Ursprung
Commit
c8dffb6920

+ 11 - 5
Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs

@@ -175,15 +175,21 @@ public class SysDatabaseService : IDynamicApiController, ITransient
     public void UpdateColumn(UpdateDbColumnInput input)
     {
         var db = _db.AsTenant().GetConnectionScope(input.ConfigId);
-        db.DbMaintenance.RenameColumn(input.TableName, input.OldColumnName, input.ColumnName);
-        if (!string.IsNullOrWhiteSpace(input.DefaultValue))
+
+        // 前端未修改列名时,不进行重命名操作,避免报错
+        if (input.OldColumnName != input.ColumnName)
         {
-            db.DbMaintenance.AddDefaultValue(input.TableName, input.ColumnName, input.DefaultValue);
+            db.DbMaintenance.RenameColumn(input.TableName, input.OldColumnName, input.ColumnName);
         }
-        if (db.DbMaintenance.IsAnyColumnRemark(input.ColumnName, input.TableName))
+
+        if (!string.IsNullOrWhiteSpace(input.DefaultValue))
         {
-            db.DbMaintenance.DeleteColumnRemark(input.ColumnName, input.TableName);
+            db.DbMaintenance.AddDefaultValue(input.TableName, input.ColumnName, input.DefaultValue);
         }
+        //if (db.DbMaintenance.IsAnyColumnRemark(input.ColumnName, input.TableName))
+        //{
+        //    db.DbMaintenance.DeleteColumnRemark(input.ColumnName, input.TableName);
+        //}
 
         db.DbMaintenance.AddColumnRemark(input.ColumnName, input.TableName, string.IsNullOrWhiteSpace(input.Description) ? input.ColumnName : input.Description);
     }

+ 3 - 0
Web/src/theme/element.scss

@@ -346,9 +346,11 @@
 			padding: 0 !important;
 			margin: 0 auto !important;
 			position: absolute;
+            max-height: 100vh;
 
 			.el-dialog__body {
 				padding: 18px !important;
+                max-height: calc(100vh - 37px);
 			}
 		}
 	}
@@ -386,6 +388,7 @@
 	padding: 8px;
     border-radius: var(--el-dialog-border-radius) var(--el-dialog-border-radius) 0 0;
 	background: var(--el-color-primary);
+    color: #fff;
     height: 37px;
     line-height: 21px;
 

+ 1 - 0
Web/src/theme/media/scrollbar.scss

@@ -41,6 +41,7 @@
 	}
 	::-webkit-scrollbar-track-piece {
 		background-color: var(--next-bg-main-color);
+        border-radius: 4px;
 	}
 	// 滚动条的设置
 	::-webkit-scrollbar-thumb {

+ 14 - 3
Web/src/views/system/database/component/addTable.vue

@@ -50,7 +50,7 @@
 				</el-table-column>
 				<el-table-column prop="dataType" label="类型" width="150">
 					<template #default="scope">
-						<el-select v-model="scope.row.dataType" class="m-2" placeholder="Select">
+						<el-select v-model="scope.row.dataType" class="m-2" placeholder="Select" @change="handleColTypeChange(scope.row)">
 							<el-option v-for="item in dataTypeList" :key="item.value" :label="item.value" :value="item.value" />
 						</el-select>
 					</template>
@@ -183,13 +183,13 @@ function addPrimaryColumn() {
 function addColumn() {
 	state.tableData.push({
 		columnDescription: '',
-		dataType: 'varchar',
+		//dataType: 'varchar',
 		dbColumnName: '',
 		decimalDigits: 0,
 		isIdentity: 0,
 		isNullable: 1,
 		isPrimarykey: 0,
-		length: 32,
+		//length: 32,
 		key: colIndex,
 		editable: true,
 		isNew: true,
@@ -310,6 +310,17 @@ function handleColDelete(index: number) {
 	state.tableData.splice(index, 1);
 }
 
+// 列类型选择变化
+function handleColTypeChange(record: EditRecordRow) {
+    if (['varchar', 'char', 'nvarchar', 'nchar'].includes(record.dataType as string)) {
+        if ([0, undefined, null].includes(record.length)) {
+            record.length = 32;
+        }
+    } else {
+        record.length = 0;
+    }
+}
+
 // 上移
 function handleColUp(record: EditRecordRow, index: number) {
 	if (record.isNew) {

+ 39 - 58
Web/src/views/system/stressTest/index.vue

@@ -1,47 +1,40 @@
 <template>
 	<div class="sys-stress-test h100 overlay-none">
-		<div>
-			<NoticeBar text="接口压测会占用服务器大量的内存资源,请慎重操作!" style="margin: 4px" />
-		</div>
 		<el-splitter class="smallbar-el-splitter overlay-hidden">
-			<el-splitter-panel size="20%" :min="200">
-				<el-card class="vh80" shadow="hover" header="接口列表" v-loading="state.loading">
-					<el-row :gutter="35">
-						<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb10">
-							<el-select v-model="state.swaggerUrl" @change="queryTreeNode" placeholder="接口分组" size="small">
-								<el-option :label="item.name" :value="item.url" v-for="(item, index) in state.groupList" :key="index" />
-							</el-select>
-						</el-col>
-						<el-col :xs="24" :sm="18" :md="18" :lg="18" :xl="18" class="mb10">
-							<el-input v-model="state.keywords" size="small" placeholder="关键字" clearable />
-						</el-col>
-						<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6" class="mb10">
-							<el-button size="small" icon="ele-Search" v-reclick="1000" @click="queryTreeNode()" />
-						</el-col>
-					</el-row>
-					<el-tree
-						ref="treeRef"
-						class="filter-tree overlay-y vh68"
-						style="padding-bottom: 60px"
-						:data="state.data"
-						:props="{ children: 'children', label: 'summary' }"
-						:filter-node-method="filterNode"
-						node-key="id"
-						highlight-current
-						check-strictly>
-						<template #default="{ node }">
-							{{ node.label }}
-							<span class="node-button" v-if="!node.data.children">
-								<el-button size="small" icon="ele-DataLine" @click="treeNodeTest(node.data)" />
-							</span>
-						</template>
-					</el-tree>
-				</el-card>
+			<el-splitter-panel size="25%" :min="300">
+				<CardPro title="接口列表" full-height shadow="hover" v-loading="state.loading" body-style="display: flex; flex-direction: column;">
+					<el-select v-model="state.swaggerUrl" @change="queryTreeNode" placeholder="接口分组" class="mb10">
+						<el-option :label="item.name" :value="item.url" v-for="(item, index) in state.groupList" :key="index" />
+					</el-select>
+                    <div class="mb10" style="display: flex;">
+                        <el-input v-model="state.keywords" placeholder="关键字" clearable style="flex: 1; margin-right: 10px;" />
+                        <el-button icon="ele-Search" v-reclick="1000" @click="queryTreeNode()" />
+                    </div>
+                    <el-tree ref="treeRef" class="filter-tree overlay-y"
+                        :data="state.data"
+                        :props="{ children: 'children', label: 'summary' }"
+                        :filter-node-method="filterNode"
+                        node-key="id"
+                        highlight-current
+                        check-strictly
+                        style="flex: 1 1 0;"
+                    >
+                        <template #default="{ node }">
+                            {{ node.label }}
+                            <span class="node-button" v-if="!node.data.children">
+                                <el-button size="small" icon="ele-DataLine" @click="treeNodeTest(node.data)" />
+                            </span>
+                        </template>
+                    </el-tree>
+					
+				</CardPro>
 			</el-splitter-panel>
 			<el-splitter-panel :min="200">
-				<el-card class="main-container vh80" shadow="hover" header="缓存数据" v-loading="state.loading" body-style="height:100vh; overflow:auto">
-					<template #header>
-						<el-button type="primary" @click="showDialog(undefined)">开始测试</el-button>
+				<CardPro title="缓存数据" full-height shadow="hover"v-loading="state.loading">
+					<template #suffix>
+                        <div style="display: flex; width: 100%;">
+                            <el-button type="primary" @click="showDialog(undefined)">开始测试</el-button>
+                        </div>
 					</template>
 					<el-descriptions title="压测参数" label-width="180px" :column="2" class="mb20" border>
 						<el-descriptions-item label="请求方式" label-align="left" align="left">
@@ -104,7 +97,7 @@
 							{{ (state.result.percentile999ResponseTime ?? 0).toFixed(2) }}
 						</el-descriptions-item>
 					</el-descriptions>
-				</el-card>
+				</CardPro>
 			</el-splitter-panel>
 		</el-splitter>
 		<EditStressTest ref="editStressTestRef" @refreshData="refreshData" />
@@ -114,10 +107,9 @@
 <script lang="ts" setup name="sysStressTest">
 import { onMounted, reactive, ref } from 'vue';
 import EditStressTest from './component/editStressTest.vue';
-import NoticeBar from '/@/components/noticeBar/index.vue';
+import CardPro from '/@/components/CardPro/index.vue';
 import request, { getToken } from '/@/utils/request';
 import { StressTestOutput } from "/@/api-services";
-import { Splitpanes, Pane } from 'splitpanes';
 import { ElTree } from 'element-plus';
 import 'splitpanes/dist/splitpanes.css';
 import 'vue-json-pretty/lib/styles.css';
@@ -136,13 +128,13 @@ const state = reactive({
 		requestParameters: [[]],
 		queryParameters: [[]],
 		pathParameters: [[]],
-		headers: [[]],
+		headers: [[]] as Array<Array<any>>,
 	},
 	keywords: undefined,
 	swaggerUrl: '/swagger/Default/swagger.json',
 	result: {} as StressTestOutput,
 	data: [] as Array<any>,
-	groupList: [],
+	groupList: [] as Array<any>,
 });
 
 onMounted(async () => {
@@ -195,7 +187,7 @@ const treeNodeTest = async (node: any) => {
 
 const showDialog = async (row: any) => {
 	const newRow = row ?? { ...state.ruleForm };
-	const convertToKeyValuePairs = (params) => {
+	const convertToKeyValuePairs = (params: any) => {
 		if (Array.isArray(params) && params.every(item => Array.isArray(item) && item.length === 2)) {
 			return params
 		} else if (typeof params === 'object' && params !== null) {
@@ -219,7 +211,7 @@ const refreshData = (data: StressTestOutput) => {
 	state.result = data;
 }
 
-const getApiList = (keywords: string | undefined) => {
+const getApiList = (keywords?: string | undefined) => {
 	const emojiPattern = /[\u{2139}\u{2B05}-\u{2B07}\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu;
 	return request(state.swaggerUrl, { method: 'get' }).then(({ data }) => {
 		const pathMap = data.paths;
@@ -239,7 +231,7 @@ const getApiList = (keywords: string | undefined) => {
 					data: apiInfo,
 				});
 		});
-		return result.filter((u) => u.children.length > 0);
+		return result.filter((u: any) => u.children.length > 0);
 	});
 };
 
@@ -255,22 +247,11 @@ const filterNode = (value: string, data: any) => {
 </script>
 
 <style lang="scss" scoped>
-.card-header {
-	width: 100%;
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-}
 :deep(.el-collapse-item) {
 	.el-collapse-item__arrow {
 		float: right;
 	}
 }
-:deep(.main-container) {
-	.el-card__header {
-		padding: 8px;
-	}
-}
 .node-button {
 	position: absolute;
 	scale: 0.7;