十二、【核心功能篇】测试用例列表与搜索:高效展示和查找海量用例

article/2025/8/6 7:18:54

【核心功能篇】测试用例列表与搜索:高效展示和查找海量用例

    • 前言
      • 准备工作
      • 第一步:更新 API 服务以支持分页和更完善的搜索
      • 第二步:创建测试用例列表页面组件 (`src/views/testcase/TestCaseListView.vue`)
      • 第三步:测试列表、搜索、筛选和分页
    • 总结

前言

当测试用例数量逐渐增多,一个简单罗列所有用例的列表将变得非常低效和不友好。我们需要:

  • 清晰的列表展示: 以表格形式清晰展示用例的关键信息。
  • 分页加载: 避免一次性加载过多数据导致页面卡顿。
  • 关键字搜索: 能够根据用例名称、描述等关键词快速查找。
  • 条件筛选: 能够根据所属项目、模块、优先级、类型等条件进行筛选。
  • 便捷的操作: 在列表行内直接提供编辑、删除等快捷操作入口。

我们将创建一个 TestCaseListView.vue 组件,并利用 Element Plus 的 ElTableElPaginationElForm 组件来实现这些功能。

准备工作

  1. 前端项目就绪: test-platform/frontend 项目可以正常运行 (npm run dev)。
  2. 后端 API 运行中: Django 后端服务运行(python manage.py runserver
    ),测试用例的 API (/api/testcases/) 可用,并且支持通过查询参数进行过滤 (如 project_id, module_id, search 等) 和分页。
  3. Axios 和 API 服务已封装: utils/request.tsapi/testcase.ts (包含 getTestCaseList 函数) 已配置好。
  4. Element Plus 集成完毕。
  5. 测试用例编辑页面可用: 我们将从列表页跳转到编辑页。

第一步:更新 API 服务以支持分页和更完善的搜索

我们的后端 DRF TestCaseViewSet 默认就支持分页 (如果继承了 ModelViewSet 并配置了 pagination_class),并且通过 SearchFilterDjangoFilterBackend 可以实现搜索和过滤。我们需要确保前端的 API 服务函数能够传递这些参数,并正确处理分页响应。

1. 修改 frontend/src/api/testcase.ts 中的类型和函数:
DRF 分页响应通常包含 count, next, previous, results 字段。
在这里插入图片描述

// test-platform/frontend/src/api/testcase.ts
import request from '@/utils/request'
import type { AxiosPromise } from 'axios'// TestCase 接口定义保持不变...
export interface TestCase {id: number;name: string;description: string | null;module: number;module_name?: string;project_id?: number;project_name?: string;priority: 'P0' | 'P1' | 'P2' | 'P3';priority_display?: string;precondition: string | null;steps_text: string;expected_result: string;case_type: 'functional' | 'api' | 'ui';case_type_display?: string;maintainer: string | null;create_time: string;update_time: string;
}// 更新:定义分页响应的通用接口
export interface PaginatedResponse<T> {count: number;next: string | null;previous: string | null;results: T[];
}// 更新:TestCaseListResponse 现在使用 PaginatedResponse
export type TestCaseListResponse = PaginatedResponse<TestCase>// 定义获取测试用例列表的参数类型
export interface GetTestCaseListParams {page?: number;page_size?: number; // 后端 DRF 通常用 page_sizesearch?: string; // 关键词搜索project_id?: number | null;module_id?: number | null;priority?: string | null;case_type?: string | null;ordering?: string; // 排序字段,例如 '-create_time'
}// 1. 获取测试用例列表 (支持分页、搜索、过滤、排序)
export function getTestCaseList(params?: GetTestCaseListParams): AxiosPromise<TestCaseListResponse> {return request({url: '/testcases/',method: 'get',params // 将所有参数传递给后端})
}// createTestCase, getTestCaseDetail, updateTestCase, deleteTestCase 函数保持不变...
// ...

关键变更:

  • PaginatedResponse<T>: 定义了一个通用的分页响应接口。
  • TestCaseListResponse: 类型更新为 PaginatedResponse<TestCase>
  • GetTestCaseListParams: 定义了更详细的查询参数类型,包括 page, page_size, search 以及各种过滤条件。
  • getTestCaseList 函数现在接收 GetTestCaseListParams 类型的参数。

2. 确保后端 TestCaseViewSet 支持搜索和过滤:
在你的 Django 后端 api/views.py 中的 TestCaseViewSet,你需要确保配置了相应的 filter_backendssearch_fields / filterset_fields
在这里插入图片描述
在这里插入图片描述

# test-platform/api/views.py
from rest_framework import viewsets, filters # 确保导入 filters
from django_filters.rest_framework import DjangoFilterBackend # 确保导入 DjangoFilterBackend
# ... 其他导入 ...
from .models import TestCase
from .serializers import TestCaseSerializerclass TestCaseViewSet(viewsets.ModelViewSet):queryset = TestCase.objects.all().order_by('-update_time') # 默认排序serializer_class = TestCaseSerializerfilter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]# DjangoFilterBackend 的精确匹配字段filterset_fields = {'module__project_id': ['exact'], # /api/testcases/?module__project_id=1'module_id': ['exact'],         # /api/testcases/?module_id=5'priority': ['exact'],          # /api/testcases/?priority=P1'case_type': ['exact'],         # /api/testcases/?case_type=api}# SearchFilter 的模糊搜索字段search_fields = ['name', 'description', 'precondition', 'steps_text', 'expected_result','maintainer'] # /api/testcases/?search=登录# OrderingFilter 允许排序的字段ordering_fields = ['id', 'name', 'priority', 'case_type', 'create_time', 'update_time']# pagination_class = YourCustomPagination # 如果使用了自定义分页器

重要:

  • 要使用 DjangoFilterBackend,你需要先安装 django-filter 包。在你的 Django 项目的虚拟环境中运行:

    pip install django-filter
    

    在这里插入图片描述

  • INSTALLED_APPS 中注册 'django_filters'
    在这里插入图片描述

      # settings.pyINSTALLED_APPS = [# ... 其他应用 ...'rest_framework','django_filters', # 添加这一行'api',# ...]
    
  • filterset_fields 用于精确匹配,例如选择某个项目下的用例。我们这里用 module__project_id 来通过模块关联到项目进行筛选。

  • search_fields 用于关键词的模糊搜索。

  • ordering_fields 允许前端指定排序。

  • DRF 的默认分页器 (PageNumberPagination) 使用 pagepage_size (或 limit/offset 如果是 LimitOffsetPagination) 参数。确保前端传递的参数名与后端分页器配置一致。

第二步:创建测试用例列表页面组件 (src/views/testcase/TestCaseListView.vue)

这个组件将包含搜索/筛选表单、用例表格和分页控件。
在上一篇【核心功能】测试用例管理:设计强大的用例编辑界面,我们已经在frontend/src/router/index.ts中添加了用例列表的路由信息,如下所示:
在这里插入图片描述

// test-platform/frontend/src/router/index.ts
// ... (在 Layout 的 children 中添加){path: '/testcases', // 用例列表页name: 'testcases',component: () => import('../views/testcase/TestCaseListView.vue'), //之前的文件路径是'../views/project/TestCaseListView.vue',这个是不对的,所以这里进行了更正。meta: { title: '用例管理', requiresAuth: true }},
// ...

a. 创建文件:
src/views/testcase/TestCaseListView.vue 尚不存在,现在来创建它。

b. 编写 TestCaseListView.vue
在这里插入图片描述

<!-- test-platform/frontend/src/views/testcase/TestCaseListView.vue -->
<template><div class="testcase-list-view" v-loading="pageLoading"><el-card class="filter-card"><el-form :inline="true" :model="queryParams" ref="queryFormRef" @submit.prevent="handleSearch"><el-form-item label="所属项目" prop="project_id"><el-selectv-model="queryParams.project_id"placeholder="请选择项目"clearablestyle="width: 180px"@change="onProjectChange"@focus="fetchProjectsForSelect":loading="projectSelectLoading"><el-option v-for="item in projectOptions" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item><el-form-item label="所属模块" prop="module_id"><el-selectv-model="queryParams.module_id"placeholder="请选择模块"clearablefilterablestyle="width: 180px":disabled="!queryParams.project_id":loading="moduleSelectLoading"><el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item><el-form-item label="优先级" prop="priority"><el-select v-model="queryParams.priority" placeholder="优先级" clearable style="width: 120px"><el-option label="P0" value="P0" /><el-option label="P1" value="P1" /><el-option label="P2" value="P2" /><el-option label="P3" value="P3" /></el-select></el-form-item><el-form-item label="类型" prop="case_type"><el-select v-model="queryParams.case_type" placeholder="用例类型" clearable style="width: 140px"><el-option label="功能测试" value="functional" /><el-option label="接口测试" value="api" /><el-option label="UI测试" value="ui" /></el-select></el-form-item><el-form-item label="关键词" prop="search"><el-input v-model="queryParams.search" placeholder="名称/描述/步骤等" clearable style="width: 200px" /></el-form-item><el-form-item><el-button type="primary" :icon="SearchIcon" @click="handleSearch">搜索</el-button><el-button :icon="RefreshIcon" @click="handleReset">重置</el-button></el-form-item></el-form></el-card><el-card class="table-card"><template #header><div class="card-header"><span>测试用例列表</span><el-button type="primary" :icon="PlusIcon" @click="navigateToCreate">新建用例</el-button></div></template><el-table :data="testCases" v-loading="tableLoading" style="width: 100%" empty-text="暂无测试用例数据"><el-table-column prop="id" label="ID" width="80" sortable /><el-table-column prop="name" label="用例名称" min-width="200" show-overflow-tooltip sortable><template #default="scope"><el-link type="primary" @click="handleEdit(scope.row.id)">{{ scope.row.name }}</el-link></template></el-table-column><el-table-column prop="project_name" label="所属项目" width="150" show-overflow-tooltip /><el-table-column prop="module_name" label="所属模块" width="150" show-overflow-tooltip /><el-table-column prop="priority_display" label="优先级" width="100" sortable><template #default="scope"><el-tag :type="getPriorityTagType(scope.row.priority)">{{ scope.row.priority_display || scope.row.priority }}</el-tag></template></el-table-column><el-table-column prop="case_type_display" label="类型" width="120" sortable><template #default="scope">{{ scope.row.case_type_display || getCaseTypeText(scope.row.case_type) }}</template></el-table-column><el-table-column prop="maintainer" label="维护人" width="120" show-overflow-tooltip /><el-table-column prop="update_time" label="最后更新" width="170" sortable><template #default="scope">{{ formatDateTime(scope.row.update_time) }}</template></el-table-column><el-table-column label="操作" width="150" fixed="right"><template #default="scope"><el-button size="small" type="warning" :icon="EditIcon" @click="handleEdit(scope.row.id)">编辑</el-button><el-popconfirmtitle="确定要删除这个用例吗?"@confirm="handleDelete(scope.row.id)"><template #reference><el-button size="small" type="danger" :icon="DeleteIcon">删除</el-button></template></el-popconfirm></template></el-table-column></el-table><el-paginationv-if="totalCases > 0"class="pagination-container":current-page="queryParams.page":page-size="queryParams.page_size":page-sizes="[10, 20, 50, 100]"layout="total, sizes, prev, pager, next, jumper":total="totalCases"@size-change="handleSizeChange"@current-change="handlePageChange"/></el-card></div>
</template><script setup lang="ts">
import { ref, reactive, onMounted, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router' // 导入 useRoute
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { Search as SearchIcon, Refresh as RefreshIcon, Plus as PlusIcon, Edit as EditIcon, Delete as DeleteIcon } from '@element-plus/icons-vue'
import { getTestCaseList, deleteTestCase, type TestCase, type GetTestCaseListParams } from '@/api/testcase'
import { getProjectList, type Project } from '@/api/project'
import { getModuleList as fetchModulesApi, type Module as ApiModule } from '@/api/module' // 避免与组件内变量冲突const router = useRouter()
const route = useRoute() // 获取当前路由信息const pageLoading = ref(false) // 页面级加载,例如初始加载项目模块选项
const tableLoading = ref(false)
const queryFormRef = ref<FormInstance>()const testCases = ref<TestCase[]>([])
const totalCases = ref(0)const queryParams = reactive<GetTestCaseListParams>({page: 1,page_size: 10,search: '',project_id: null,module_id: null,priority: null,case_type: null,ordering: '-update_time', // 默认按更新时间降序
})const projectOptions = ref<Project[]>([])
const moduleOptions = ref<ApiModule[]>([])
const projectSelectLoading = ref(false)
const moduleSelectLoading = ref(false)// 获取测试用例列表
const fetchTestCases = async () => {tableLoading.value = truetry {const response = await getTestCaseList(queryParams)console.log('API返回数据:', response.data) // 添加这行用于调试// 检查返回的数据结构if (response.data && Array.isArray(response.data.results)) {testCases.value = response.data.resultstotalCases.value = response.data.count} else if (response.data && Array.isArray(response.data.entities)) {// 如果API返回的是entities而不是resultstestCases.value = response.data.entitiestotalCases.value = response.data.total} else if (Array.isArray(response.data)) {// 如果API直接返回数组testCases.value = response.datatotalCases.value = response.data.length} else {console.error('API返回的数据结构不符合预期:', response.data)testCases.value = []totalCases.value = 0}} catch (error) {console.error('获取测试用例列表失败:', error)testCases.value = []totalCases.value = 0} finally {tableLoading.value = false}
}// 获取项目列表用于筛选器
const fetchProjectsForSelect = async () => {if (projectOptions.value.length > 0) return; // 避免重复加载projectSelectLoading.value = truetry {const response = await getProjectList({ page_size: 1000 }) // 获取足够多的项目,或实现分页/搜索选择器projectOptions.value = response.data // 假设不分页,或取第一页} catch (error) {console.error('获取项目选项失败:', error)} finally {projectSelectLoading.value = false}
}// 根据选中的项目获取模块列表用于筛选器
const fetchModulesForSelect = async (projectId: number | null) => {moduleOptions.value = [] // 清空旧模块queryParams.module_id = null // 清空已选模块if (!projectId) return;moduleSelectLoading.value = truetry {const response = await fetchModulesApi(projectId) // 调用 api/module.ts 中的 getModuleListmoduleOptions.value = response.data} catch (error) {console.error('获取模块选项失败:', error)} finally {moduleSelectLoading.value = false}
}// 监听项目选择变化,动态加载模块
watch(() => queryParams.project_id, (newProjectId) => {fetchModulesForSelect(newProjectId)
})// 页面加载时初始化
onMounted(async () => {pageLoading.value = true;await fetchProjectsForSelect(); // 先加载项目选项// 检查路由查询参数中是否有 moduleId (例如从用例编辑页跳转过来)const routeModuleId = route.query.moduleId as string | undefined;if (routeModuleId) {queryParams.module_id = Number(routeModuleId);// 如果有 moduleId,尝试找到其对应的 projectId 并设置const moduleDetail = moduleOptions.value.find(m => m.id === queryParams.module_id) ||(await fetchModulesApi().then(res => res.data.find(m => m.id === Number(routeModuleId)))); // 如果初始 moduleOptions 为空,则重新获取所有模块来查找if(moduleDetail && moduleDetail.project){queryParams.project_id = moduleDetail.project;await fetchModulesForSelect(queryParams.project_id); // 确保选中项目的模块列表被加载queryParams.module_id = Number(routeModuleId); // 再次设置,因为 fetchModulesForSelect 会清空它}}await fetchTestCases();pageLoading.value = false;
})const handleSearch = () => {queryParams.page = 1 // 搜索时重置到第一页fetchTestCases()
}const handleReset = () => {queryFormRef.value?.resetFields() // Element Plus 表单重置方法// queryParams.project_id = null; // resetFields可能不会重置非表单组件绑定的值// queryParams.module_id = null;// moduleOptions.value = [];// 手动重置非表单元素绑定的queryParams属性queryParams.page = 1;queryParams.project_id = null; // 这会触发 watch 清空 module_id 和 moduleOptionsqueryParams.priority = null;queryParams.case_type = null;queryParams.search = '';// 重置后立即搜索fetchTestCases()
}const handlePageChange = (newPage: number) => {queryParams.page = newPagefetchTestCases()
}const handleSizeChange = (newSize: number) => {queryParams.page_size = newSizequeryParams.page = 1 // 切换每页大小时回到第一页fetchTestCases()
}const navigateToCreate = () => {router.push('/testcase/create')
}const handleEdit = (testCaseId: number) => {router.push(`/testcase/edit/${testCaseId}`)
}const handleDelete = async (testCaseId: number) => {try {await ElMessageBox.confirm('此操作将永久删除该测试用例,是否继续?', '警告', {confirmButtonText: '确定删除',cancelButtonText: '取消',type: 'warning',});tableLoading.value = true; // 表示正在删除await deleteTestCase(testCaseId);ElMessage.success('测试用例删除成功!');// 如果删除的是当前页的最后一条数据,且不是第一页,则可能需要跳转到前一页if (testCases.value.length === 1 && queryParams.page! > 1) {queryParams.page!--;}fetchTestCases(); // 重新加载列表} catch (error) {if (error !== 'cancel') { // 用户点击取消时不提示错误console.error('删除测试用例失败:', error);}} finally {tableLoading.value = false;}
}// 辅助函数
const formatDateTime = (dateTimeStr: string) => {if (!dateTimeStr) return ''return new Date(dateTimeStr).toLocaleString()
}
const getPriorityTagType = (priority: string) => {const map: Record<string, '' | 'success' | 'warning' | 'info' | 'danger'> = { P0: 'danger', P1: 'warning', P2: '', P3: 'info' }return map[priority] || 'info'
}
const getCaseTypeText = (caseType: string) => {const map: Record<string, string> = { functional: '功能测试', api: '接口测试', ui: 'UI测试' };return map[caseType] || caseType;
}</script><style scoped lang="scss">
.testcase-list-view {padding: 20px;.filter-card {margin-bottom: 20px;}.table-card {.card-header {display: flex;justify-content: space-between;align-items: center;}}.pagination-container {margin-top: 20px;display: flex;justify-content: flex-end;}
}
</style>

代码解释与关键点:

  • 筛选表单 (filter-card):
    • 使用 el-formel-form-item 构建筛选区域。
    • 项目选择器: fetchProjectsForSelect 获取项目列表填充选项。
    • 模块选择器: fetchModulesForSelect 根据选中的项目动态加载模块选项。通过 watch(() => queryParams.project_id, ...) 实现联动。
    • 其他筛选条件如优先级、类型、关键词输入框。
    • “搜索”按钮调用 handleSearch,“重置”按钮调用 handleReset
  • 用例表格 (table-card):
    • 顶部有“新建用例”按钮。
    • 使用 el-table 展示用例数据。关键列包括 ID, 名称 (可点击跳转编辑), 所属项目/模块, 优先级 (带标签), 类型, 更新时间等。
    • show-overflow-tooltip 用于内容过长时显示省略号和tooltip。
    • “操作”列包含“编辑”和“删除”按钮。
  • 分页控件 (el-pagination):
    • totalCases > 0 时显示。
    • 绑定了 queryParams.page, queryParams.page_size, totalCases
    • 监听 @size-change@current-change 事件,分别调用 handleSizeChangehandlePageChange 来更新查询参数并重新获取数据。
  • 数据获取与状态:
    • testCases, totalCases, loading (分为 pageLoadingtableLoading) 等响应式变量。
    • queryParams 对象存储所有查询、筛选和分页参数。
    • fetchTestCases() 是核心数据获取函数,它将 queryParams 发送给 getTestCaseList API,并用返回的 resultscount 更新本地状态。
  • 初始化加载:
    • onMounted 中首先加载项目选项,然后检查路由查询参数 moduleId (用于支持从用例编辑页成功后跳转回列表并筛选到对应模块)。最后调用 fetchTestCases 加载初始用例列表。
  • 操作处理:
    • handleSearch: 重置页码为1,然后获取数据。
    • handleReset: 重置表单和 queryParams (注意 resetFields 对非表单组件绑定的数据可能无效,需要手动重置),然后获取数据。
    • navigateToCreate, handleEdit: 使用 router.push 跳转到用例创建/编辑页。
    • handleDelete: 弹出确认框,调用删除 API,成功后刷新列表。增加了删除当前页最后一条数据时页码处理的逻辑。
  • 辅助函数: 用于格式化日期、显示优先级标签颜色、用例类型文本等。

第三步:测试列表、搜索、筛选和分页

  1. 确保后端服务运行正常,并且你已经创建了一些测试用例,分布在不同的项目和模块下,具有不同的优先级和类型。

  2. 启动前端开发服务器 (npm run dev)。

  3. 登录并访问用例列表页 (http://127.0.0.1:5173/testcases):
    在这里插入图片描述

    • 初始加载: 表格应显示第一页的测试用例数据,分页控件应正确显示总数。
    • 分页测试: 点击页码、上一页/下一页、改变每页显示数量,观察表格数据和分页控件是否正确更新,Network 面板中的 API 请求参数 (page, page_size) 是否正确。
    • 筛选测试:
      • 选择一个项目,模块选择器应动态加载该项目下的模块。
      • 选择项目、模块、优先级、类型,点击“搜索”。观察表格数据是否按条件筛选,Network 请求参数是否正确。
    • 关键词搜索测试: 输入关键词 (如用例名称的一部分),点击“搜索”。观察结果。
    • 重置测试: 点击“重置”按钮,所有筛选条件应清空,列表应恢复显示所有用例的第一页。
    • 操作测试:
      • 点击“新建用例”按钮,应跳转到用例创建页。
      • 点击某行用例的名称或“编辑”按钮,应跳转到该用例的编辑页,并能正确加载数据。
      • 点击“删除”按钮,确认后,该用例应被删除,列表刷新。
    • 从编辑/新建页跳转测试: 在用例编辑/新建成功后,会跳转回列表页,并尝试根据创建/编辑的用例所属模块进行筛选。验证此功能。

总结

在这篇文章中,我们成功地实现了测试用例的列表展示、分页、搜索和筛选:

  • 更新了 api/testcase.ts 中的 API 服务函数和类型定义,以更好地支持分页、搜索和过滤参数,并处理 DRF 标准的分页响应结构。
  • 确保了后端 TestCaseViewSet 配置了 SearchFilterDjangoFilterBackend 以支持前端的搜索和筛选需求。
  • 创建并实现了 TestCaseListView.vue 组件,其核心功能包括:
    • 一个包含项目、模块、优先级、类型选择器以及关键词输入框的筛选/搜索表单
    • 项目和模块选择器的联动加载
    • 使用 ElTable 清晰地展示测试用例的关键信息,并提供行内操作。
    • 使用 ElPagination 实现前端分页控制,与后端分页数据同步。
  • 实现了从列表页到用例创建/编辑页的跳转,以及从创建/编辑成功后返回列表并尝试定位到相关模块的逻辑。

现在,我们的测试平台在用例管理方面已经具备了查找、展示、新建、编辑、删除的完整闭环,可以高效地管理和维护测试用例库了。

在下一篇文章中,我们将继续完善核心功能,开始构建测试计划/测试套件的管理。这将涉及到如何从现有的用例库中选择用例,将它们组织成可执行的集合。


http://www.hkcw.cn/article/iVHJTySILp.shtml

相关文章

Windows环境下PHP,在PowerShell控制台输出中文乱码

解决方法&#xff1a; 以管理员运行PowerShell , 输入&#xff1a; chcp 65001 重启控制台&#xff1b;然后就正常输出中文&#xff1b;

安卓apk安装包签名步骤

1.获取apk对应的原始证书&#xff08;问前端要&#xff09; 2.打开命令窗口win r 输入 cmd 3.输入 cd .android 定位到 .android 文件夹 4.执行证书签名命令 keytool -genkey -v -keystore 前端提供的.keystore -alias 自定义别名信息 -keyalg RSA -validity 10000 密钥为&a…

C与C++相互调用

C与C为什么相互调用的方式不同 C 和 C 之间的相互调用方式存在区别&#xff0c;主要是由于 C 和 C 语言本身的设计和特性不同。 函数调用和参数传递方式不同 &#xff1a; C 和 C 在函数调用和参数传递方面有一些不同之处。 C 使用标准 的函数调用约定&#xff0c;而 …

Nest全栈到失业(附加):Mysql+TypeOrm构建CRUD

前置内容 在此之前,我希望你准备好一个docker环境,以及魔法的网络哦 自己创建一个项目哈,使用nest new XXX Docker 什么是docker?相信很多人都知道了,说白了,就是一个镜像容器;以mysql为例,你在电脑上使用mysql5.6啥的,他电脑上是5.7啥的,然后数据内容不兼容了,怎么办了?他卸…

InnoDB引擎逻辑存储结构及架构

简化理解版 想象 InnoDB 是一个高效运转的仓库&#xff1a; 核心内存区 (大脑 & 高速缓存 - 干活超快的地方) 缓冲池 Buffer Pool (最最核心&#xff01;)&#xff1a; 作用&#xff1a; 相当于仓库的“高频货架”。把最常用的数据&#xff08;表数据、索引&#xff09;从…

基于定制开发开源AI智能名片S2B2C商城小程序的大零售渗透策略研究

摘要&#xff1a;本文聚焦“一切皆零售”理念下的大零售渗透趋势&#xff0c;提出以定制开发开源AI智能名片S2B2C商城小程序为核心工具的渗透策略。通过分析该小程序在需求感应、场景融合、数据驱动等方面的技术优势&#xff0c;结合零售渗透率提升的关键路径&#xff0c;揭示其…

基于SpringBoot的在线拍卖系统计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

二分法算法技巧-思维提升

背景&#xff1a; 在写力扣题目“搜素插入位置 ”时&#xff0c;发现二分法的一个细节点&#xff0c;打算记录下来&#xff0c;先看一张图&#xff1a; 我们知道&#xff0c;排序数组&#xff0c;更高效的是二分查找法~~~而二分法就是切割中间&#xff0c;定义left是最开始的&…

实验分享|基于sCMOS相机科学成像技术的耐高温航空涂层材料损伤检测实验

1实验背景 航空发动机外壳的耐高温涂层材料在长期高温、高压工况下易产生微小损伤与裂纹&#xff0c;可能导致严重安全隐患。传统光学检测手段受限于分辨率与灵敏度&#xff0c;难以捕捉微米级缺陷&#xff0c;且检测效率低下。 某高校航空材料实验室&#xff0c;采用科学相机…

特伦斯 S75 电钢琴:重构演奏美学的极致表达

在数字音乐时代&#xff0c;电钢琴正从功能性乐器升级为融合艺术、科技与生活的美学载体。特伦斯 S75 电钢琴以极简主义哲学重构产品设计&#xff0c;将专业级演奏体验与现代家居美学深度融合&#xff0c;为音乐爱好者打造跨越技术边界的沉浸式艺术空间。 一、极简主义的视觉叙…

室内VR全景助力房产营销及装修

在当今的地产行业&#xff0c;VR全景已成为不可或缺的应用工具。从地产直播到楼市VR地图&#xff0c;从效果图到水电家装施工记录&#xff0c;整个地产行业的上下游生态中&#xff0c;云VR全景的身影无处不在。本文将探讨VR全景在房产营销及装修领域的应用&#xff0c;并介绍众…

AWS API Gateway 配置WAF(中国区)

问题 需要给AWS API Gateway配置WAF。 AWS WAF设置 打开AWS WAF首页&#xff0c;开始创建和配置WAF&#xff0c;如下图&#xff1a; 设置web acl名称&#xff0c;然后开始添加aws相关资源&#xff0c;如下图&#xff1a; 选择资源类型&#xff0c;但是&#xff0c;我这里出…

文件雕刻——一种碎片文件的恢复方法

文件雕刻是指基于对文件格式而非其他元数据的了解&#xff0c;在数据流中搜索文件的一种过程。 当文件系统元数据损坏或无法使用时&#xff0c;雕刻非常有用。FAT 文件系统&#xff08;通常用于小型介质&#xff09;是最常见的例子。 删除文件或格式化介质后&#xff0c;文件系…

如何解决MySQL Workbench中的错误Error Code: 1175

错误描述&#xff1a; 在MySQL Workbench8.0中练习SQL语句时&#xff0c;执行一条update语句&#xff0c;总是提示如下错误&#xff1a; Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY columnTo disab…

VScode-使用技巧-持续更新

一、Visual Studio Code - MACOS版本 复制当前行 shiftoption方向键⬇️ 同时复制多行 shiftoption 批量替换换行 在查找和替换面板中&#xff0c;你会看到一个 .∗ 图标&#xff08;表示启用正则表达式&#xff09;。确保这个选项被选中&#xff0c;因为我们需要使用正则…

【Redis】hash

Hash 哈希 几乎所有的主流编程语言都提供了哈希&#xff08;hash&#xff09;类型&#xff0c;它们的叫法可能是哈希、字典、关联数组、映射等。在 Redis 中&#xff0c;哈希类型指值本身又是一个键值对结构&#xff0c;形如 key “key”, value {{field1, value1}, …{field…

产品更新|数字主线深度解析:华望解决方案助力企业数字化转型

在数字化转型的浪潮中&#xff0c;企业如何打破数据孤岛、实现全流程协同是亟需解决的问题。数字主线&#xff08;Digital Thread&#xff09;作为新一代工业智能的核心技术&#xff0c;正在成为推动数字化转型的“加速引擎”。 一、什么是数字主线&#xff1f; 数字主线是贯穿…

PECVD 生成 SiO₂ 的反应方程式

在PECVD工艺中&#xff0c;沉积氧化硅薄膜以SiH₄基与TEOS基两种工艺路线为主。 IMD Oxide&#xff08;USG&#xff09; 这部分主要沉积未掺杂的SiO₂&#xff0c;也叫USG&#xff08;Undoped Silicate Glass&#xff09;&#xff0c;常用于IMD&#xff08;Inter-Metal Diele…

Centos7搭建zabbix6.0

此方法适用于zabbix6以上版本zabbix6.0前期环境准备&#xff1a;Lamp&#xff08;linux httpd mysql8.0 php&#xff09;mysql官网下载位置&#xff1a;https://dev.mysql.com/downloads/mysql/Zabbix源码包地址&#xff1a;https://www.zabbix.com/cn/download_sourcesZabbix6…

[CSS3]响应式布局

导读 响应式就是一套代码, 兼容大中小不同的屏幕, 即网页内容不变, 网页布局随屏幕切换而改变 媒体查询 响应式布局的核心技术是媒体查询 媒体查询可以检测屏幕尺寸, 设置差异化的css 开发中的常用写法 使用范围属性, 划定屏幕范围 max-width 最大宽度min-width 最小宽度 …