修改概述
今天的修改分为两个阶段:
阶段一:实现分页功能 + 创建50条测试数据
- 修改 API endpoint 匹配逻辑(关键修复)
- 从原有约2条数据增加到50条测试数据
- 实现完整的分页功能(搜索、分页组件、跳转)
- 添加模板类型支持(公用/共享/个人)
阶段二:增加50条测试数据
- 在50条基础上再增加50条,达到100条测试数据
修改文件清单
src/api/index.js- Mock API和测试数据(2条→50条→100条)src/stores/searchStore.js- Store分页逻辑src/components/search/TemplateManagerDialog.vue- 模板管理弹窗组件src/components/search/SearchPanel.vue- 搜索面板下拉列表样式
阶段一修改内容
1. src/api/index.js
1.1 修改 endpoint 匹配逻辑(关键修复)
问题原因: URL包含查询参数(如/templates?start=0&limit=20)时,严格相等匹配===会失败,导致数据无法加载
位置: 第63行(GET请求)和第257行(POST请求)
修改前:
if(endpoint==='/templates'&&method==='GET'){修改后:
if(endpoint.startsWith('/templates')&&method==='GET'){同样修改 POST 请求(第257行):
// 修改前if(endpoint==='/templates'&&method==='POST'){// 修改后if(endpoint.startsWith('/templates')&&method==='POST'){1.2 创建50条测试数据
背景: 原有代码只有约2条测试数据
位置: 第68-175行
修改内容:
// 生成50条测试数据constTOTAL_TEMPLATES=50consttemplateNames=['故障查询模板','维护记录模板','日常巡检模板','设备监控模板','告警处理模板','工单派发模板','资源申请模板','权限审批模板','数据备份模板','系统升级模板','网络诊断模板','性能分析模板','安全审计模板','日志查询模板','配置管理模板','变更管理模板','问题管理模板','事件管理模板','发布管理模板','容量规划模板','可用性管理模板','连续性管理模板','服务级别模板','财务管理模板','资产管理模板','知识管理模板','供应商管理模板','安全管理模板','项目管理模板','质量管理模板','风险管理模板','合规管理模板','业务关系管理模板','战略管理模板','设计管理模板','转换管理模板','运营支持模板','服务报告模板','改进管理模板','评估管理模板','测试管理模板','部署管理模板','监控管理模板','备份恢复模板','灾备演练模板','应急响应模板','漏洞管理模板','补丁管理模板','配置审计模板','访问控制模板',]数据分布规则:
- ID 1-5:公用模板(type=‘public’)
- ID 6-15:共享模板(type=‘shared’)
- ID 16-50:个人模板(type=‘private’)
1.3 添加关键词搜索过滤
位置: 第164-170行
新增代码:
// 根据keyword过滤数据constkeyword=url.searchParams.get('keyword')||''letfilteredTemplates=allTemplatesif(keyword){filteredTemplates=allTemplates.filter((t)=>t.name.toLowerCase().includes(keyword.toLowerCase()),)}// 根据start和limit截取数据constpaginatedResults=filteredTemplates.slice(start,start+limit)2. src/stores/searchStore.js
2.1 添加分页状态
位置: 第127-134行(在activeFieldsConfig定义后添加)
新增代码:
/** * 模板分页状态 * 作用:管理模板列表的分页数据 */consttemplatePagination=ref({currentPage:1,pageSize:20,total:0,})2.2 添加分页获取模板函数
位置: 第212-272行(在initData函数后添加)
新增代码:
/** * 获取分页模板列表 * * 函数意义:用于模板管理弹窗的分页数据获取 * 执行逻辑: * 1. 根据当前分页参数调用API * 2. 转换数据格式 * 3. 更新本地状态 * * 参数说明: * page: 页码(从1开始) * pageSize: 每页条数 * keyword: 搜索关键词(可选) * * 返回:转换后的模板数据和总数 */constfetchTemplatesByPage=async(page=1,pageSize=20,keyword='')=>{try{conststart=(page-1)*pageSizeconsttemplateData=awaittrackedApi.template.getTemplates({start,limit:pageSize,keyword,})// 转换API数据结构为前端友好的格式constconvertedTemplates=templateData.results.map((template)=>({id:template.id,name:template.name,type:template.type||(template.active?'public':'private'),isDefault:template.is_default,creator:template.creator||'Unknown',createTime:template.createTime||newDate(template.change_time).toLocaleString(),sharedTo:template.shared_to||template.sharedTo||'--',description:template.description||'--',content:parseTemplateContent(template.content),permission:{canDelete:template.permission?.can_delete||false,canShare:template.permission?.can_share||false,canUpdate:template.permission?.can_update||false,},}))// 更新分页状态templatePagination.value={currentPage:page,pageSize:pageSize,total:templateData.total||templateData.results.length,}return{templates:convertedTemplates,total:templateData.total||templateData.results.length,}}catch(error){console.error('获取模板列表失败:',error)ElMessage.error('获取模板列表失败,请重试')throwerror}}2.3 导出新增的状态和函数
位置: 第575行(在return语句中添加)
修改前:
return{// ... 其他导出 ...apiSetDefault,apiDeleteTemplate,apiShareTemplate,}修改后:
return{// ... 其他导出 ...apiSetDefault,apiDeleteTemplate,apiShareTemplate,fetchTemplatesByPage,// 分页获取模板列表templatePagination,// 模板分页状态}3. src/components/search/TemplateManagerDialog.vue
3.1 修改模板结构
位置: 第2-96行
新增搜索输入框:
<el-input v-model="searchKeyword" placeholder="请输入模板名称" clearable style="width: 100%; margin-bottom: 1rem" :prefix-icon="Search" @keyup.enter="handleSearch" @clear="handleSearch" />修改表格数据源和添加最大高度:
<el-table :data="pagedTemplates" style="width: 100%" stripe v-loading="loading" max-height="500" ></el-table>修改模板类型列(支持三种类型):
<el-table-column label="模板类型" width="100"> <template #default="scope"> <el-tag :type="getTagType(scope.row.type)"> {{ getTypeLabel(scope.row.type) }} </el-tag> </template> </el-table-column>新增两列(被共享群组或个人、描述):
<el-table-column prop="sharedTo" label="被共享群组或个人" width="150" /> <el-table-column prop="description" label="描述" min-width="120" />修改"设为默认"列标题:
<el-table-column label="设置为默认模板" width="130" align="center"></el-table-column>新增分页组件(第68-99行):
<!-- 分页组件 --> <div class="pagination-container"> <div class="pagination-left"> <span class="total-text">总共 {{ pagination.total }} 条</span> <el-select v-model="pagination.pageSize" @change="handleSizeChange" style="width: 100px"> <el-option label="10条/页" :value="10" /> <el-option label="20条/页" :value="20" /> <el-option label="50条/页" :value="50" /> <el-option label="100条/页" :value="100" /> </el-select> </div> <div class="pagination-right"> <el-pagination v-model:current-page="pagination.currentPage" :page-size="pagination.pageSize" :total="pagination.total" layout="prev, pager, next" @current-change="handlePageChange" /> <div class="jump-to"> <span>跳至</span> <el-input-number v-model="jumpToPage" :min="1" :max="Math.ceil(pagination.total / pagination.pageSize) || 1" controls-position="right" style="width: 80px; margin: 0 8px" @keyup.enter="handleJumpToPage" /> <span>页</span> </div> </div> </div>3.2 修改 script 部分
位置: 第117-310行
修改导入:
import{computed,ref,reactive,watch}from'vue'import{Share,Delete,Search}from'@element-plus/icons-vue'import{showApiError,isPermissionError}from'../../utils/errorHandler'添加分页相关状态:
constsearchKeyword=ref('')constpagedTemplates=ref([])constloading=ref(false)constjumpToPage=ref(1)constpagination=reactive({currentPage:1,pageSize:20,total:0,})添加数据加载函数:
constloadTemplates=async()=>{loading.value=truetry{constresult=awaitsearchStore.fetchTemplatesByPage(pagination.currentPage,pagination.pageSize,searchKeyword.value,)pagedTemplates.value=result.templates pagination.total=result.total}catch(error){console.error('加载模板列表失败:',error)}finally{loading.value=false}}consthandleSearch=()=>{pagination.currentPage=1jumpToPage.value=1loadTemplates()}consthandlePageChange=(page)=>{pagination.currentPage=pageloadTemplates()}consthandleSizeChange=(size)=>{pagination.pageSize=size pagination.currentPage=1jumpToPage.value=1loadTemplates()}consthandleJumpToPage=()=>{constmaxPage=Math.ceil(pagination.total/pagination.pageSize)||1if(jumpToPage.value>=1&&jumpToPage.value<=maxPage){pagination.currentPage=jumpToPage.valueloadTemplates()}}添加模板类型辅助函数(支持公用/共享/个人三种类型):
constgetTagType=(type)=>{switch(type){case'public':return'warning'case'shared':return'success'default:return'info'}}constgetTypeLabel=(type)=>{switch(type){case'public':return'公用'case'shared':return'共享'default:return'个人'}}修改删除逻辑(删除后自动处理分页):
// 在handleDelete中,删除成功后添加:if(pagedTemplates.value.length===1&&pagination.currentPage>1){pagination.currentPage--jumpToPage.value=pagination.currentPage}awaitloadTemplates()添加弹窗打开监听:
watch(()=>props.modelValue,(newVal)=>{if(newVal){pagination.currentPage=1jumpToPage.value=1loadTemplates()}},)3.3 修改 style 部分
位置: 第380-425行
添加分页样式:
/* 分页容器样式 */.pagination-container{display:flex;justify-content:space-between;align-items:center;margin-top:1rem;padding:0.5rem 0;}.pagination-left{display:flex;align-items:center;gap:0.5rem;}.total-text{color:#606266;font-size:0.875rem;}.pagination-right{display:flex;align-items:center;gap:0.5rem;}.jump-to{display:flex;align-items:center;color:#606266;font-size:0.875rem;}.jump-to :deep(.el-input-number) .el-input__inner{padding-left:8px;padding-right:8px;text-align:center;}4. src/components/search/SearchPanel.vue
4.1 修改下拉列表样式(添加最大高度)
位置: 第223-227行
修改前:
.template-dropdown-list{list-style:none;padding:0;margin:0;}修改后:
.template-dropdown-list{list-style:none;padding:0;margin:0;max-height:300px;overflow-y:auto;}阶段二修改内容
1. src/api/index.js - 增加50条测试数据(50条→100条)
背景: 在阶段一的50条数据基础上,再增加50条,达到100条
位置: 第68-170行
修改内容:
// 修改前constTOTAL_TEMPLATES=50consttemplateNames=[// ... 原有的50个名称 ...'访问控制模板',]// 修改后constTOTAL_TEMPLATES=100consttemplateNames=[// ... 原有的50个名称 ...'访问控制模板',// 新增的50个模板名称'用户管理模板','角色管理模板','组织架构模板','流程审批模板','数据统计模板','报表生成模板','数据导入模板','数据导出模板','系统配置模板','参数设置模板','字典管理模板','菜单管理模板','接口管理模板','定时任务模板','消息通知模板','邮件发送模板','短信发送模板','文件上传模板','文件下载模板','图片处理模板','视频管理模板','音频管理模板','文档管理模板','版本控制模板','代码审查模板','构建部署模板','自动化测试模板','性能压测模板','负载均衡模板','缓存管理模板','队列管理模板','搜索引擎模板','大数据分析模板','机器学习模板','人工智能模板','物联网管理模板','区块链管理模板','云计算管理模板','容器编排模板','微服务管理模板','服务网格模板','API网关模板','身份认证模板','单点登录模板','多租户管理模板','数据隔离模板','隐私保护模板','加密解密模板','签名验签模板','证书管理模板','密钥管理模板','令牌管理模板','会话管理模板','限流熔断模板','降级预案模板','灰度发布模板','蓝绿部署模板','金丝雀发布模板','A/B测试模板','用户画像模板','行为分析模板','推荐系统模板','风控管理模板','反欺诈模板','内容审核模板','版权管理模板','合同管理模板','发票管理模板','支付管理模板','对账管理模板','结算管理模板','退款管理模板','优惠券管理模板','积分管理模板','会员管理模板','等级管理模板','权益管理模板','活动管理模板','抽奖管理模板','秒杀管理模板','团购管理模板','预约管理模板','排队管理模板','叫号管理模板',]最终数据分布(100条):
- 公用模板:5条 (ID 1-5)
- 共享模板:10条 (ID 6-15)
- 个人模板:85条 (ID 16-100)
修改验证清单
部署后请检查:
关键注意事项
- endpoint匹配修改(第63行和第257行)是关键修复,必须使用
startsWith而不是===,否则URL查询参数会导致匹配失败,数据无法加载 - 数据生成逻辑:
- ID 1-5:公用模板(type=‘public’)
- ID 6-15:共享模板(type=‘shared’)
- ID 16-100:个人模板(type=‘private’)
- 分页逻辑:采用后端分页,前端只显示当前页数据,每次翻页都会调用API
- 所有新增代码均通过 ESLint 检查