Просмотр исходного кода

CardPro 组件增加 full-height 自适应100%高度属性

夜鹰 8 месяцев назад
Родитель
Сommit
50502cd1d8

+ 26 - 1
Web/src/components/CardPro/README.md

@@ -4,6 +4,16 @@
 
 ---
 
+## 属性
+
+| 属性名 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | ---  |
+| title | 卡片的标题 | `string` | — |
+| prefix-icon | 标题前方的图标 | `string` | — |
+| suffix | header 右侧的内容,可以传入文本内容,也可以通过 `#footer` 传入 `solt`  | `string` | — |
+| size | 尺寸, 可取值有 `large` 、`default` 、 `small` | `enum` | — |
+| full-height | 是否 100% 高度,设置为 `true` 后,卡片将使用 flex 布局,父元素需有高度。卡片内容区将根据父元素高度自适应,无需再设置卡片 `style="height:100%" ` 和 `body-style="height:100%"` 。 | `boolean` | false |
+
 ## 如何使用
 
 ### 基本用法
@@ -69,6 +79,21 @@ import CardPro from '/@/components/CardPro/index.vue';
 </script>
 ```
 
+### 自适应100%高度
+
+设置 `full-height` 属性为 `true` 即可
+
+```html
+<template>
+    <card-pro title="标题" :full-height="true">
+        <!-- 你的内容 -->
+    </card-pro>
+</template>
+<script lang="ts" setup>
+import CardPro from '/@/components/CardPro/index.vue';
+</script>
+```
+
 ---
 
-最新更新于 2025.10.10
+最新更新于 2025.10.15

+ 20 - 3
Web/src/components/CardPro/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <el-card v-bind="$attrs" :class="sizeClass">
+    <el-card v-bind="$attrs" :class="[sizeClass, fullHeight ? 'full-height' : '']">
         <template #header v-if="title || $slots.prefix || prefixIcon || $slots.suffix || suffix">
             <div class="cardpro-header">
                 <div v-if="$slots.prefix || prefixIcon" class="cardpro-header-prefix">
@@ -37,7 +37,8 @@ const props = defineProps({
     title: { type: String },
     prefixIcon: { type: String },
     suffix: { type: String },
-    size: useSizeProp
+    size: useSizeProp,
+    fullHeight: { type: Boolean, default: false }
 });
 
 // 获取全局组件大小
@@ -63,7 +64,13 @@ const sizeClass = computed(() => {
         align-items: center;
         margin-top: 1px;
     }
-    &-title { flex: 1; padding: var(--cardpro-padding) 0; }
+    &-title { 
+        flex: 1; 
+        padding: var(--cardpro-padding) 0; 
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+    }
     &-suffix {
         height: 100%;
         margin-left: 5px;
@@ -86,4 +93,14 @@ const sizeClass = computed(() => {
 :deep(.el-card__body) {
     padding: var(--cardpro-padding);
 }
+
+.full-height {
+    display: flex;
+    flex-direction:column;
+    height: 100%;
+    
+    :deep(.el-card__body) {
+        flex: 1;
+    }
+}
 </style>

+ 5 - 1
Web/src/theme/element.scss

@@ -294,10 +294,14 @@
 
 /* Tabs 标签页
 ------------------------------- */
+.el-tabs__header {
+    border-bottom: 1px solid var(--el-border-color-light);
+}
 .el-tabs__nav-wrap::after {
-	height: 1px !important;
+	content: none;
 }
 
+
 /* Dropdown 下拉菜单
 ------------------------------- */
 .el-dropdown-menu {

+ 15 - 32
Web/src/views/system/cache/index.vue

@@ -1,25 +1,19 @@
 <template>
 	<div class="sys-cache-container">
-		<div>
+		<!-- <div>
 			<NoticeBar text="系统缓存数据管理,请慎重操作!" style="margin: 4px" />
-		</div>
+		</div> -->
 
 		<el-splitter class="smallbar-el-splitter">
 			<el-splitter-panel size="20%" :min="200">
-				<el-card shadow="hover" header="缓存列表" v-loading="state.loading" style="height: 100%" body-style="height:100%; overflow:auto">
-					<template #header>
-						<div class="card-header">
-							<span>缓存列表</span>
-							<div>
-								<el-button icon="ele-Refresh" size="small" type="success" circle plain @click="handleQuery" v-auth="'sysCache:keyList'" />
-								<el-button icon="ele-DeleteFilled" size="small" type="danger" circle plain @click="clearCache" v-auth="'sysCache:clear'"> </el-button>
-							</div>
-						</div>
+				<CardPro title="缓存列表" v-loading="state.loading" full-height body-style="overflow:auto">
+					<template #suffix>
+						<el-button icon="ele-Refresh" type="success" circle plain @click="handleQuery" v-auth="'sysCache:keyList'" />
+                        <el-button icon="ele-DeleteFilled" type="danger" circle plain @click="clearCache" v-auth="'sysCache:clear'"> </el-button>
 					</template>
 					<el-tree
 						ref="treeRef"
 						class="filter-tree"
-						style="padding-bottom: 60px"
 						:data="state.cacheData"
 						node-key="id"
 						:props="{ children: 'children', label: 'name' }"
@@ -30,18 +24,15 @@
 						default-expand-all
 						accordion
 					/>
-				</el-card>
+				</CardPro>
 			</el-splitter-panel>
 			<el-splitter-panel :min="200">
-				<el-card shadow="hover" header="缓存数据" v-loading="state.loading1" style="height: 100%" body-style="height:100%; overflow:auto">
-					<template #header>
-						<div class="card-header">
-							<span>{{ `缓存数据${state.cacheKey ? `【${state.cacheKey}】` : ''}` }}</span>
-							<el-button icon="ele-Delete" size="small" type="danger" @click="delCache" v-auth="'sysCache:delete'"> 删除缓存 </el-button>
-						</div>
-					</template>
-					<vue-json-pretty :data="state.cacheValue" showLength showIcon showLineNumber showSelectController style="padding-bottom: 60px" />
-				</el-card>
+				<CardPro :title="`缓存数据${state.cacheKey ? `【${state.cacheKey}】` : ''}`" v-loading="state.loading1" full-height body-style="overflow:auto">
+                    <template #suffix>
+                        <el-button icon="ele-Delete" type="danger" @click="delCache" v-auth="'sysCache:delete'"> 删除缓存 </el-button>
+                    </template>
+                    <vue-json-pretty :data="state.cacheValue" showLength showIcon showLineNumber showSelectController />
+				</CardPro>
 			</el-splitter-panel>
 		</el-splitter>
 	</div>
@@ -50,10 +41,10 @@
 <script lang="ts" setup name="sysCache">
 import { onMounted, reactive, ref } from 'vue';
 import { ElMessageBox, ElMessage, ElTree } from 'element-plus';
-import NoticeBar from '/@/components/noticeBar/index.vue';
+// import NoticeBar from '/@/components/noticeBar/index.vue';
+import CardPro from '/@/components/CardPro/index.vue';
 import VueJsonPretty from 'vue-json-pretty';
 import 'vue-json-pretty/lib/styles.css';
-//import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 
 import { getAPI } from '/@/utils/axios-utils';
@@ -171,11 +162,3 @@ const nodeClick = async (node: any) => {
 	state.loading1 = false;
 };
 </script>
-
-<style lang="scss" scoped>
-.card-header {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-}
-</style>

+ 70 - 54
Web/src/views/system/stressTest/component/editStressTest.vue

@@ -31,75 +31,91 @@
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="每轮请求数" :rules="[{ required: true, message: '每轮请求数不能为空', trigger: 'blur' }]">
-							<el-input-number v-model="state.ruleForm.numberOfRequests" step="100" placeholder="每轮请求数" />
+							<el-input-number v-model="state.ruleForm.numberOfRequests" :step="100" placeholder="每轮请求数" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="最大并发量">
-							<el-input-number v-model="state.ruleForm.maxDegreeOfParallelism" step="5" placeholder="最大并发量" />
+							<el-input-number v-model="state.ruleForm.maxDegreeOfParallelism" :step="5" placeholder="最大并发量" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
 						<el-tabs v-model="state.activeName" addable @tab-add="addParams()">
 							<el-tab-pane label="Headers" name="1">
-								<el-row :gutter="25" class="w100">
-									<template v-for="(item, index) in state.ruleForm.headers" :key="index">
-										<el-col :xs="24" :sm="2" :md="2" :lg="2" :xl="2" class="mb10">
-											<el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.headers.splice(index,1)" />
-										</el-col>
-										<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6" class="mb10">
-											<el-input v-model="item[0]" placeholder="参数名" clearable />
-										</el-col>
-										<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16" class="mb10">
-											<el-input v-model="item[1]" placeholder="参数值" clearable />
-										</el-col>
-									</template>
-								</el-row>
+								<template v-for="(item, index) in state.ruleForm.headers" :key="index">
+                                    <div class="flex flex-items-center">
+                                        <div class="flex-auto">
+                                            <el-row :gutter="15" class="w100">
+                                                <el-col :xs="24" :sm="7" :md="7" :lg="7" :xl="7" class="mt5 mb5">
+                                                    <el-input v-model="item[0]" placeholder="参数名" clearable />
+                                                </el-col>
+                                                <el-col :xs="24" :sm="17" :md="17" :lg="17" :xl="17" class="mt5 mb5">
+                                                    <el-input v-model="item[1]" placeholder="参数值" clearable />
+                                                </el-col>
+                                            </el-row>
+                                        </div>
+                                        <div style="width: 40px;">
+                                            <el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.headers.splice(index,1)" />
+                                        </div>
+                                    </div>
+                                </template>
 							</el-tab-pane>
 							<el-tab-pane label="Body" name="2">
-								<el-row :gutter="25" class="w100">
-									<template v-for="(item, index) in state.ruleForm.requestParameters" :key="index">
-										<el-col :xs="24" :sm="2" :md="2" :lg="2" :xl="2" class="mb10">
-											<el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.requestParameters.splice(index,1)" />
-										</el-col>
-										<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6" class="mb10">
-											<el-input v-model="item[0]" placeholder="参数名" clearable />
-										</el-col>
-										<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16" class="mb10">
-											<el-input v-model="item[1]" placeholder="参数值" clearable />
-										</el-col>
-									</template>
-								</el-row>
+                                <template v-for="(item, index) in state.ruleForm.requestParameters" :key="index">
+                                    <div class="flex flex-items-center">
+                                        <div class="flex-auto">
+                                            <el-row :gutter="15" class="w100">
+                                                <el-col :xs="24" :sm="7" :md="7" :lg="7" :xl="7" class="mt5 mb5">
+                                                    <el-input v-model="item[0]" placeholder="参数名" clearable />
+                                                </el-col>
+                                                <el-col :xs="24" :sm="17" :md="17" :lg="17" :xl="17" class="mt5 mb5">
+                                                    <el-input v-model="item[1]" placeholder="参数值" clearable />
+                                                </el-col>
+                                            </el-row>
+                                        </div>
+                                        <div style="width: 40px;">
+                                            <el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.requestParameters.splice(index,1)" />
+                                        </div>
+                                    </div>
+                                </template>
 							</el-tab-pane>
 							<el-tab-pane label="Path" name="3">
-								<el-row :gutter="25" class="w100">
-									<template v-for="(item, index) in state.ruleForm.pathParameters" :key="index">
-										<el-col :xs="24" :sm="2" :md="2" :lg="2" :xl="2" class="mb10">
-											<el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.pathParameters.splice(index,1)" />
-										</el-col>
-										<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6" class="mb10">
-											<el-input v-model="item[0]" placeholder="参数名" clearable />
-										</el-col>
-										<el-col :xs="24" :sm="14" :md="14" :lg="14" :xl="14" class="mb10">
-											<el-input v-model="item[1]" placeholder="参数值" clearable/>
-										</el-col>
-									</template>
-								</el-row>
+                                <template v-for="(item, index) in state.ruleForm.pathParameters" :key="index">
+                                    <div class="flex flex-items-center">
+                                        <div class="flex-auto">
+                                            <el-row :gutter="15" class="w100">
+                                                <el-col :xs="24" :sm="7" :md="7" :lg="7" :xl="7" class="mt5 mb5">
+                                                    <el-input v-model="item[0]" placeholder="参数名" clearable />
+                                                </el-col>
+                                                <el-col :xs="24" :sm="17" :md="17" :lg="17" :xl="17" class="mt5 mb5">
+                                                    <el-input v-model="item[1]" placeholder="参数值" clearable/>
+                                                </el-col>
+                                            </el-row>
+                                        </div>
+                                        <div style="width: 40px;">
+                                            <el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.pathParameters.splice(index,1)" />
+                                        </div>
+                                    </div>
+                                </template>
 							</el-tab-pane>
 							<el-tab-pane label="Query" name="4">
-								<el-row :gutter="25" class="w100">
-									<template v-for="(item, index) in state.ruleForm.queryParameters" :key="index">
-										<el-col :xs="24" :sm="2" :md="2" :lg="2" :xl="2" class="mb10">
-											<el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.queryParameters.splice(index,1)" />
-										</el-col>
-										<el-col :xs="24" :sm="6" :md="6" :lg="6" :xl="6" class="mb10">
-											<el-input v-model="item[0]" placeholder="参数名" clearable/>
-										</el-col>
-										<el-col :xs="24" :sm="14" :md="14" :lg="14" :xl="14" class="mb10">
-											<el-input v-model="item[1]" placeholder="参数值" clearable/>
-										</el-col>
-									</template>
-								</el-row>
+                                <template v-for="(item, index) in state.ruleForm.queryParameters" :key="index">
+                                    <div class="flex flex-items-center">
+                                        <div class="flex-auto">
+                                            <el-row :gutter="15" class="w100">
+                                                <el-col :xs="24" :sm="7" :md="7" :lg="7" :xl="7" class="mt5 mb5">
+                                                    <el-input v-model="item[0]" placeholder="参数名" clearable/>
+                                                </el-col>
+                                                <el-col :xs="24" :sm="17" :md="17" :lg="17" :xl="17" class="mt5 mb5">
+                                                    <el-input v-model="item[1]" placeholder="参数值" clearable/>
+                                                </el-col>
+                                            </el-row>
+                                        </div>
+                                        <div style="width: 40px;">
+                                            <el-button type="danger" size="small" icon="ele-Delete" text @click="() => state.ruleForm.queryParameters.splice(index,1)" />
+                                        </div>
+                                    </div>
+                                </template>
 							</el-tab-pane>
 						</el-tabs>
 					</el-col>