Rows.Find( key ) 以及 table.ImportRow(datarow)

本文介绍了如何使用SqlDataAdapter填充DataSet,并设置MissingSchemaAction为AddWithKey以包含主键信息。随后通过DataRow的Find方法查找特定记录,并将其导入新的DataTable。

 

首先在Fill一个DataSet的时候,设置DataAdapter.MissingSchemaAction = MissionSchemaAction.AddWithKey; 也就是说在Fill的时候把主键信息也包含进去。

 

然后新建一个DataRow,就可以用Rows.Find(Key)这个方法通过表的主键值查找到这一行Row,在复制给新的DataRow。

 

new 一个 DataTable克隆一下DataSet中的table【ds.table[0].clone()】,再ImportRow(datarow);就可以将row导入到新的datatable中了。

 

 

<template> <div class="app-container"> <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px" > <el-form-item label="seasonNo" prop="seasonNo" label-width="140"> <el-input v-model="queryParams.seasonNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="colorwayid" prop="colorwayid" label-width="140"> <el-input v-model="queryParams.colorwayid" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="modelNo" prop="modelNo" label-width="140"> <el-input v-model="queryParams.modelNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery" >搜索</el-button > <el-button icon="Refresh" @click="resetQuery">重置</el-button> </el-form-item> <el-form-item> <el-button type="primary" plain @click="handleTest">测试</el-button> </el-form-item> </el-form> <el-table v-loading="loading" :data="qsList"> <el-table-column label="seasonNo" align="center" prop="seasonNo"> </el-table-column> <el-table-column label="stage" align="center" prop="stage"> </el-table-column> <el-table-column label="modelNo" align="center" prop="modelNo"> </el-table-column> <el-table-column label="Colorway Name" align="center" prop="colorwayid"> </el-table-column> <el-table-column label="pattern" align="center" prop="pattern"> </el-table-column> <el-table-column label="firstsource" align="center" prop="firstsource"> </el-table-column> <el-table-column label="Operate" align="center" class-name="small-padding fixed-width" > <template #default="scope"> <el-button link type="primary" icon="Plus" @click="handleCreate(scope.row)" ></el-button> </template> </el-table-column> </el-table> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> </div> <el-dialog title="测试" v-model="testDialog" width="1600px" append-to-body> <div> <el-form :model="queryParams" ref="testRef" :inline="true" label-width="108px" > <el-form-item label="seasonNo" prop="seasonNo" label-width="140"> <el-input v-model="queryParams.seasonNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="colorwayid" prop="colorwayid" label-width="140"> <el-input v-model="queryParams.colorwayid" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="modelNo" prop="modelNo" label-width="140"> <el-input v-model="queryParams.modelNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQueryTest" >Search</el-button > <el-button icon="Refresh" @click="resetQueryTest">Reset</el-button> </el-form-item> </el-form> <el-table v-loading="loading" :data="ptrList"> <el-table-column label="seasonNo" align="center" prop="seasonNo"> </el-table-column> <el-table-column label="stage" align="center" prop="stage"> </el-table-column> <el-table-column label="modelNo" align="center" prop="modelNo"> </el-table-column> <el-table-column label="Colorway Name" align="center" prop="colorwayid"> </el-table-column> <el-table-column label="pattern" align="center" prop="pattern"> </el-table-column> <el-table-column label="firstsource" align="center" prop="firstsource"> </el-table-column> <el-table-column label="Operate" align="center" class-name="small-padding fixed-width" > <template #default="scope"> <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" ></el-button> </template> </el-table-column> </el-table> <pagination v-show="totalTest > 0" :total="totalTest" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getTestList" /> </div> </el-dialog> <el-dialog title="创建" v-model="createDialog" width="1800px" append-to-body> <div> <el-tabs v-model="activeTab" type="card"> <el-tab-pane v-for="(item, index) in mainList" :key="index" :label="getTabLabel(item)" :name="index.toString()" > <!-- 每个标签页使用独立的表单和数据结构 --> <div v-if="currentTabData[index]"> <!-- 基本信息区域(只读) --> <el-card header="基本信息" style="margin-bottom: 20px"> <el-form :model="currentTabData[index].baseInfo" label-width="120px" :inline="true" > <el-form-item label="Dev Style Name"> <el-input v-model="currentTabData[index].baseInfo.modelNo" readonly style="width: 100px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.modelName" readonly style="width: 150px" class="readonly-input" /> </el-form-item> <el-form-item label="Color Way Name" label-width="125"> <el-input v-model="currentTabData[index].baseInfo.colorwayid" readonly style="width: 100px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.colorwayname" readonly style="width: 400px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.bomid" readonly style="width: 100px" class="readonly-input" /> </el-form-item> <el-form-item label="Stage" label-width="60"> <el-input v-model="currentTabData[index].baseInfo.stage" readonly class="readonly-input" style="width: 120px" /> </el-form-item> <el-form-item label="DPA/STYLE" prop="prodCd" label-width="100"> <el-input v-model="currentTabData[index].baseInfo.prodCd" readonly class="readonly-input" /> </el-form-item> <el-form-item label="Season"> <el-input v-model="currentTabData[index].baseInfo.seasonNo" readonly class="readonly-input" style="width: 100px" /> </el-form-item> <el-form-item label="Version" prop="pfcVersion" label-width="80" > <el-input v-model="currentTabData[index].baseInfo.pfcVersion" readonly style="width: 120px" class="readonly-input" /> </el-form-item> <el-form-item label="Tool Code" prop="pattern" label-width="100" > <el-input v-model="currentTabData[index].baseInfo.pattern" readonly class="readonly-input" /> </el-form-item> <el-form-item label="PFC手册号" prop="pfcNo" label-width="100"> <el-input v-model="currentTabData[index].baseInfo.pfcNo" readonly style="width: 100px" class="readonly-input" /> </el-form-item> <el-form-item label="Page Number"> <el-input v-model="currentTabData[index].baseInfo.pageNumber" readonly class="readonly-input" style="width: 80px" /> <el-input v-model="currentTabData[index].baseInfo.stepno" readonly class="readonly-input" style="width: 80px" /> </el-form-item> <el-form-item label="鞋码类型" prop="sizeType" label-width="100" > <el-input v-model="currentTabData[index].baseInfo.sizeType" readonly class="readonly-input" /> </el-form-item> </el-form> </el-card> <!-- 图片上传区域 --> <el-card header="图片上传" style="margin-bottom: 20px"> </el-card> <!-- 可编辑的表单区域 --> <el-card header="编辑信息"> <!-- <el-form :model="currentTabData[index].formData" :rules="getTabRules(index)" label-width="120px" > <el-row> <el-col :span="8"> <el-form-item label="STYLE NO" prop="styleNo"> <el-input v-model="currentTabData[index].formData.styleNo" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="DPA" prop="dpa"> <el-input v-model="currentTabData[index].formData.dpa" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="TD CODE" prop="tdCode"> <el-input v-model="currentTabData[index].formData.tdCode" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="FACTORY" prop="factory"> <el-input v-model="currentTabData[index].formData.factory" placeholder="Please input" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="8"> <el-form-item label="LAB TEST" prop="labTest"> <el-input v-model="currentTabData[index].formData.labTest" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="APPROVED BY" prop="approvedBy" label-width="130" > <el-input v-model="currentTabData[index].formData.approvedBy" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="APPROVED DATE" prop="approvedDate" label-width="180" > <el-date-picker v-model="currentTabData[index].formData.approvedDate" type="date" placeholder="选择日期" style="width: 50%" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="16"> <el-form-item label="具体描述" prop="description"> <el-input v-model="currentTabData[index].formData.description" placeholder="Please input" type="textarea" :rows="2" /> </el-form-item> </el-col> </el-row> </el-form> --> <!-- 动态数据行区域(根据标签页类型显示不同的字段) --> <div style="margin-top: 20px"> <!-- 将模板选择器和列表标题放在同一行 --> <div style=" display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; " > <!-- 左侧:模板选择器 --> <div style="display: flex; align-items: center; flex: 1"> <span style=" font-weight: bold; margin-right: 10px; min-width: 100px; " >测试用例列表</span > <el-cascader v-model="currentTabData[index].selectedTemplate" :options="currentTabData[index].templateOptions" :props="getCascaderProps(index)" placeholder="请选择测试用例模板" clearable filterable style="width: 350px; margin-right: 10px" @change="handleTemplateSelect(index)" /> </div> <!-- 右侧:按钮和标题 --> <!-- <div style="display: flex; align-items: center;"> <el-button type="primary" size="small" @click="addDataRow(index)" >添加空白用例</el-button> </div> --> </div> <el-table :data="currentTabData[index].dataRows" border v-loading="currentTabData[index].loading" > <!-- 根据页面类型动态显示列 --> <el-table-column v-for="column in getTableColumns(index)" :key="column.prop" :label="column.label" :prop="column.prop" :width="column.width" > <template #default="scope"> <el-input v-model="scope.row[column.prop]" size="small" /> </template> </el-table-column> <el-table-column label="Operate" width="80"> <template #default="scope"> <el-button link type="danger" size="small" @click="removeDataRow(index, scope.$index)" >delete</el-button > </template> </el-table-column> </el-table> </div> </el-card> </div> </el-tab-pane> </el-tabs> <!-- 底部操作按钮 --> <div style="text-align: center; margin-top: 20px"> <!-- <el-button type="primary" @click="handleSaveAll">保存所有</el-button> --> <el-button type="success" @click="handleSaveCurrent" >保存当前</el-button > <el-button @click="createDialog = false">取消</el-button> </div> </div> </el-dialog> </template> <script setup name="User"> import { ptrInfo, addQualityStand, qsInfo, getQsMain, getTemplateTree, saveQualityStandards, getSavedQualityStandards, uploadImages, getImages, deleteImage, } from "@/api/quality/standard/quasd.js"; import { getSrc } from "@/utils/interceptSrc"; const { proxy } = getCurrentInstance(); const qsList = ref([]); const ptrList = ref([]); const mainList = ref([]); const loading = ref(true); const showSearch = ref(true); const testDialog = ref(false); const createDialog = ref(false); const total = ref(0); const totalTest = ref(0); const activeTab = ref("0"); // 为每个标签页存储独立的数据 const currentTabData = ref({}); const data = reactive({ queryParams: { pageNum: 1, pageSize: 10, stage: null, modelNo: null, colorwayid: null, seasonNo: null, pfcNo: null, pattern: null, firstsource: null, pageNumber: null, stepno: null, pfcCaption: null, }, rules: { styleNo: [{ required: true, message: "STYLE NO不能为空", trigger: "blur" }], dpa: [{ required: true, message: "DPA不能为空", trigger: "blur" }], tdCode: [{ required: true, message: "TD CODE不能为空", trigger: "blur" }], factory: [{ required: true, message: "FACTORY不能为空", trigger: "blur" }], labTest: [{ required: true, message: "LAB TEST不能为空", trigger: "blur" }], approvedBy: [ { required: true, message: "APPROVED BY不能为空", trigger: "blur" }, ], approvedDate: [ { required: true, message: "APPROVED DATE不能为空", trigger: "blur" }, ], // 其他验证规则... }, }); const { queryParams, rules } = toRefs(data); // 初始化标签页数据 async function initTabData(tabIndex, sourceData) { currentTabData.value[tabIndex] = { baseInfo: { ...sourceData }, formData: { styleNo: "", dpa: "", tdCode: "", factory: "", labTest: "", approvedBy: "", approvedDate: "", description: "", }, dataRows: [], templateOptions: [], selectedTemplate: [], currentTemplateData: null, loading: false, // 添加加载状态 }; // 加载模板数据 await loadTemplateOptions(tabIndex, sourceData.pageNumber); // 加载已保存的测试用例数据 await loadSavedDataRows(tabIndex, sourceData.pfcNo, sourceData.pageNumber); } // 加载已保存的测试用例数据 async function loadSavedDataRows(tabIndex, pfcNo, pageNumber) { const currentTab = currentTabData.value[tabIndex]; try { currentTab.loading = true; const response = await getSavedQualityStandards(pfcNo, pageNumber); const savedData = response.data || []; if (savedData.length > 0) { const currentTab = currentTabData.value[tabIndex]; // 转换已保存数据为表格行格式 currentTab.dataRows = savedData.map((item) => { const row = { templateId: item.templateId, // 保存模板ID // 复制表单数据到当前标签页的表单中(只复制一次,取第一条数据) ...(currentTab.dataRows.length === 0 ? { // 这些字段会被表单数据覆盖,所以这里主要处理测试用例特定字段 } : {}), }; // 根据页面类型设置不同的字段 if (pageNumber == "P42" || pageNumber == "P124") { // P42/P124字段 row.bondTest = item.bondTest || ""; row.testItem = item.testItem || ""; row.pictureRef = item.pictureRef || ""; row.materialOne = item.materialOne || ""; row.materialTwo = item.materialTwo || ""; row.speed = item.speed || ""; row.minSpec = item.minSpec || ""; row.peSpec = item.peSpec || ""; } else if (pageNumber == "P43" || pageNumber == "P125") { // P43/P125字段 row.testMethod = item.testMethod || ""; row.testMethodName = item.testMethodName || ""; row.pictureRef = item.pictureRef || ""; row.flmc = item.flmc || ""; row.minSpec = item.minSpec || ""; if (pageNumber == "P43") { row.testParameter = item.testParameter || ""; } else if (pageNumber == "P125") { row.speed = item.speed || ""; } } // 设置可选字段 row.csan = item.csan || ""; row.pead = item.pead || ""; row.peSpec = item.peSpec || ""; return row; }); // 设置表单数据(取第一条数据的表单信息) if (savedData.length > 0) { const firstItem = savedData[0]; currentTab.formData = { styleNo: firstItem.styleNo || "", dpa: firstItem.dpa || "", tdCode: firstItem.tdCode || "", factory: firstItem.factory || "", labTest: firstItem.labTest || "", approvedBy: firstItem.approvedBy || "", approvedDate: firstItem.approvedDate || "", description: firstItem.description || "", }; } console.log(`标签页 ${tabIndex} 加载了 ${savedData.length} 条已保存数据`); } } catch (error) { console.error("加载已保存数据失败:", error); } finally { currentTab.loading = false; } } // 加载模板选项 async function loadTemplateOptions(tabIndex, pageNumber) { try { const response = await getTemplateTree(pageNumber); currentTabData.value[tabIndex].templateOptions = response.data || []; } catch (error) { console.error("加载模板数据失败:", error); proxy.$modal.msgError("加载测试用例模板失败"); } } // 获取级联选择器配置 function getCascaderProps(tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 所有页面使用相同的配置 return { value: "value", label: "label", children: "children", checkStrictly: false, emitPath: true, expandTrigger: "hover", }; } // 处理模板选择 function handleTemplateSelect(tabIndex) { const currentTab = currentTabData.value[tabIndex]; const selectedValue = currentTab.selectedTemplate; const pageNumber = mainList.value[tabIndex]?.pageNumber; if (selectedValue && selectedValue.length > 0) { // 找到选中的模板数据 const templateData = findTemplateData( currentTab.templateOptions, selectedValue ); if (templateData && templateData.data) { currentTab.currentTemplateData = templateData.data; // 自动添加数据行 addDataRowFromTemplate(tabIndex); } else { // 如果不是叶子节点,不清空选择,让用户继续选择下级 if ( templateData && templateData.children && templateData.children.length > 0 ) { currentTab.currentTemplateData = null; } else { // 没有数据也没有子节点,清空选择 currentTab.selectedTemplate = []; currentTab.currentTemplateData = null; proxy.$modal.msgWarning("请选择有效的测试用例模板"); } } } else { currentTab.currentTemplateData = null; } } // 从模板添加数据行 function addDataRowFromTemplate(tabIndex) { const currentTab = currentTabData.value[tabIndex]; if (currentTab.currentTemplateData) { const columns = getTableColumns(tabIndex); const newRow = {}; // 初始化所有字段为空 columns.forEach((col) => { newRow[col.prop] = ""; }); // 用模板数据填充 fillRowWithTemplateData(newRow, currentTab.currentTemplateData, tabIndex); currentTab.dataRows.push(newRow); // 清空选择器 currentTab.selectedTemplate = []; currentTab.currentTemplateData = null; proxy.$modal.msgSuccess("已从模板添加测试用例"); } } // 在模板树中查找数据 function findTemplateData(options, path) { if (!options || !path || path.length == 0) return null; let currentLevel = options; let result = null; for (let i = 0; i < path.length; i++) { const currentValue = path[i]; const found = currentLevel.find((item) => item.value == currentValue); if (!found) return null; if (i == path.length - 1) { result = found; } else { currentLevel = found.children; } } return result; } // 修改原有的添加数据行方法 function addDataRow(tabIndex) { const currentTab = currentTabData.value[tabIndex]; const columns = getTableColumns(tabIndex); // 创建新行 const newRow = {}; columns.forEach((col) => { newRow[col.prop] = ""; }); currentTab.dataRows.push(newRow); proxy.$modal.msgSuccess("已添加空白的测试用例行"); } // 用模板数据填充行 function fillRowWithTemplateData(row, templateData, tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 保存模板ID,用于后续保存操作 row.templateId = templateData.id; if (pageNumber == "P42" || pageNumber == "P124") { // P42/P124模板数据映射 const bondingData = templateData; // 映射所有字段 row.bondTest = bondingData.bondTest || ""; row.testItem = bondingData.testItem || ""; row.pictureRef = bondingData.pictureRef || ""; row.materialOne = bondingData.materialOne || ""; row.materialTwo = bondingData.materialTwo || ""; row.speed = bondingData.speed || ""; row.minSpec = bondingData.minSpec || ""; row.peSpec = bondingData.peSpec || ""; row.csan = bondingData.csan || ""; row.pead = bondingData.pead || ""; } else if (pageNumber == "P43") { // P43模板数据映射 const customData = templateData; row.testMethod = customData.testMethod || ""; row.testMethodName = customData.testMethodName || ""; row.pictureRef = customData.pictureRef || ""; row.flmc = customData.flmc || ""; row.testParameter = customData.testParameter || ""; // P43特有 row.minSpec = customData.minSpec || ""; row.peSpec = customData.peSpec || ""; row.csan = customData.csan || ""; row.pead = customData.pead || ""; } else if (pageNumber == "P125") { // P125模板数据映射 const customData = templateData; row.testMethod = customData.testMethod || ""; row.testMethodName = customData.testMethodName || ""; row.pictureRef = customData.pictureRef || ""; row.flmc = customData.flmc || ""; row.speed = customData.speed || ""; // P125特有 row.minSpec = customData.minSpec || ""; row.peSpec = customData.peSpec || ""; row.csan = customData.csan || ""; row.pead = customData.pead || ""; } } /** 查询【请填写功能名称】列表 */ function getList() { loading.value = true; qsInfo(queryParams.value).then((response) => { qsList.value = response.rows; total.value = response.total; loading.value = false; }); } function handleTest() { testDialog.value = true; getTestList(); } // 根据页面类型获取表格列配置 function getTableColumns(tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 根据不同的pageNumber返回不同的列配置 switch (pageNumber) { case "P42": // Finished Shoe Bonding页面 return [ { prop: "bondTest", label: "BOND TEST", width: 120 }, { prop: "testItem", label: "TEST ITEM", width: 100 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 130 }, { prop: "materialOne", label: "MATERIAL 1", width: 120 }, { prop: "materialTwo", label: "MATERIAL 2", width: 120 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P43": // Finished Shoe Custom页面 return [ { prop: "testMethod", label: "Nike Test Method #", width: 120 }, { prop: "testMethodName", label: "Nike Test Method Name", width: 130 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "flmc", label: "FOCUSED LOCATION/MATERIAL/COLOR", width: 220 }, { prop: "testParameter", label: "Test Parameter", width: 120 }, // P43特有 { prop: "minSpec", label: "Min.Spec", width: 120 }, { prop: "peSpec", label: "Product Exc.Spec", width: 120 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P124": //Fuse & No Sew Upper return [ { prop: "bondTest", label: "BOND TEST", width: 120 }, { prop: "testMethod", label: "Nike Test Method #", width: 120 }, { prop: "testItem", label: "TEST ITEM", width: 100 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "materialOne", label: "MATERIAL 1", width: 120 }, { prop: "materialTwo", label: "MATERIAL 2", width: 120 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P125": // Sockliner页面 return [ { prop: "testMethod", label: "Nike Test Method #", width: 120 }, { prop: "testMethodName", label: "Nike Test Method Name", width: 130 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "flmc", label: "FOCUSED LOCATION/MATERIAL/COLOR", width: 220 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, // P125特有 { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; default: return []; } } // 获取标签页显示名称 function getTabLabel(item) { return `${item.pfcCaption} (${item.pageNumber})`; } // 删除数据行 function removeDataRow(tabIndex, rowIndex) { currentTabData.value[tabIndex].dataRows.splice(rowIndex, 1); } // 获取对应标签页的验证规则 function getTabRules(tabIndex) { // 可以根据不同的标签页返回不同的验证规则 return data.rules; } async function handleCreate(row) { createDialog.value = true; try { const response = await getQsMain(row.pfcNo); mainList.value = response.data; // 为每个标签页初始化独立的数据 for (let index = 0; index < mainList.value.length; index++) { const item = mainList.value[index]; await initTabData(index, item); } // 设置默认激活第一个标签页 if (mainList.value.length > 0) { activeTab.value = "0"; } } catch (error) { console.error("加载数据失败:", error); proxy.$modal.msgError("加载数据失败"); } } // 保存当前标签页 async function handleSaveCurrent() { const currentIndex = parseInt(activeTab.value); const currentData = currentTabData.value[currentIndex]; const baseInfo = currentData.baseInfo; try { // 构建保存数据 const saveDataList = []; // 遍历当前标签页的所有测试用例 for (const dataRow of currentData.dataRows) { const saveData = { pageNumber: baseInfo.pageNumber, // 当前标签页的页码 pfcNo: baseInfo.pfcNo, // PFC手册号 templateId: dataRow.templateId, // 模板树第七层data的id // 其他表单数据 // styleNo: currentData.formData.styleNo, // dpa: currentData.formData.dpa, // tdCode: currentData.formData.tdCode, // factory: currentData.formData.factory, // labTest: currentData.formData.labTest, // approvedBy: currentData.formData.approvedBy, // approvedDate: currentData.formData.approvedDate, // description: currentData.formData.description }; // 添加测试用例数据 // const pageNumber = baseInfo.pageNumber; // if (pageNumber == 'P42' || pageNumber == 'P124') { // // P42/P124字段 // saveData.testItem = dataRow.testItem || ''; // saveData.pictureRef = dataRow.pictureRef || ''; // saveData.materialOne = dataRow.materialOne || ''; // saveData.materialTwo = dataRow.materialTwo || ''; // saveData.speed = dataRow.speed || ''; // saveData.minSpec = dataRow.minSpec || ''; // saveData.bondTest = dataRow.bondTest || ''; // } else if (pageNumber == 'P43' || pageNumber == 'P125') { // // P43/P125字段 // saveData.testMethod = dataRow.testMethod || ''; // saveData.testMethodName = dataRow.testMethodName || ''; // saveData.pictureRef = dataRow.pictureRef || ''; // saveData.flmc = dataRow.flmc || ''; // saveData.minSpec = dataRow.minSpec || ''; // if (pageNumber == 'P43') { // saveData.testParameter = dataRow.testParameter || ''; // } else if (pageNumber == 'P125') { // saveData.speed = dataRow.speed || ''; // } // } // 如果csan和pead不为空,也添加到保存数据中 if (dataRow.csan && dataRow.csan.trim() !== "") { saveData.csan = dataRow.csan; } if (dataRow.pead && dataRow.pead.trim() !== "") { saveData.pead = dataRow.pead; } saveDataList.push(saveData); } console.log("保存数据:", saveDataList); // 调用API保存数据 const response = await saveQualityStandards(saveDataList); proxy.$modal.msgSuccess( `保存 ${mainList.value[currentIndex].pfcCaption} 成功,共保存 ${saveDataList.length} 个测试用例` ); // 保存成功后重新加载数据,确保数据一致性 await loadSavedDataRows(currentIndex, baseInfo.pfcNo, baseInfo.pageNumber); } catch (error) { console.error("保存失败:", error); proxy.$modal.msgError("保存失败: " + (error.message || "未知错误")); } } // 监听弹窗关闭 watch(createDialog, (newVal) => { if (!newVal) { // 关闭弹窗时清理数据 currentTabData.value = {}; mainList.value = []; activeTab.value = "0"; } }); // 保存所有标签页 function handleSaveAll() { console.log("保存所有标签页数据:", currentTabData.value); // 遍历所有标签页数据并保存 Object.keys(currentTabData.value).forEach((index) => { const tabData = currentTabData.value[index]; console.log(`标签页 ${index} 数据:`, tabData); // 调用API保存每个标签页的数据 }); proxy.$modal.msgSuccess("所有数据保存成功"); createDialog.value = false; } function getTestList() { loading.value = true; ptrInfo(queryParams.value).then((response) => { ptrList.value = response.rows; totalTest.value = response.total; loading.value = false; }); } function handleAdd(row) { addQualityStand(row).then((response) => { proxy.$modal.msgSuccess("新增成功"); getList(); }); } /** 搜索按钮操作 */ function handleQuery() { queryParams.value.pageNum = 1; getList(); } function handleQueryTest() { queryParams.value.pageNum = 1; getTestList(); } /** 重置按钮操作 */ function resetQuery() { proxy.resetForm("queryRef"); handleQuery(); } function resetQueryTest() { proxy.resetForm("testRef"); handleQuery(); } getList(); </script> <style scoped> /* 为级联选择器添加样式,确保显示完整 */ :deep(.el-cascader) { width: 450px; /* 增加宽度以显示更长的路径 */ margin-right: 10px; } :deep(.el-cascader__dropdown) { max-height: 400px; /* 增加下拉框高度 */ } .readonly-input :deep(.el-input__inner) { background-color: #fff7e6; } /* 为级联选择器的标签添加更好的显示 */ :deep(.el-cascader-node__label) { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 300px; } /* 模板选择区域样式 */ .template-selector { display: flex; align-items: center; margin-bottom: 15px; padding: 10px; background-color: #f8f9fa; border-radius: 4px; } .template-selector-label { font-weight: bold; margin-right: 10px; min-width: 120px; } .template-selector-hint { margin-left: 10px; color: #666; font-size: 12px; } /* 图片上传样式 */ :deep(.el-upload-list--picture-card .el-upload-list__item) { width: 100px; height: 100px; } :deep(.el-upload--picture-card) { width: 100px; height: 100px; line-height: 100px; } :deep(.el-upload-list--picture-card .el-upload-list__item-thumbnail) { object-fit: contain; } .upload-tip { margin-top: 10px; color: #909399; font-size: 12px; } </style> 这是我目前的页面,需要在图片上传区域加一个照片墙用于上传图片和回显,我希望可以参考刚刚我提供的案例那样去实现,后端的接口我已经写好了@PostMapping("/images/upload") public AjaxResult uploadImages(@RequestParam("files") MultipartFile[] files, @RequestParam String pfcNo, @RequestParam String pageNumber) { try { if (files == null || files.length == 0) { return AjaxResult.error("上传文件不能为空"); } int successCount = qualityStandardService.uploadImages(files, pfcNo, pageNumber); return AjaxResult.success("上传成功,共上传 " + successCount + " 张图片"); } catch (Exception e) { e.printStackTrace(); return AjaxResult.error("上传失败: " + e.getMessage()); } }@Override public Integer uploadImages(MultipartFile[] files, String pfcNo, String pageNumber) { if (files == null || files.length == 0) { throw new ServiceException("上传文件不能为空"); } int successCount = 0; String username = SecurityUtils.getUsername(); Date now = MyDateUtils.getNowDate(); for (MultipartFile file : files) { try { // 跳过空文件 if (file.isEmpty()) { continue; } QualityShoeDesign qualityShoeDesign = new QualityShoeDesign(); // 执行上传 R<ToolsFile> fileResult = remoteFileService.upload(file, MinioBucketNameConstants.SHOEDESIGN, SecurityUtils.getFact(), file.getOriginalFilename(), FileEnum.LOCAL, SecurityConstants.INNER); if (MyStringUtils.isNull(fileResult) || MyStringUtils.isNull(fileResult.getData())) { throw new ServiceException("文件服务器异常"); } qualityShoeDesign.setPfcNo(pfcNo); qualityShoeDesign.setPageNumber(pageNumber); qualityShoeDesign.setFilePath(fileResult.getData().getUrl()); qualityShoeDesign.setOriginalName(file.getOriginalFilename()); qualityShoeDesign.setCreateBy(username); qualityShoeDesign.setCreateTime(now); // 插入记录 int result = qualityStandardMapper.insertQualityShoeDesign(qualityShoeDesign); if (result > 0) { successCount++; } } catch (Exception e) { // 记录错误日志,但继续处理其他文件 log.error("上传文件失败: {}", file.getOriginalFilename(), e); } } if (successCount == 0) { throw new ServiceException("所有文件上传失败"); } return successCount; }@GetMapping("/images/list") public AjaxResult getImages(@RequestParam String pfcNo, @RequestParam String pageNumber) { try { List<QualityShoeDesign> images = qualityStandardService.getImagesByPfcNoAndPage(pfcNo, pageNumber); return AjaxResult.success(images); } catch (Exception e) { return AjaxResult.error("获取图片列表失败: " + e.getMessage()); } }这些是上传代码和获取图片代码,请帮我生成合适的前端vue代码,图片上传我要可多选的
10-15
### 使用 `table.Rows.Add(newRow)` 向 `DataTable` 添加行操作详解 `table.Rows.Add(newRow)` 方法的主要功能是将一个新的 `DataRow` 对象添加到 `DataTable` 的 `Rows` 集合中。`DataRow` 对象可以通过 `DataTable.NewRow` 方法创建,该方法会创建一个与 `DataTable` 架构相匹配的新行对象。以下是一个示例代码: ```csharp using System; using System.Data; class Program { static void Main() { // 创建一个新的 DataTable DataTable table = new DataTable(); // 定义表的列 table.Columns.Add("ID", typeof(int)); table.Columns.Add("Name", typeof(string)); // 使用 NewRow 方法创建新行 DataRow newRow = table.NewRow(); // 为新行的列赋值 newRow["ID"] = 1; newRow["Name"] = "John Doe"; // 将新行添加到 DataTabletable.Rows.Add(newRow); // 输出 DataTable 中的数据 foreach (DataRow row in table.Rows) { Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}"); } } } ``` 在上述代码中,首先创建了一个 `DataTable` 对象,并定义了两列。然后使用 `NewRow` 方法创建了一个新的 `DataRow` 对象,为其列赋值后,将该新行添加到 `DataTable` 的 `Rows` 集合中。最后遍历 `DataTable` 的行并输出数据。 ### 常见问题及解决方案 #### 1. 数据类型不匹配问题 当为 `DataRow` 的列赋值时,如果数据类型与 `DataTable` 中定义的列的数据类型不匹配,会抛出 `InvalidCastException` 异常。 **解决方案**:在赋值前进行数据类型的检查和转换,确保赋值的数据类型与列的数据类型一致。例如: ```csharp DataRow newRow = table.NewRow(); object idValue = 1; if (idValue is int) { newRow["ID"] = idValue; } ``` #### 2. 违反约束问题 如果 `DataTable` 定义了约束(如唯一约束、外键约束等),当添加的行违反这些约束时,会抛出 `ConstraintException` 异常。 **解决方案**:在添加行之前,检查数据是否符合约束条件。或者在捕获异常后进行相应的处理,如提示用户重新输入数据。例如: ```csharp try { table.Rows.Add(newRow); } catch (ConstraintException ex) { Console.WriteLine($"添加行时违反约束: {ex.Message}"); // 可以在这里进行其他处理,如提示用户重新输入数据 } ``` #### 3. 并发访问问题 在多线程环境下,如果多个线程同时对 `DataTable` 的 `Rows` 集合进行添加操作,可能会导致数据不一致或抛出异常。 **解决方案**:使用线程同步机制,如 `lock` 语句来确保同一时间只有一个线程可以访问 `Rows` 集合。例如: ```csharp private static readonly object lockObject = new object(); // 在添加行的代码处进行加锁 lock (lockObject) { table.Rows.Add(newRow); } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值