fix: 参考中天的[检测标准]页面,设置总分两张表,总表代表着一个检测标准汇总(也要根据质检类型去选择),分表代表这个检测标准汇总下具体的检测参数信息。
已添加4个文件
已修改4个文件
1725 ■■■■ 文件已修改
src/api/basicData/productProcess.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qualityManagement/metricMaintenance.js 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/message.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PIMTable/PIMTable.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/metricMaintenance/ParamFormDialog.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/metricMaintenance/StandardFormDialog.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/metricMaintenance/index.vue 986 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/metricMaintenance/index0.vue 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/productProcess.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
import request from '@/utils/request'
// å·¥åºåˆ—表分页查询
export function productProcessListPage(query) {
  return request({
    url: '/productProcess/listPage',
    method: 'get',
    params: query
  })
}
src/api/qualityManagement/metricMaintenance.js
@@ -1,45 +1,90 @@
import request from '@/utils/request'
import request from "@/utils/request";
// æŸ¥è¯¢æŒ‡æ ‡åˆ—表
export function qualityTestStandardListPage(query) {
    return request({
        url: '/quality/qualityTestStandard/listPage',
        method: 'get',
    url: "/qualityTestStandard/listPage",
    method: "get",
        params: query,
    })
  });
}
// æ–°å¢žæŒ‡æ ‡åˆ—表
export function qualityTestStandardAdd(query) {
    return request({
        url: '/quality/qualityTestStandard/add',
        method: 'post',
    url: "/qualityTestStandard/add",
    method: "post",
        data: query,
    })
  });
}
// ä¿®æ”¹æŒ‡æ ‡åˆ—表
export function qualityTestStandardUpdate(query) {
    return request({
        url: '/quality/qualityTestStandard/update',
        method: 'post',
    url: "/qualityTestStandard/update",
    method: "post",
        data: query,
    })
  });
}
// åˆ é™¤æŒ‡æ ‡åˆ—表
export function qualityTestStandardDel(query) {
    return request({
        url: '/quality/qualityTestStandard/del',
        method: 'delete',
    url: "/qualityTestStandard/del",
    method: "delete",
        data: query,
    })
  });
}
// åˆ é™¤æŒ‡æ ‡åˆ—表
export function qualityInspectDetailByProductId(productId) {
    return request({
        url: '/quality/qualityTestStandard/product/' + productId,
        method: 'get',
    })
    url: "/qualityTestStandard/product/" + productId,
    method: "get",
  });
}
// å¤åˆ¶æ ‡å‡†å‚æ•°
export function qualityTestStandardCopyParam(id) {
  return request({
    url: "/qualityTestStandard/copyParam",
    method: "post",
    data: { id },
  });
}
// æ ‡å‡†å‚数:列表(不分页)
export function qualityTestStandardParamList(query) {
  return request({
    url: "/qualityTestStandardParam/list",
    method: "get",
    params: query,
  });
}
// æ ‡å‡†å‚数:新增
export function qualityTestStandardParamAdd(data) {
  return request({
    url: "/qualityTestStandardParam/add",
    method: "post",
    data,
  });
}
// æ ‡å‡†å‚数:修改
export function qualityTestStandardParamUpdate(data) {
  return request({
    url: "/qualityTestStandardParam/update",
    method: "post",
    data,
  });
}
// æ ‡å‡†å‚数:删除(传 id æ•°ç»„)
export function qualityTestStandardParamDel(ids) {
  return request({
    url: "/qualityTestStandardParam/del",
    method: "delete",
    data: ids,
  });
}
src/api/system/message.js
@@ -30,7 +30,7 @@
// ä¸€é”®æ ‡è®°æ‰€æœ‰æ¶ˆæ¯ä¸ºå·²è¯»
export function markAllAsRead() {
  return request({
    url: "/system/notice/markAllAsRead",
    url: "/system/notice/readAll",
    method: "post",
  });
}
src/components/PIMTable/PIMTable.vue
@@ -46,6 +46,16 @@
      :type="item.type"
      :width="item.width"
    >
      <template #header="scope">
        <div class="pim-table-header-cell">
          <div class="pim-table-header-title">
            {{ item.label }}
          </div>
          <div v-if="item.headerSlot" class="pim-table-header-extra">
            <slot :name="item.headerSlot" :column="scope.column" />
          </div>
        </div>
      </template>
      <template
        v-if="item.hasOwnProperty('colunmTemplate')"
        #[item.colunmTemplate]="scope"
@@ -429,4 +439,22 @@
  padding-right: 0 !important;
  padding-left: 0 !important;
}
.pim-table-header-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  text-align: center;
}
.pim-table-header-title {
  font-weight: 500;
}
.pim-table-header-extra :deep(.el-input),
.pim-table-header-extra :deep(.el-select) {
  width: 100%;
}
</style>
src/views/qualityManagement/metricMaintenance/ParamFormDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
<template>
  <FormDialog
    v-model="dialogVisible"
    :title="computedTitle"
    :operation-type="operationType"
    width="520px"
    @close="emit('close')"
    @cancel="handleCancel"
    @confirm="handleConfirm"
  >
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="100px"
    >
      <el-form-item label="参数项" prop="parameterItem">
        <el-input v-model="form.parameterItem" placeholder="请输入参数项" />
      </el-form-item>
      <el-form-item label="单位" prop="unit">
        <el-input v-model="form.unit" placeholder="请输入单位" />
      </el-form-item>
      <el-form-item label="标准值" prop="standardValue">
        <el-input v-model="form.standardValue" placeholder="请输入标准值" />
      </el-form-item>
      <el-form-item label="内控值" prop="controlValue">
        <el-input v-model="form.controlValue" placeholder="请输入内控值" />
      </el-form-item>
      <el-form-item label="默认值" prop="defaultValue">
        <el-input v-model="form.defaultValue" placeholder="请输入默认值" />
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
<script setup>
import { computed, ref } from 'vue'
import FormDialog from '@/components/Dialog/FormDialog.vue'
const props = defineProps({
  modelValue: { type: Boolean, default: false },
  operationType: { type: String, default: 'add' }, // add | edit
  form: { type: Object, required: true }
})
const emit = defineEmits(['update:modelValue', 'close', 'cancel', 'confirm'])
const dialogVisible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})
const formRef = ref(null)
const rules = {
  parameterItem: [{ required: true, message: '请输入参数项', trigger: 'blur' }],
  unit: [{ required: true, message: '请输入单位', trigger: 'blur' }]
}
const computedTitle = computed(() => (props.operationType === 'edit' ? '编辑标准参数' : '新增标准参数'))
const handleConfirm = () => {
  formRef.value?.validate?.((valid) => {
    if (valid) emit('confirm')
  })
}
const handleCancel = () => {
  emit('cancel')
  dialogVisible.value = false
}
const resetFields = () => {
  formRef.value?.resetFields?.()
}
defineExpose({ resetFields })
</script>
src/views/qualityManagement/metricMaintenance/StandardFormDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
<template>
  <FormDialog
    v-model="dialogVisible"
    :title="computedTitle"
    :operation-type="operationType"
    :width="width"
    @close="emit('close')"
    @cancel="handleCancel"
    @confirm="handleConfirm"
  >
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="100px"
    >
      <el-form-item label="标准编号" prop="standardNo">
        <el-input v-model="form.standardNo" placeholder="请输入标准编号" />
      </el-form-item>
      <el-form-item label="标准名称" prop="standardName">
        <el-input v-model="form.standardName" placeholder="请输入标准名称" />
      </el-form-item>
      <el-form-item label="类别" prop="inspectType">
        <el-select v-model="form.inspectType" placeholder="请选择类别" style="width: 100%">
          <el-option label="原材料检验" value="0" />
          <el-option label="过程检验" value="1" />
          <el-option label="出厂检验" value="2" />
        </el-select>
      </el-form-item>
      <el-form-item label="工序" prop="processId">
        <el-select v-model="form.processId" placeholder="请选择工序" style="width: 100%">
          <el-option
            v-for="item in processOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="状态" prop="state">
        <el-select v-model="form.state" placeholder="请选择状态" style="width: 100%">
          <el-option label="草稿" value="0" />
          <el-option label="通过" value="1" />
          <el-option label="撤销" value="2" />
        </el-select>
      </el-form-item>
      <el-form-item label="备注" prop="remark">
        <el-input
          v-model="form.remark"
          type="textarea"
          :rows="3"
          placeholder="请输入备注"
        />
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
<script setup>
import { computed, ref } from 'vue'
import FormDialog from '@/components/Dialog/FormDialog.vue'
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  operationType: {
    type: String,
    default: 'add'
  },
  form: {
    type: Object,
    required: true
  },
  rules: {
    type: Object,
    default: () => ({})
  },
  processOptions: {
    type: Array,
    default: () => []
  },
  width: {
    type: String,
    default: '500px'
  }
})
const emit = defineEmits(['update:modelValue', 'close', 'cancel', 'confirm'])
const dialogVisible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})
const formRef = ref(null)
const computedTitle = computed(() => {
  if (props.operationType === 'edit') return '编辑检测标准'
  if (props.operationType === 'copy') return '复制检测标准'
  return '新增检测标准'
})
const handleConfirm = () => {
  if (!formRef.value) {
    emit('confirm')
    return
  }
  formRef.value.validate((valid) => {
    if (valid) {
      emit('confirm')
    }
  })
}
const handleCancel = () => {
  emit('cancel')
  dialogVisible.value = false
}
const resetFields = () => {
  formRef.value?.resetFields?.()
}
defineExpose({
  resetFields
})
</script>
src/views/qualityManagement/metricMaintenance/index.vue
@@ -1,415 +1,685 @@
<template>
  <div class="app-container product-view">
    <div class="left">
      <div>
        <el-input
            v-model="search"
            style="width: 210px"
            placeholder="输入关键字进行搜索"
            @change="searchFilter"
            @clear="searchFilter"
            clearable
            prefix-icon="Search"
        />
  <div class="app-container metric-maintenance">
    <!-- å·¦ä¾§ï¼šæ£€æµ‹æ ‡å‡†åˆ—表 -->
    <div class="left-panel">
      <div class="toolbar">
        <div class="toolbar-left"></div>
        <div class="toolbar-right">
          <el-button type="primary" @click="openStandardDialog('add')">新增</el-button>
          <el-button type="danger" plain @click="handleBatchDelete">删除</el-button>
      </div>
      <div ref="containerRef">
        <el-tree
            ref="tree"
            v-loading="treeLoad"
            :data="list"
            @node-click="handleNodeClick"
            :expand-on-click-node="false"
            default-expand-all
            :default-expanded-keys="expandedKeys"
            :draggable="true"
            :filter-node-method="filterNode"
            :props="{ children: 'children', label: 'label' }"
            highlight-current
            node-key="id"
            style="
            height: calc(100vh - 190px);
            overflow-y: scroll;
            scrollbar-width: none;
          "
        >
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span class="tree-node-content">
                <el-icon class="orange-icon">
                  <component :is="data.children && data.children.length > 0
                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                </el-icon>
                {{ data.label }}
              </span>
            </div>
          </template>
        </el-tree>
      </div>
    </div>
    <div class="right">
      <div style="margin-bottom: 10px">
        <el-button type="primary" @click="openModelDia('add')">
          æ–°å¢žæ£€æµ‹æŒ‡æ ‡
        </el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button
            type="danger"
            @click="handleDelete"
            style="margin-left: 10px"
            plain
        >
          åˆ é™¤
        </el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
        :column="standardColumns"
        :tableData="standardTableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
        @selection-change="handleSelectionChange"
        @pagination="handlePagination"
          :total="page.total"
      ></PIMTable>
    </div>
    <el-dialog
        v-model="modelDia"
        title="检测指标"
        width="400px"
        @close="closeModelDia"
    >
      <el-form
          :model="modelForm"
          label-width="140px"
          label-position="top"
          :rules="modelRules"
          ref="modelFormRef"
      >
        <el-row>
          <el-col :span="24">
            <el-form-item label="指标:" prop="parameterItem">
              <el-input
                  v-model="modelForm.parameterItem"
                  placeholder="请输入指标"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="单位:" prop="unit">
              <el-input
                  v-model="modelForm.unit"
                  placeholder="请输入单位"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="标准值:" prop="standardValue">
              <el-input
                  v-model="modelForm.standardValue"
                  placeholder="请输入标准值"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="内控值:" prop="controlValue">
              <el-input
                  v-model="modelForm.controlValue"
                  placeholder="请输入内控值"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitModelForm">确认</el-button>
          <el-button @click="closeModelDia">取消</el-button>
        </div>
        <template #standardNoCell="{ row }">
          <span class="clickable-link" @click="handleStandardRowClick(row)">
            {{ row.standardNo }}
          </span>
      </template>
    </el-dialog>
        <!-- è¡¨å¤´æœç´¢æ’æ§½ -->
        <template #standardNoHeader>
          <el-input
            v-model="searchForm.standardNo"
            placeholder="标准编号"
            clearable
            size="small"
            @change="handleQuery"
            @clear="handleQuery"
          />
        </template>
        <template #standardNameHeader>
          <el-input
            v-model="searchForm.standardName"
            placeholder="标准名称"
            clearable
            size="small"
            @change="handleQuery"
            @clear="handleQuery"
          />
        </template>
        <template #inspectTypeHeader>
          <el-select
            v-model="searchForm.inspectType"
            placeholder="类别"
            clearable
            size="small"
            style="width: 120px"
            @change="handleQuery"
            @clear="handleQuery"
          >
            <el-option label="原材料检验" value="0" />
            <el-option label="过程检验" value="1" />
            <el-option label="出厂检验" value="2" />
          </el-select>
        </template>
        <template #stateHeader>
          <el-select
            v-model="searchForm.state"
            placeholder="状态"
            clearable
            size="small"
            style="width: 110px"
            @change="handleQuery"
            @clear="handleQuery"
          >
            <el-option label="草稿" value="0" />
            <el-option label="通过" value="1" />
            <el-option label="撤销" value="2" />
          </el-select>
        </template>
      </PIMTable>
    </div>
    <!-- å³ä¾§ï¼šæ ‡å‡†å‚数列表 -->
    <div class="right-panel">
      <div class="right-header">
        <div class="title">标准参数</div>
        <div class="desc" v-if="currentStandard">
          æ‚¨å½“前选择的检测标准编号是:
          <span class="link-text">{{ currentStandard.standardNo }}</span>
        </div>
        <div class="desc" v-else>请先在左侧选择一个检测标准</div>
      </div>
      <div class="right-toolbar">
        <el-button type="primary" :disabled="!currentStandard" @click="openParamDialog('add')">
          æ–°å¢ž
        </el-button>
        <el-button type="danger" plain :disabled="!currentStandard" @click="handleParamBatchDelete">
          åˆ é™¤
        </el-button>
      </div>
      <el-table
        v-loading="detailLoading"
        :data="detailTableData"
        border
        style="width: 100%"
        height="calc(100vh - 220px)"
        @selection-change="handleParamSelectionChange"
      >
        <el-table-column type="selection" width="48" align="center" />
        <el-table-column type="index" label="序号" width="60" align="center" />
        <el-table-column prop="parameterItem" label="参数项" min-width="120" />
        <el-table-column prop="unit" label="单位" width="80" />
        <el-table-column prop="standardValue" label="标准值" min-width="120" />
        <el-table-column prop="controlValue" label="内控值" min-width="120" />
        <el-table-column prop="defaultValue" label="默认值" min-width="120" />
        <el-table-column label="操作" width="140" fixed="right" align="center">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click="openParamDialog('edit', row)">
              ç¼–辑
            </el-button>
            <el-button link type="danger" size="small" @click="handleParamDelete(row)">
              åˆ é™¤
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- æ–°å¢ž / ç¼–辑检测标准 -->
    <StandardFormDialog
      ref="standardFormDialogRef"
      v-model="standardDialogVisible"
      :operation-type="standardOperationType"
      :form="standardForm"
      :rules="standardRules"
      :process-options="processOptions"
      @confirm="submitStandardForm"
      @close="closeStandardDialog"
      @cancel="closeStandardDialog"
    />
    <ParamFormDialog
      ref="paramFormDialogRef"
      v-model="paramDialogVisible"
      :operation-type="paramOperationType"
      :form="paramForm"
      @confirm="submitParamForm"
      @close="closeParamDialog"
      @cancel="closeParamDialog"
    />
  </div>
</template>
<script setup>
import {ref} from "vue";
import {addOrEditProductModel, delProductModel, modelListPage, productTreeList} from "@/api/basicData/product.js";
import ImportExcel from "@/views/basicData/product/ImportExcel/index.vue";
import {ElMessageBox} from "element-plus";
import { Search } from '@element-plus/icons-vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ElMessageBox } from 'element-plus'
import {
  qualityTestStandardAdd, qualityTestStandardDel,
  qualityTestStandardListPage,
  qualityTestStandardUpdate
} from "@/api/qualityManagement/metricMaintenance.js";
const { proxy } = getCurrentInstance();
// æ ‘
const search = ref("");
const treeLoad = ref(false);
const list = ref([]);
const expandedKeys = ref([]);
const currentId = ref("");
const currentParentId = ref("");
// æŒ‡æ ‡è¡¨æ ¼
const tableData = ref([]);
const tableLoading = ref(false);
  qualityTestStandardAdd,
  qualityTestStandardUpdate,
  qualityTestStandardDel,
  qualityTestStandardCopyParam,
  qualityTestStandardParamList,
  qualityTestStandardParamAdd,
  qualityTestStandardParamUpdate,
  qualityTestStandardParamDel
} from '@/api/qualityManagement/metricMaintenance.js'
import { productProcessListPage } from '@/api/basicData/productProcess.js'
import StandardFormDialog from './StandardFormDialog.vue'
import ParamFormDialog from './ParamFormDialog.vue'
const { proxy } = getCurrentInstance()
// æœç´¢æ¡ä»¶
const data = reactive({
  searchForm: {
    standardNo: '',
    standardName: '',
    remark: '',
    state: '',
    inspectType: '',
    processId: ''
  },
  standardForm: {
    id: undefined,
    standardNo: '',
    standardName: '',
    remark: '',
    state: '0',
    inspectType: '',
    processId: ''
  },
  standardRules: {
    standardNo: [{ required: true, message: '请输入标准编号', trigger: 'blur' }],
    standardName: [{ required: true, message: '请输入标准名称', trigger: 'blur' }],
    inspectType: [{ required: true, message: '请选择检测类型', trigger: 'change' }],
    processId: [{ required: true, message: '请选择工序', trigger: 'change' }]
  }
})
const { searchForm, standardForm, standardRules } = toRefs(data)
// å·¦ä¾§è¡¨æ ¼
const standardTableData = ref([])
const selectedRows = ref([])
const tableLoading = ref(false)
const page = reactive({
  current: 1,
  size: 10,
});
const tableColumn = ref([
  total: 0
})
// å·¥åºä¸‹æ‹‰
const processOptions = ref([])
// èŽ·å–å·¥åºåˆ—è¡¨
const getProcessList = async () => {
  try {
    const res = await productProcessListPage({ current: 1, size: 1000 })
    if (res?.code === 200) {
      const records = res?.data?.records || []
      processOptions.value = records.map(item => ({
        label: item.processName || item.name || item.label,
        value: item.id || item.processId || item.value
      }))
    }
  } catch (error) {
    console.error('获取工序列表失败:', error)
  }
}
// å½“前选中的标准 & å³ä¾§è¯¦æƒ…
const currentStandard = ref(null)
const detailTableData = ref([])
const detailLoading = ref(false)
const paramSelectedRows = ref([])
const paramDialogVisible = ref(false)
const paramOperationType = ref('add') // add | edit
const paramFormDialogRef = ref(null)
const paramForm = reactive({
  id: undefined,
  parameterItem: '',
  unit: '',
  standardValue: '',
  controlValue: '',
  defaultValue: ''
})
// å¼¹çª—
const standardDialogVisible = ref(false)
const standardOperationType = ref('add') // add | edit | copy
const standardFormDialogRef = ref(null)
// åˆ—定义
const standardColumns = ref([
  {
    label: "指标",
    prop: "parameterItem",
    label: '标准编号',
    prop: 'standardNo',
    dataType: 'slot',
    slot: 'standardNoCell',
    minWidth: 160,
    headerSlot: 'standardNoHeader'
  },
  {
    label: "单位",
    prop: "unit",
    label: '标准名称',
    prop: 'standardName',
    minWidth: 180,
    headerSlot: 'standardNameHeader'
  },
  {
    label: "标准值",
    prop: "standardValue",
    label: '类别',
    prop: 'inspectType',
    headerSlot: 'inspectTypeHeader',
    dataType: 'tag',
    formatData: (val) => {
      const map = {
        0: '原材料检验',
        1: '过程检验',
        2: '出厂检验'
      }
      return map[val] || val
    }
  },
  {
    label: "内控值",
    prop: "controlValue",
    label: '工序',
    prop: 'processId'
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    label: '状态',
    prop: 'state',
    headerSlot: 'stateHeader',
    dataType: 'tag',
    formatData: (val) => {
      const map = {
        0: '草稿',
        1: '通过',
        2: '撤销'
      }
      return map[val] || val
    },
    formatType: (val) => {
      if (val === '1' || val === 1) return 'success'
      if (val === '2' || val === 2) return 'warning'
      return 'info'
    }
  },
  {
    label: '备注',
    prop: 'remark',
    minWidth: 160
  },
  {
    dataType: 'action',
    label: '操作',
    align: 'center',
    fixed: 'right',
    width: 220,
    operation: [
      {
        name: "编辑",
        type: "text",
        name: '编辑',
        type: 'text',
        clickFun: (row) => {
          openModelDia("edit", row);
          openStandardDialog('edit', row)
        }
        },
      {
        name: '复制',
        type: 'text',
        clickFun: async (row) => {
          if (!row?.id) return
          try {
            await ElMessageBox.confirm('确认复制该标准参数?', '提示', { type: 'warning' })
          } catch {
            return
          }
          await qualityTestStandardCopyParam(row.id)
          proxy.$message.success('复制成功')
          getStandardList()
          if (currentStandard.value?.id === row.id) {
            loadDetail(row.id)
          }
        }
      },
    ],
  },
]);
const selectedRows = ref([]);
// æŒ‡æ ‡å¼¹æ¡†
const modelDia = ref(false);
const modelOperationType = ref("");
const data = reactive({
  modelForm: {
    parameterItem: "",
    unit: "",
    standardValue: "",
    controlValue: "",
  },
  modelRules: {
    parameterItem: [{ required: true, message: "请输入", trigger: "blur" }],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    standardValue: [{ required: true, message: "请输入", trigger: "blur" }],
    controlValue: [{ required: true, message: "请输入", trigger: "blur" }],
  },
});
const { modelForm, modelRules } = toRefs(data);
      {
        name: '删除',
        type: 'text',
        clickFun: (row) => {
          handleDelete(row)
        }
      }
    ]
  }
])
// æŸ¥è¯¢äº§å“æ ‘
const getProductTreeList = () => {
  treeLoad.value = true;
  productTreeList().then((res) => {
    list.value = res;
    list.value.forEach((a) => {
      expandedKeys.value.push(a.label);
    });
    treeLoad.value = false;
  }).catch((err) => {
    treeLoad.value = false;
  });
};
// è¿‡æ»¤äº§å“æ ‘
const searchFilter = () => {
  proxy.$refs.tree.filter(search.value);
};
// é€‰æ‹©äº§å“
const handleNodeClick = (val, node, el) => {
  // åªæœ‰å¶å­èŠ‚ç‚¹æ‰æ‰§è¡Œä»¥ä¸‹é€»è¾‘
  currentId.value = val.id;
  currentParentId.value = val.parentId;
  getModelList();
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æŸ¥è¯¢æŒ‡æ ‡æ•°æ®
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getModelList();
};
const getModelList = () => {
  tableLoading.value = true;
  qualityTestStandardListPage({
    productId: currentId.value,
// æŸ¥è¯¢åˆ—表
const getStandardList = () => {
  tableLoading.value = true
  const params = {
    ...searchForm.value,
    current: page.current,
    size: page.size,
  }).then((res) => {
    tableData.value = res.data.records;
    page.total = res.data.total;
    tableLoading.value = false;
  });
};
// è°ƒç”¨tree过滤方法 ä¸­æ–‡è‹±è¿‡æ»¤
const filterNode = (value, data, node) => {
  if (!value) {
    //如果数据为空,则返回true,显示所有的数据项
    return true;
    size: page.size
  }
  // æŸ¥è¯¢åˆ—表是否有匹配数据,将值小写,匹配英文数据
  let val = value.toLowerCase();
  return chooseNode(val, data, node); // è°ƒç”¨è¿‡æ»¤äºŒå±‚方法
};
// è¿‡æ»¤çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹ (如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。name是中文字符,enName是英文字符.
const chooseNode = (value, data, node) => {
  if (data.label.indexOf(value) !== -1) {
    return true;
  qualityTestStandardListPage(params)
    .then((res) => {
      const records = res?.data?.records || []
      standardTableData.value = records
      page.total = res?.data?.total || records.length
    })
    .finally(() => {
      tableLoading.value = false
    })
  }
  const level = node.level;
  // å¦‚果传入的节点本身就是一级节点就不用校验了
  if (level === 1) {
    return false;
  }
  // å…ˆå–当前节点的父节点
  let parentData = node.parent;
  // éåŽ†å½“å‰èŠ‚ç‚¹çš„çˆ¶èŠ‚ç‚¹
  let index = 0;
  while (index < level - 1) {
    // å¦‚果匹配到直接返回,此处name值是中文字符,enName是英文字符。判断匹配中英文过滤
    if (parentData.data.label.indexOf(value) !== -1) {
      return true;
    }
    // å¦åˆ™çš„话再往上一层做匹配
    parentData = parentData.parent;
    index++;
  }
  // æ²¡åŒ¹é…åˆ°è¿”回false
  return false;
};
// æ‰“开指标弹框
const openModelDia = (type, data) => {
  modelOperationType.value = type;
  modelDia.value = true;
  modelForm.value.model = "";
  modelForm.value.model = "";
  modelForm.value.id = "";
  if (type === "edit") {
    modelForm.value = { ...data };
  }
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    proxy.download("/quality/qualityTestStandard/export", {}, "检测指标.xlsx");
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
// åˆ é™¤æŒ‡æ ‡
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
const handleQuery = () => {
  page.current = 1
  getStandardList()
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    tableLoading.value = true;
    qualityTestStandardDel(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getModelList();
    }).finally(() => {
      tableLoading.value = false;
    });
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
// æäº¤è§„格型号修改
const submitModelForm = () => {
  proxy.$refs.modelFormRef.validate((valid) => {
    if (valid) {
      modelForm.value.productId = Number(currentId.value);
      if(modelOperationType.value === 'add') {
        qualityTestStandardAdd(modelForm.value).then((res) => {
          proxy.$modal.msgSuccess("提交成功");
          closeModelDia();
          getModelList();
        });
const resetQuery = () => {
  searchForm.value.standardNo = ''
  searchForm.value.standardName = ''
  searchForm.value.remark = ''
  searchForm.value.state = ''
  searchForm.value.inspectType = ''
  searchForm.value.processId = ''
  handleQuery()
}
const handlePagination = (obj) => {
  page.current = obj.page
  page.size = obj.limit
  getStandardList()
}
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
// å·¦ä¾§è¡Œç‚¹å‡»ï¼ŒåŠ è½½å³ä¾§å‚æ•°
const handleStandardRowClick = (row) => {
  currentStandard.value = row
  loadDetail(row.id)
}
const loadDetail = (standardId) => {
  if (!standardId) {
    detailTableData.value = []
    return
  }
  detailLoading.value = true
  qualityTestStandardParamList({ testStandardId: standardId }).then((res) => {
    detailTableData.value = res?.data || []
  })
    .finally(() => {
      detailLoading.value = false
    })
}
const handleParamSelectionChange = (selection) => {
  paramSelectedRows.value = selection
}
const openParamDialog = (type, row) => {
  if (!currentStandard.value?.id) return
  paramOperationType.value = type
  if (type === 'add') {
    Object.assign(paramForm, {
      id: undefined,
      parameterItem: '',
      unit: '',
      standardValue: '',
      controlValue: '',
      defaultValue: ''
    })
  } else if (type === 'edit' && row) {
    Object.assign(paramForm, row)
  }
  paramDialogVisible.value = true
}
const closeParamDialog = () => {
  paramDialogVisible.value = false
  paramFormDialogRef.value?.resetFields?.()
}
const submitParamForm = async () => {
  const testStandardId = currentStandard.value?.id
  if (!testStandardId) return
  const payload = { ...paramForm, testStandardId }
  if (paramOperationType.value === 'edit') {
    await qualityTestStandardParamUpdate(payload)
    proxy.$message.success('提交成功')
      } else {
        qualityTestStandardUpdate(modelForm.value).then((res) => {
          proxy.$modal.msgSuccess("提交成功");
          closeModelDia();
          getModelList();
        });
    await qualityTestStandardParamAdd(payload)
    proxy.$message.success('提交成功')
  }
  closeParamDialog()
  loadDetail(testStandardId)
}
const handleParamDelete = async (row) => {
  if (!row?.id) return
  try {
    await ElMessageBox.confirm('确认删除该参数?', '提示', { type: 'warning' })
  } catch {
    return
  }
  await qualityTestStandardParamDel([row.id])
  proxy.$message.success('删除成功')
  loadDetail(currentStandard.value?.id)
}
const handleParamBatchDelete = async () => {
  if (!paramSelectedRows.value.length) {
    proxy.$message.warning('请选择数据')
    return
  }
  const ids = paramSelectedRows.value.map((i) => i.id)
  try {
    await ElMessageBox.confirm('选中的内容将被删除,是否确认删除?', '删除提示', { type: 'warning' })
  } catch {
    return
  }
  await qualityTestStandardParamDel(ids)
  proxy.$message.success('删除成功')
  loadDetail(currentStandard.value?.id)
}
// æ–°å¢ž / ç¼–辑 / å¤åˆ¶
const openStandardDialog = (type, row) => {
  standardOperationType.value = type
  if (type === 'add') {
    Object.assign(standardForm.value, {
      id: undefined,
      standardNo: '',
      standardName: '',
      remark: '',
      state: '0',
      inspectType: '',
      processId: ''
    })
  } else if (type === 'edit' && row) {
    Object.assign(standardForm.value, row)
  } else if (type === 'copy' && row) {
    const { id, ...rest } = row
    Object.assign(standardForm.value, {
      ...rest,
      id: undefined,
      standardNo: '',
      state: '0'
    })
  }
  standardDialogVisible.value = true
}
const closeStandardDialog = () => {
  standardDialogVisible.value = false
  standardFormDialogRef.value?.resetFields?.()
}
const submitStandardForm = () => {
  const payload = { ...standardForm.value }
  const isEdit = standardOperationType.value === 'edit'
  if (isEdit) {
    qualityTestStandardUpdate(payload).then(() => {
      proxy.$message.success('提交成功')
      standardDialogVisible.value = false
      getStandardList()
    })
  } else {
    qualityTestStandardAdd(payload).then(() => {
       proxy.$message.success('提交成功')
      standardDialogVisible.value = false
      getStandardList()
    })
      }
    }
  });
};
// å…³é—­åž‹å·å¼¹æ¡†
const closeModelDia = () => {
  proxy.$refs.modelFormRef.resetFields();
  modelDia.value = false;
};
getProductTreeList();
// åˆ é™¤ï¼ˆå•条)
const handleDelete = (row) => {
  const ids = [row.id]
  ElMessageBox.confirm('选中的内容将被删除,是否确认删除?', '删除提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      tableLoading.value = true
      qualityTestStandardDel(ids)
        .then(() => {
          proxy.$message.success('删除成功')
          getStandardList()
          if (currentStandard.value && currentStandard.value.id === row.id) {
            currentStandard.value = null
            detailTableData.value = []
          }
        })
        .finally(() => {
          tableLoading.value = false
        })
    })
    .catch(() => {
      proxy.$modal?.msg('已取消')
    })
}
// æ‰¹é‡åˆ é™¤
const handleBatchDelete = () => {
  if (!selectedRows.value.length) {
    proxy.$message.warning('请选择数据')
    return
  }
  const ids = selectedRows.value.map((item) => item.id)
  ElMessageBox.confirm('选中的内容将被删除,是否确认删除?', '删除提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      tableLoading.value = true
      qualityTestStandardDel(ids)
        .then(() => {
           proxy.$message.success('删除成功')
          getStandardList()
          if (currentStandard.value && ids.includes(currentStandard.value.id)) {
            currentStandard.value = null
            detailTableData.value = []
          }
        })
        .finally(() => {
          tableLoading.value = false
        })
    })
    .catch(() => {
      proxy.$modal?.msg('已取消')
    })
}
onMounted(() => {
  getProcessList()
  getStandardList()
})
</script>
<style scoped>
.product-view {
.metric-maintenance {
  display: flex;
  gap: 16px;
}
.left {
  width: 380px;
  padding: 16px;
  background: #ffffff;
}
.right {
  width: calc(100% - 380px);
  padding: 16px;
  margin-left: 20px;
  background: #ffffff;
}
.custom-tree-node {
.left-panel,
.right-panel {
  flex: 1;
  background: #ffffff;
  padding: 16px;
  box-sizing: border-box;
}
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.toolbar-left {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
  flex-wrap: wrap;
  gap: 4px;
}
.tree-node-content {
.toolbar-right {
  flex-shrink: 0;
}
.search-label {
  margin: 0 4px 0 12px;
}
.search-label:first-of-type {
  margin-left: 0;
}
.right-header {
  display: flex;
  align-items: center; /* åž‚直居中 */
  height: 100%;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
.orange-icon {
  color: orange;
  font-size: 18px;
  margin-right: 8px; /* å›¾æ ‡ä¸Žæ–‡å­—之间加点间距 */
.right-header .title {
  font-size: 16px;
  font-weight: 600;
}
.right-header .desc {
  font-size: 13px;
  color: #666;
}
.right-toolbar {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-bottom: 10px;
}
.link-text {
  color: #409eff;
  cursor: default;
}
.clickable-link {
  color: #409eff;
  cursor: pointer;
}
.clickable-link:hover {
  text-decoration: underline;
}
</style>
src/views/qualityManagement/metricMaintenance/index0.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,415 @@
<template>
  <div class="app-container product-view">
    <div class="left">
      <div>
        <el-input
            v-model="search"
            style="width: 210px"
            placeholder="输入关键字进行搜索"
            @change="searchFilter"
            @clear="searchFilter"
            clearable
            prefix-icon="Search"
        />
      </div>
      <div ref="containerRef">
        <el-tree
            ref="tree"
            v-loading="treeLoad"
            :data="list"
            @node-click="handleNodeClick"
            :expand-on-click-node="false"
            default-expand-all
            :default-expanded-keys="expandedKeys"
            :draggable="true"
            :filter-node-method="filterNode"
            :props="{ children: 'children', label: 'label' }"
            highlight-current
            node-key="id"
            style="
            height: calc(100vh - 190px);
            overflow-y: scroll;
            scrollbar-width: none;
          "
        >
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span class="tree-node-content">
                <el-icon class="orange-icon">
                  <component :is="data.children && data.children.length > 0
                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                </el-icon>
                {{ data.label }}
              </span>
            </div>
          </template>
        </el-tree>
      </div>
    </div>
    <div class="right">
      <div style="margin-bottom: 10px">
        <el-button type="primary" @click="openModelDia('add')">
          æ–°å¢žæ£€æµ‹æŒ‡æ ‡
        </el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button
            type="danger"
            @click="handleDelete"
            style="margin-left: 10px"
            plain
        >
          åˆ é™¤
        </el-button>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
          :total="page.total"
      ></PIMTable>
    </div>
    <el-dialog
        v-model="modelDia"
        title="检测指标"
        width="400px"
        @close="closeModelDia"
    >
      <el-form
          :model="modelForm"
          label-width="140px"
          label-position="top"
          :rules="modelRules"
          ref="modelFormRef"
      >
        <el-row>
          <el-col :span="24">
            <el-form-item label="指标:" prop="parameterItem">
              <el-input
                  v-model="modelForm.parameterItem"
                  placeholder="请输入指标"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="单位:" prop="unit">
              <el-input
                  v-model="modelForm.unit"
                  placeholder="请输入单位"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="标准值:" prop="standardValue">
              <el-input
                  v-model="modelForm.standardValue"
                  placeholder="请输入标准值"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="内控值:" prop="controlValue">
              <el-input
                  v-model="modelForm.controlValue"
                  placeholder="请输入内控值"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitModelForm">确认</el-button>
          <el-button @click="closeModelDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {addOrEditProductModel, delProductModel, modelListPage, productTreeList} from "@/api/basicData/product.js";
import ImportExcel from "@/views/basicData/product/ImportExcel/index.vue";
import {ElMessageBox} from "element-plus";
import {
  qualityTestStandardAdd, qualityTestStandardDel,
  qualityTestStandardListPage,
  qualityTestStandardUpdate
} from "@/api/qualityManagement/metricMaintenance.js";
const { proxy } = getCurrentInstance();
// æ ‘
const search = ref("");
const treeLoad = ref(false);
const list = ref([]);
const expandedKeys = ref([]);
const currentId = ref("");
const currentParentId = ref("");
// æŒ‡æ ‡è¡¨æ ¼
const tableData = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 10,
});
const tableColumn = ref([
  {
    label: "指标",
    prop: "parameterItem",
  },
  {
    label: "单位",
    prop: "unit",
  },
  {
    label: "标准值",
    prop: "standardValue",
  },
  {
    label: "内控值",
    prop: "controlValue",
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openModelDia("edit", row);
        },
      },
    ],
  },
]);
const selectedRows = ref([]);
// æŒ‡æ ‡å¼¹æ¡†
const modelDia = ref(false);
const modelOperationType = ref("");
const data = reactive({
  modelForm: {
    parameterItem: "",
    unit: "",
    standardValue: "",
    controlValue: "",
  },
  modelRules: {
    parameterItem: [{ required: true, message: "请输入", trigger: "blur" }],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    standardValue: [{ required: true, message: "请输入", trigger: "blur" }],
    controlValue: [{ required: true, message: "请输入", trigger: "blur" }],
  },
});
const { modelForm, modelRules } = toRefs(data);
// æŸ¥è¯¢äº§å“æ ‘
const getProductTreeList = () => {
  treeLoad.value = true;
  productTreeList().then((res) => {
    list.value = res;
    list.value.forEach((a) => {
      expandedKeys.value.push(a.label);
    });
    treeLoad.value = false;
  }).catch((err) => {
    treeLoad.value = false;
  });
};
// è¿‡æ»¤äº§å“æ ‘
const searchFilter = () => {
  proxy.$refs.tree.filter(search.value);
};
// é€‰æ‹©äº§å“
const handleNodeClick = (val, node, el) => {
  // åªæœ‰å¶å­èŠ‚ç‚¹æ‰æ‰§è¡Œä»¥ä¸‹é€»è¾‘
  currentId.value = val.id;
  currentParentId.value = val.parentId;
  getModelList();
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// æŸ¥è¯¢æŒ‡æ ‡æ•°æ®
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getModelList();
};
const getModelList = () => {
  tableLoading.value = true;
  qualityTestStandardListPage({
    productId: currentId.value,
    current: page.current,
    size: page.size,
  }).then((res) => {
    tableData.value = res.data.records;
    page.total = res.data.total;
    tableLoading.value = false;
  });
};
// è°ƒç”¨tree过滤方法 ä¸­æ–‡è‹±è¿‡æ»¤
const filterNode = (value, data, node) => {
  if (!value) {
    //如果数据为空,则返回true,显示所有的数据项
    return true;
  }
  // æŸ¥è¯¢åˆ—表是否有匹配数据,将值小写,匹配英文数据
  let val = value.toLowerCase();
  return chooseNode(val, data, node); // è°ƒç”¨è¿‡æ»¤äºŒå±‚方法
};
// è¿‡æ»¤çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹ (如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。name是中文字符,enName是英文字符.
const chooseNode = (value, data, node) => {
  if (data.label.indexOf(value) !== -1) {
    return true;
  }
  const level = node.level;
  // å¦‚果传入的节点本身就是一级节点就不用校验了
  if (level === 1) {
    return false;
  }
  // å…ˆå–当前节点的父节点
  let parentData = node.parent;
  // éåŽ†å½“å‰èŠ‚ç‚¹çš„çˆ¶èŠ‚ç‚¹
  let index = 0;
  while (index < level - 1) {
    // å¦‚果匹配到直接返回,此处name值是中文字符,enName是英文字符。判断匹配中英文过滤
    if (parentData.data.label.indexOf(value) !== -1) {
      return true;
    }
    // å¦åˆ™çš„话再往上一层做匹配
    parentData = parentData.parent;
    index++;
  }
  // æ²¡åŒ¹é…åˆ°è¿”回false
  return false;
};
// æ‰“开指标弹框
const openModelDia = (type, data) => {
  modelOperationType.value = type;
  modelDia.value = true;
  modelForm.value.model = "";
  modelForm.value.model = "";
  modelForm.value.id = "";
  if (type === "edit") {
    modelForm.value = { ...data };
  }
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    proxy.download("/quality/qualityTestStandard/export", {}, "检测指标.xlsx");
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
// åˆ é™¤æŒ‡æ ‡
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    tableLoading.value = true;
    qualityTestStandardDel(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
      getModelList();
    }).finally(() => {
      tableLoading.value = false;
    });
  }).catch(() => {
    proxy.$modal.msg("已取消");
  });
};
// æäº¤è§„格型号修改
const submitModelForm = () => {
  proxy.$refs.modelFormRef.validate((valid) => {
    if (valid) {
      modelForm.value.productId = Number(currentId.value);
      if(modelOperationType.value === 'add') {
        qualityTestStandardAdd(modelForm.value).then((res) => {
          proxy.$modal.msgSuccess("提交成功");
          closeModelDia();
          getModelList();
        });
      } else {
        qualityTestStandardUpdate(modelForm.value).then((res) => {
          proxy.$modal.msgSuccess("提交成功");
          closeModelDia();
          getModelList();
        });
      }
    }
  });
};
// å…³é—­åž‹å·å¼¹æ¡†
const closeModelDia = () => {
  proxy.$refs.modelFormRef.resetFields();
  modelDia.value = false;
};
getProductTreeList();
</script>
<style scoped>
.product-view {
  display: flex;
}
.left {
  width: 380px;
  padding: 16px;
  background: #ffffff;
}
.right {
  width: calc(100% - 380px);
  padding: 16px;
  margin-left: 20px;
  background: #ffffff;
}
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
.tree-node-content {
  display: flex;
  align-items: center; /* åž‚直居中 */
  height: 100%;
}
.orange-icon {
  color: orange;
  font-size: 18px;
  margin-right: 8px; /* å›¾æ ‡ä¸Žæ–‡å­—之间加点间距 */
}
</style>