guoyujie
8 天以前 2bb136b11d19e0397239c9469525effd4f8df5b8
提交部分bom代码
2个文件已修改
5个文件已添加
1715 ■■■■■ 已修改文件
north-glass-erp/northglass-erp/src/hook/footSum.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/router/index.js 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/BOM.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/MaterialBOM.vue 456 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/OrderBOM.vue 698 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/ProductBOM.vue 398 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/bom/ProductBomAdd.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/hook/footSum.js
@@ -3,9 +3,9 @@
    list.forEach(item => {
        if(field.indexOf('.')>-1){
            let  array = field.split('.')
            count += Number(item[array[0]][array[1]])
            count += Number(item[array[0]][array[1]]) || 0
        }else {
            count += Number(item[field])
            count += Number(item[field])  || 0
        }
    })
    return count.toFixed(2)
north-glass-erp/northglass-erp/src/router/index.js
@@ -111,7 +111,34 @@
            }
          ]
        },
          //bom模块
        {
          path:'bom',
          name: 'bom',
          component: () => import('../views/sd/bom/BOM.vue'),
          children:[
            {
              path: 'materialBOM',
              name: 'materialBOM',
              component: () => import('../views/sd/bom/MaterialBOM.vue')
            },
            {
              path: 'productBOM',
              name: 'productBOM',
              component: () => import('../views/sd/bom/ProductBOM.vue')
            },
            {
              path: 'orderBOM',
              name: 'orderBOM',
              component: () => import('../views/sd/bom/OrderBOM.vue')
            },
            {
              name: 'bom1',
              path: '',
              redirect:'/main/bom/orderBOM'
            }
          ]
        },
          //sd模块
        {
@@ -655,7 +682,7 @@
            }
          ]
        },
        {
        /*{
          //BOM管理
          path: 'BOM',
          name: 'BOM',
@@ -696,7 +723,7 @@
              redirect:'/main/BOM/SelectBOM'
            }
          ]
        },
        },*/
        {
          //设备管理
          path: 'machine',
north-glass-erp/northglass-erp/src/views/sd/bom/BOM.vue
New file
@@ -0,0 +1,64 @@
<script setup>
import {ArrowLeftBold, ArrowRight, Search} from "@element-plus/icons-vue"
import {useRouter,useRoute,onBeforeRouteUpdate} from "vue-router"
import {useI18n} from "vue-i18n"
const { t } = useI18n()
const router = useRouter()
const route = useRoute()
let indexFlag=$ref(1)
function changeRouter(index){
  indexFlag=index
}
</script>
<template>
  <div id="main-div">
    <div id="div-title">
      <el-breadcrumb :separator-icon="ArrowRight">
        <el-breadcrumb-item @click="changeRouter(1)" :class="indexFlag===1?'indexTag':''" :to="{ path: '/main/bom/orderBOM' }">订单BOM</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(2)" :class="indexFlag===2?'indexTag':''" :to="{ path: '/main/bom/productBOM' }">产品BOM</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(3)" :class="indexFlag===3?'indexTag':''" :to="{ path: '/main/bom/materialBOM' }">物料BOM</el-breadcrumb-item>
        <el-breadcrumb-item v-show="false" :to="{ path: '/main/order/orderReport' }"></el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <div id="main-body">
      <router-view :key="route.fullPath" />
    </div>
  </div>
</template>
<style scoped>
#main-div{
  width: 99%;
  height: 100%;
}
#div-title{
  height: 2%;
  width: 100%;
}
#searchButton{
  margin-top: -5px;
  margin-left: 1rem;
}
#searchButton1{
//margin-left: 10rem;
}
/*main-body样式*/
#main-body{
  width: 100%;
  height: 95%;
  margin-top: 1%;
}
#select{
  margin-left:0.5rem;
}
:deep(.indexTag .el-breadcrumb__inner){
  color: #5CADFE !important;
}
</style>
north-glass-erp/northglass-erp/src/views/sd/bom/MaterialBOM.vue
New file
@@ -0,0 +1,456 @@
<script setup>
import request from "@/utils/request"
import deepClone from "@/utils/deepClone"
import {ElMessage} from "element-plus"
import {computed, onMounted, reactive, ref} from "vue"
import {useRoute, useRouter} from "vue-router"
import {changeFilterEvent,filterChanged} from "@/hook"
import { useI18n } from 'vue-i18n'
import useUserInfoStore from "@/stores/userInfo";
//语言获取
const { t } = useI18n()
const userStore = useUserInfoStore()
const router = useRouter()
const route = useRoute()
let produceList = ref([])
const dialogTableVisible = ref(false)
//表单验证
const ruleFormRef = ref()
const ruleForm = reactive({
  type: '',
  consume: '',
  price: '',
})
const validatePass = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('Please input the password'))
  } else {
    if (ruleForm.checkPass !== '') {
      if (!ruleFormRef.value) return
      ruleFormRef.value.validateField('checkPass')
    }
    callback()
  }
}
const rules = reactive({
  type: [{ validator: validatePass, trigger: 'blur' }],
  /*checkPass: [{ validator: validatePass2, trigger: 'blur' }],
  age: [{ validator: checkAge, trigger: 'blur' }],*/
})
const submitForm = (formEl) => {
  if (!formEl) return
  formEl.validate((valid) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!')
    }
  })
}
const resetForm = (formEl) => {
  if (!formEl) return
  formEl.resetFields()
}
const getTableRow = (row,type) =>{
  switch (type) {
    case 'edit' :{
      dialogTableVisible.value = true
      return
    }
  }
}
const value = ref('')
const options = [
  {
    value: t('ingredients.originalFilm'),
    label: t('ingredients.originalFilm')
  },
  {
    value: t('ingredients.accessories'),
    label: t('ingredients.accessories'),
  }
]
const hasDecimal=(value)=>{
  const regex=/\./ // 定义正则表达式,查找小数点
  return regex.test(value) //返回true/false
}
const hasDecimalhtml=(item,row)=>{
  let aa=item.split('.').length
  if (aa===2){
    return row[item.split('.')[0]][item.split('.')[1]]
  }else if(aa===3){
    return row[item.split('.')[0]][item.split('.')[1]][item.split('.')[2]]
  }
}
let pageNum=ref(1)
let total = reactive({
  pageTotal : 0,
  dataTotal : 0,
  pageSize : 1000
})
let filterData = ref({
  type:''
})
let BasicData = ref([])
let materialStore= ref([])
let arr = [
  {title: t('basicData.operate'), width: '110', slots: { default: 'button_slot' },fixed:'left'},
  { type: 'seq',fixed:'left', title: t('basicData.Number'), width: '80' },
  {field: 'id', width: '150',title: t('ingredients.materialCode'), sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged}
]
const bomTitle = [
  {field: 'type',title: '类型', showOverflow:'ellipsis' },
  {field: 'consume',title: '消耗量',showOverflow:'ellipsis' },
  {price: '使用价格',title: '使用价格',showOverflow:'ellipsis' }
]
//第一次加载默认
value.value=t('ingredients.originalFilm')
filterData.value.type=t('ingredients.originalFilm')
request.get(`/BasicWarehouse/BasicWarehouseType/${value.value}`).then((res) => {
  if(res.code==200){
    gridOptions.columns.splice(0,gridOptions.columns.length)
    BasicData.value = res.data
    //添加列
    gridOptions.columns=arr.slice()
    for (let i=0;i<BasicData.value.length;i++){
      let aa={field: BasicData.value[i].OperateType, width: '150',title: BasicData.value[i].OperateTypeName, sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged}
      gridOptions.columns.push(aa)
    }
    bomTitle.forEach((item) => {
      gridOptions.columns.push(item)
    })
    getWorks()
  }else{
    ElMessage.warning(res.msg)
  }
})
//列查询
const getWork = () => {
  filterData.value.type=value.value
  request.get(`/BasicWarehouse/BasicWarehouseType/${value.value}`).then((res) => {
    if(res.code==200){
      gridOptions.columns=[]
      BasicData.value = res.data
      //添加列
      gridOptions.columns=arr.slice()
      for (let i=0;i<BasicData.value.length;i++){
        let column={field: BasicData.value[i].OperateType,
          width: '150',title: BasicData.value[i].OperateTypeName,
          sortable: true,showOverflow:'ellipsis' ,
          filters:[{ data: '' }],
          slots: { filter: 'num1_filter' },
          filterMethod:filterChanged}
        gridOptions.columns.push(column)
      }
      bomTitle.forEach((item) => {
        gridOptions.columns.push(item)
      })
      getWorks()
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
//数据绑定
const getWorks = () => {
  request.post(`/materialStore/getSelectMaterialStore/1/${total.pageSize}`,filterData.value).then((res) => {
    if(res.code==200){
      materialStore.value=[]
      for (let i=0;i<res.data.data.length;i++){
        materialStore.value[i]= JSON.parse(res.data.data[i].json)
        materialStore.value[i].id= res.data.data[i].id
      }
      total.dataTotal = res.data.total.total*1
      total.pageTotal= res.data.total.pageTotal
      pageNum.value=1
      produceList = deepClone(materialStore.value)
      xGrid.value.loadData(produceList)
      gridOptions.loading=false
    }else{
      ElMessage.warning(res.msg)
      router.push("/login")
    }
  })
}
//分页查询
const getWorkPaging = () => {
  request.post(`/materialStore/getSelectMaterialStore/${pageNum.value}/${total.pageSize}`,filterData.value).then((res) => {
    if(res.code==200){
      materialStore.value=[]
      for (let i=0;i<res.data.data.length;i++){
        materialStore.value[i]= JSON.parse(res.data.data[i].json)
        materialStore.value[i].id= res.data.data[i].id
      }
      produceList = deepClone(materialStore.value)
      xGrid.value.loadData(produceList)
      gridOptions.loading=false
    }else{
      ElMessage.warning(res.msg)
      router.push("/login")
    }
  })
}
//分页查询
const selectOrderList = ()=>{
  filterData.value.type=value.value
  request.get(`/BasicWarehouse/BasicWarehouseType/${value.value}`).then((res) => {
    if(res.code==200){
      gridOptions.columns.splice(0,gridOptions.columns.length)
      BasicData.value = res.data
      //添加列
      gridOptions.columns=arr.slice()
      for (let i=0;i<BasicData.value.length;i++){
        let aa={field: BasicData.value[i].OperateType, width: '150',title: BasicData.value[i].OperateTypeName, sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged}
        gridOptions.columns.push(aa)
      }
      bomTitle.forEach((item) => {
        gridOptions.columns.push(item)
      })
      if (res.data.total!=null){
        total.dataTotal = res.data.total.total*1
        total.pageTotal= res.data.total.pageTotal
      }
      getWorkPaging()
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
//页脚跳转
const handlePageChange = ({ currentPage, pageSize }) => {
  total.pageTotal = pageSize
  pageNum.value=currentPage
  selectOrderList();
}
//子组件接收参数
const xGrid = ref()
const gridOptions = reactive({
  border:  "full",//表格加边框
  keepSource: true,//保持源数据
  align: 'center',//文字居中
  stripe:true,//斑马纹
  rowConfig: {isCurrent: true, isHover: true,height: 30},//鼠标移动或选择高亮
  id: 'SelectIngredients',
  showFooter: true,//显示脚
  printConfig: {},
  importConfig: {},
  exportConfig: {},
  scrollY:{ enabled: true },//开启虚拟滚动
  showOverflow:true,
  columnConfig: {
    resizable: true,
    useKey: true
  },
  filterConfig: {   //筛选配置项
                    //remote: true
  },
  customConfig: {
    storage: true
  },
  editConfig: {
    trigger: 'click',
    mode: 'row',
    showStatus: true
  },//表头参数
  columns:[
  ],//表头按钮
  toolbarConfig: {
    /*import: false,
    export: true,
    print: true,*/
    export: true,
    zoom: true,
    custom: true
  },
  footerMethod ({ columns, data }) {//页脚函数
    return[
      columns.map((column, columnIndex) => {
        if (columnIndex === 0) {
          return t('basicData.total')
        }
        return ''
      })
    ]
  }
})
</script>
<template>
  <div class="main-div-customer">
    <div class="head">
      <el-row>
        <el-col :span="4">
          <el-select v-model="value" :placeholder="$t('ingredients.pleaseSelectACategory')" @change="getWork">
            <el-option
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
        </el-col>
      </el-row>
    </div>
    <div class="main-table">
      <vxe-grid
          max-height="100%"
          class="mytable-scrollbar"
          ref="xGrid"
          v-bind="gridOptions"
      >
        <template #num1_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
              <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
            </div>
          </div>
        </template>
        <!--左边固定显示的插槽-->
        <template #button_slot="{ row }">
          <el-button @click="getTableRow(row,'edit')"
                     link type="primary" size="small">{{ $t('basicData.edit') }}</el-button>
        </template>
        <template #pager>
          <!--使用 pager 插槽-->
          <vxe-pager
              @page-change="handlePageChange"
              :layouts="[  'PrevPage', 'Jump','PageCount', 'NextPage',  'Total']"
              v-model:current-page="pageNum"
              v-model:page-size="total.pageSize"
              v-model:pager-count="total.pageTotal"
              :total="total.dataTotal"
          >
          </vxe-pager>
        </template>
      </vxe-grid>
    </div>
  </div>
  <el-dialog
      :key="dialogKey"
      id="print"
      v-model="dialogTableVisible"
      destroy-on-close
      style="width: 40%;height:40%;"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
  >
    <el-form
        ref="ruleFormRef"
        style="max-width: 600px"
        :model="ruleForm"
        status-icon
        :rules="rules"
        label-width="auto"
        class="demo-ruleForm"
    >
      <el-form-item label="使用类型" prop="type">
        <el-select v-model="ruleForm.type" autocomplete="off">
          <el-option label="面积" :value="1" />
          <el-option label="周长" :value="2" />
          <el-option label="数量" :value="3" />
        </el-select>
      </el-form-item>
      <el-form-item label="消耗量" prop="consume">
        <el-input v-model="ruleForm.consume" autocomplete="off" />
      </el-form-item>
      <el-form-item label="价格" prop="price">
        <el-input v-model="ruleForm.price" autocomplete="off" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)">
          提交
        </el-button>
        <el-button @click="resetForm(ruleFormRef)">重置</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>
</template>
<style scoped>
.main-div-customer{
  width: 99%;
  height: 100%;
}
.head{
  width: 100%;
  height: 35px;
}
.main-table{
  width: 100%;
  height: calc(100% - 35px);
}
</style>
north-glass-erp/northglass-erp/src/views/sd/bom/OrderBOM.vue
New file
@@ -0,0 +1,698 @@
<script setup>
import {Check, Search} from "@element-plus/icons-vue"
import {useRouter} from "vue-router"
import {computed, onMounted, reactive, ref} from "vue"
import request from "@/utils/request"
import deepClone from "@/utils/deepClone"
import {ElMessage, ElMessageBox} from "element-plus"
import { VXETable} from "vxe-table"
import  useUserInfoStore from '@/stores/userInfo'
import companyInfo from "@/stores/sd/companyInfo"
import footSum from "@/hook/footSum"
import OrderDetail from "@/components/sd/order/OrderDetail.vue"
import OrderCraftDetail from "@/components/sd/order/OrderCraftDetail.vue"
import OrderProcess from "@/components/sd/order/OrderProcess.vue"
import PrintSheet1 from "@/components/sd/order/PrintSheet1.vue"
import PrintSheet2 from "@/components/sd/order/PrintSheet2.vue"
import {useI18n} from "vue-i18n"
import useOrderInfoStore from "@/stores/sd/order/orderInfo"
import {CircleCheck, Download, Printer} from "@element-plus/icons-vue/global"
import { saveAs } from "file-saver"
import PrintSheet3 from "@/components/sd/order/PrintSheet3.vue"
import PrintSheet4 from "@/components/sd/order/PrintSheet4.vue"
import PrintSheet5 from "@/components/sd/order/PrintSheet5.vue"
const { t } = useI18n()
const orderInfo = useOrderInfoStore()
const userStore = useUserInfoStore()
const company = companyInfo()
const tabsValue=ref('1')
const router = useRouter()
let rowClickIndex = ref(null)
let reviewDisabled = ref(true)
const dialogTableVisible = ref(false)
let dialogKey = ref(0)
let sheetIndex = ref(-1)
let orderType = ref("2")
let filterData = ref({})
let sortData = ref({
  field:'id',
  order:null
})
let orderList = ref([])
let pageNum=ref(1)
let total = ref({
  pageTotal : 0,
  dataTotal : 0,
  pageSize : 50
})
const xGrid = ref()
const gridOptions = reactive({
  border:  "full",//表格加边框
  keepSource: true,//保持源数据
  align: 'center',//文字居中
  stripe:true,//斑马纹
  rowConfig: {isCurrent: true, isHover: true,height: 30},//鼠标移动或选择高亮
  id: 'OrderList',
  showFooter: true,//显示脚
  printConfig: {},
  importConfig: {},
  exportConfig: {},
  scrollY:{ enabled: true },//开启虚拟滚动
  showOverflow:true,
  columnConfig: {
    resizable: true,
    useKey: true
  },
  filterConfig: {   //筛选配置项
    remote: true
  },
  sortConfig: {   //排序配置项
    remote: true//是否服务端排序
  },
  customConfig: {
    storage: true
  },
  editConfig: {
    trigger: 'click',
    mode: 'row',
    showStatus: true
  },
 /* menuConfig: {
    body: {
      options: [
        [
          { code: 'copy', name: t('searchOrder.copy'), prefixIcon: 'vxe-icon-copy', visible: true},
          { code: 'copyTitle', name: t('searchOrder.copyTitle'), prefixIcon: 'vxe-icon-copy', visible: true},
          {
            prefixIcon: 'vxe-icon-print',
            name: t('order.processingOrder'),
            children: [
              // { code: 'sheet1', name: '横版-普通' },
              { code: 'sheet2', name: t('order.sheet2') },
              { code: 'sheet4', name: t('order.sheet4') },
              { code: 'sheet3', name: t('order.sheet3') },
              { code: 'sheet5', name: t('order.sheet5')},
            ]
          },
          {
            prefixIcon: 'vxe-icon-repeat',
            name: t('order.oneClickReturn'),
            children: [
              // { code: 'sheet1', name: '横版-普通' },
              { code: 'back1', name: t('searchOrder.createOrder'),disabled:true },
              { code: 'back2', name: t('order.technology'),disabled:true  },
              { code: 'back3', name: t('basicData.review'),disabled:true  },
              { code: 'back4', name: t('searchOrder.production'),disabled:true },
            ]
          },
          { code: 'oneClickStorage', name: t('order.oneClickStorage'), prefixIcon: 'vxe-icon-copy', visible: true},
          // { code: 'getProcessList', name: t('searchOrder.processFlows'), prefixIcon: 'vxe-icon-file-txt', visible: true}
        ]
      ]
    }
  },*/
  //表头参数
  columns:[
    {title: t('basicData.operate'), width: 110, slots: { default: 'button_slot' },fixed:"left",},
    {type: 'seq', title: t('basicData.Number'), width: 80 ,fixed:"left",},
    {field:'createOrder',title: t('searchOrder.createOrder'), width: 40, slots: { default: 'state' }},
    {field:'processReview',title: t('order.technology'), width: 40, filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field:'orderReview',title: t('basicData.review'), width: 40, filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field:'productionOrder',title: t('searchOrder.production'), width: 40, filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field:'processingCard',title: t('searchOrder.process'), width: 40, filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field:'warehousing',title: t('searchOrder.storage'), width: 40, filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field:'delivery',title: t('searchOrder.delivery'), width: 40,filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {field: 'orderId',width:120,  title: t('order.orderId'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'customerId',width:120,  title: t('customer.customerNumber'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'customerName',width:120,  title: t('customer.customerName'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'project',width:120,  title: t('order.project'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'batch',width:120,  title: t('order.batch'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'quantity',width:120,  title: t('order.quantity'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'goodsQuantity',width:120,  title: t('searchOrder.inventoryNum'), sortable: true},
    {field: 'area',width:120,  title: t('order.computeGrossArea'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'money',width:120,  title: t('order.money'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'createTime',width:120,filters:[{ data: '' }],slots: { filter: 'num1_filter' },   title: t('basicData.reportData'), sortable: true},
    {field: 'updateTime',width:120,   title: t('productStock.approvedDate'), sortable: true},
    {field: 'packType',width:120,  title: t('order.packType'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'orderType',width:120,  title: t('order.orderType'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'salesman',width:120,  title: t('order.salesman'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'creator',width:120,  title: t('product.creator'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'verifier',width:120,  title: t('basicData.review'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'perimeter',width:120,  title: t('searchOrder.perimeter'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'deliveryDate',width:120,  title: t('order.deliveryDate'), sortable: true},
    {field: 'customerBatch',width:120,  title: t('order.customerBatch'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    //{field: '14',width:120,  title: '备注',filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'deliveryAddress',width:120,  title: t('order.deliveryAddress'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'processingNote',width:120,  title: t('order.processingNote'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true}
  ],
  mouseConfig:{selected: true},//鼠标选中
  keyboardConfig:{
    isArrow: true
  },
  //表头按钮
  toolbarConfig: {
    buttons: [
    ],
    slots:{
      buttons: "toolbar_buttons"
    },
    // import: false,
    // export: true,
    // print: true,
    zoom: true,
    custom: true
  },
  footerMethod ({ columns, data }) {//页脚函数
    return[
      columns.map((column, columnIndex) => {
        if (columnIndex === 0) {
          return t('basicData.total')
        }
        const List = ["quantity",'goodsQuantity','area','perimeter','money']
        if (List.includes(column.field)) {
          //return footSum(data, column.field)
          return total.value[column.field]
        }
        return ''
      })
    ]
  }
})
const gridEvents = {
  toolbarButtonClick ({ code }) {
    const $grid = xGrid.value
    if ($grid) {
      switch (code) {
        case 'checkList': {
          if($grid.getCheckboxRecords().length===0){
            VXETable.modal.message( t('searchOrder.msg'))
            return
          }
          break
        }
      }
    }
  },
  menuClick ({ menu, row, column }) {
    const $grid = xGrid.value
    if ($grid) {
      switch (menu.code) {
        case 'sheet1': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          dialogTableVisible.value = true
          sheetIndex.value=1
          if(rowClickIndex.value.processReview===2 && rowClickIndex.value.orderReview===0){
            reviewDisabled.value=false
          }
          break
        }
        case 'sheet2': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          dialogTableVisible.value = true
          sheetIndex.value=2
          if(rowClickIndex.value.processReview===2 && rowClickIndex.value.orderReview===0){
            reviewDisabled.value=false
          }
          break
        }
        case 'sheet3': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          dialogTableVisible.value = true
          sheetIndex.value=3
          if(rowClickIndex.value.processReview===2 && rowClickIndex.value.orderReview===0){
            reviewDisabled.value=false
          }
          break
        }
        case 'sheet4': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          ElMessage.warning(t('order.printingNumber')+rowClickIndex.value.printingNumber)
          dialogTableVisible.value = true
          sheetIndex.value=4
          if(rowClickIndex.value.processReview===2 && rowClickIndex.value.orderReview===0){
            reviewDisabled.value=false
          }
          break
        }
        case 'sheet5': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          ElMessage.warning(t('order.printingNumber')+rowClickIndex.value.printingNumber)
          dialogTableVisible.value = true
          sheetIndex.value=5
          if(rowClickIndex.value.processReview===2 && rowClickIndex.value.orderReview===0){
            reviewDisabled.value=false
          }
          break
        }
        case 'back1': {
          backProcess(1)
          break
        }
        case 'back2': {
          backProcess(2)
          break
        }
        case 'back3': {
          backProcess(3)
          break
        }
        case 'back4': {
          backProcess(4)
          break
        }
        case 'copy': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          router.push({path:'/main/order/createOrder',
            state:{
              orderId:rowClickIndex.value.orderId,
              type:'copy'
            }})
          break
        }
        case 'copyTitle': {
          if(rowClickIndex.value===null){
            ElMessage.warning(t('searchOrder.msgList.checkOrder'))
            return
          }
          router.push({path:'/main/order/createOrder',
            state:{
              orderId:rowClickIndex.value.orderId,
              type:'copyTitle'
            }})
          break
        }
        case 'print':{
          break
        }
        case 'oneClickStorage': {
          if(rowClickIndex.value.processReview===0||rowClickIndex.value.orderReview===0){
            ElMessage.warning(t('order.orderNotApproved'))
            return
          }
          if(rowClickIndex.value.warehousing==2){
            ElMessage.warning(t('order.orderHasBeenReceived'))
            return
          }
          request.post(`/finishedGoodsInventory/oneClickStorage/${rowClickIndex.value.orderId}/${userStore.user.userName}`).then((res) => {
            if(res.code==200 && res.data===true){
              ElMessage.success(t('productStock.receivedSuccessfully'))
              router.push({path:'/main/order/selectOrder',query:{random:Math.random()}})
            }else{
              ElMessage.warning(res.msg)
            }
          })
          break
        }
      }
    }
  },
  cellClick({ row }){
    rowClickIndex.value = row
    xGrid.value.menuConfig.body.options[0][3].children.forEach((item)=>{
      item.disabled=true
    })
    //判断是否入库
    if(row.warehousing>0){
      return
    }
    if(row.processReview===2){
      xGrid.value.menuConfig.body.options[0][3].children[0].disabled=false
    }
    if(row.orderReview===2){
      xGrid.value.menuConfig.body.options[0][3].children[1].disabled=false
    }
    if(row.productionOrder>0){
      xGrid.value.menuConfig.body.options[0][3].children[2].disabled=false
    }
    if(row.processingCard>0){
      xGrid.value.menuConfig.body.options[0][3].children[3].disabled=false
    }
  },
  sortChange ({ field, order }) {
    sortData.value = {field,order}
    selectOrderList()
  }
}
const getOrderList = async () => {
  //加载请求
  const config = {
    filter: filterData.value,
    sort: sortData.value
  }
  await request.post(`/order/getOrderList/1/${total.value.pageSize}/${orderType.value}/${orderInfo.selectDate}`,config).then((res) => {
    if(res.code==200){
      total.value = res.data.total
      /*total.dataTotal = res.data.total.dataTotal*1
      total.pageTotal= res.data.total.pageTotal*/
      orderInfo.selectDate = res.data.selectDate
      orderList.value = deepClone(res.data.data)
      xGrid.value.loadData(orderList.value)
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
onMounted(async () => {
  filterData.value = orderInfo.searchOrderFilter.data
  await getOrderList()
  orderInfo.searchOrderFilter.list.forEach(item =>{
    xGrid.value.getColumnByField(item.field).filters = item.column.filters
  })
})
const changeFilterEvent = (event, option, $panel) => {
  // 手动触发筛选
  $panel.changeOption(event, !!option.data, option)
}
function filterChanged(column){
  gridOptions.loading=true
  //筛选条件发生变化条件发生变化
  let value = column.datas[0]!=undefined?column.datas[0]:''
  value = value.trim()
  //判断是否存在外键
  if (column.property.indexOf('.')>-1){
    const  columnArr = column.property.split('.')
    filterData.value[columnArr[0]] = {
      [columnArr[1]]:value
    }
  }else{
    filterData.value[column.property] = value
  }
  const config = {
    filter: filterData.value,
    sort: sortData.value
  }
  request.post(`/order/getOrderList/${pageNum.value}/${total.value.pageSize}/${orderType.value}/${orderInfo.selectDate}`,config).then((res) => {
    if(res.code==200){
      total.value = res.data.total
      /*total.dataTotal = res.data.total.total*1
      total.pageTotal=parseInt(res.data.total)*/
      pageNum.value=1
      orderList.value = deepClone(res.data.data)
      xGrid.value.loadData(orderList.value)
      gridOptions.loading=false
      orderInfo.searchOrderFilter.list = xGrid.value.getCheckedFilters()
      orderInfo.searchOrderFilter.data = filterData.value
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
//双击表格行
const selectOrderList = ()=>{
  const config = {
    filter: filterData.value,
    sort: sortData.value
  }
  request.post(`/order/getOrderList/${pageNum.value}/${total.value.pageSize}/${orderType.value}/${orderInfo.selectDate}`
      ,config).then((res) => {
    if(res.code==200){
      total.value = res.data.total
      /*total.dataTotal = res.data.total.total*1
      total.pageTotal = res.data.total.pageTotal*/
      orderInfo.selectDate=res.data.selectDate
      orderList.value = deepClone(res.data.data)
      xGrid.value.loadData(orderList.value)
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
const changeOrderType = ()=>{
  pageNum.value=1
  selectOrderList()
}
const changeDate =  ()=>{
  pageNum.value=1
  selectOrderList()
}
//页脚跳转
const handlePageChange = ({ currentPage, pageSize }) => {
  pageNum.value=currentPage
  total.pageTotal    = pageSize
  selectOrderList()
}
//页面跳转更新或者删除订单
const getTableRow =  (row,type) => {
  switch (type) {
    case 'edit': {
      dialogTableVisible.value = true
      break
    }
  }
}
const showCheckbox = computed(()=>(item)=>{ //计算属性传递参数
  return 2 === item
})
const printContent = ref({
  id: 'child',
})
const printingNumber = ()=>{
  if(sheetIndex.value===4){
    request.post(`/order/updateOrderPrintNumber/${rowClickIndex.value.orderId}`).then(res =>{
    })
  }
}
const closeDialog = ()=>{
  /*selectOrderList()
  console.log(xGrid.value.getTableData())*/
}
const handleKeyDown = (evnt) =>{
  if(evnt.$event.keyCode === 38 ){
    let nextRowIndex = xGrid.value.getRowIndex(xGrid.value.getCurrentRecord()) - 1;
    if (nextRowIndex < xGrid.value.getTableData().fullData.length && nextRowIndex>=0) {
      xGrid.value.setCurrentRow(xGrid.value.getTableData().fullData[nextRowIndex]);
      rowClickIndex.value = xGrid.value.getCurrentRecord()
    }
  }
  if(evnt.$event.keyCode === 40 ){
    let nextRowIndex = xGrid.value.getRowIndex(xGrid.value.getCurrentRecord()) + 1;
    if (nextRowIndex < xGrid.value.getTableData().fullData.length) {
      xGrid.value.setCurrentRow(xGrid.value.getTableData().fullData[nextRowIndex]);
      rowClickIndex.value = xGrid.value.getCurrentRecord()
    }
  }
}
//订单距离小于三天则改变checkbox class 改变颜色
const timeOutChangeColor =(row)=>{
  if(company.timeOut){
    return row.timeOut
  }
}
</script>
<template>
  <div  style="width: 100%;height: 100% ;">
    <div style="width: 100%;height: 95%">
      <el-date-picker
          v-model="orderInfo.selectDate"
          type="daterange"
          :start-placeholder="$t('basicData.startDate')"
          :end-placeholder="$t('basicData.startDate')"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
      />
      <el-button @click="changeDate"
                 style="margin-top: -5px"
                 id="searchButton"
                 type="primary"
                 :icon="Search">
        {{ $t('basicData.search') }}
      </el-button>
      <vxe-grid
          @filter-change="filterChanged"
          height="110%"
          size="mini"
          class="mytable-scrollbar"
          ref="xGrid"
          v-bind="gridOptions"
          v-on="gridEvents"
          @keydown="handleKeyDown"
      >
        <template #state="{ row,column}">
          <el-checkbox
              :class="timeOutChangeColor(row)"
              v-if="row[column.field] === 2"
              @click.native.prevent
              :indeterminate="row[column.field]===1"
              :checked="true"/>
          <el-checkbox
              v-else
              :class="timeOutChangeColor(row)"
              @click.native.prevent
              :indeterminate="row[column.field]===1"
              :checked="false"/>
        </template>
        <!--左边固定显示的插槽-->
        <template #button_slot="{ row }">
          <el-button @click="getTableRow(row,'edit')"
                     link
                     type="primary"
                     size="small">
            生成BOM
          </el-button>
        </template>
        <template #num1_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
              <input
                  v-model="option.data"
                  @keyup.enter.native="$panel.confirmFilter()"
                  @input="changeFilterEvent($event, option, $panel)"/>
            </div>
          </div>
        </template>
        <template #num2_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
              <vxe-select
                  v-model="option.data"
                  @change="changeFilterEvent($event, option, $panel)"
                  :placeholder="$t('processCard.pleaseSelect')">
                <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
                <vxe-option value="1" :label="$t('basicData.partiallySelected')"></vxe-option>
                <vxe-option value="2" :label="$t('basicData.selected')"></vxe-option>
              </vxe-select>
            </div>
          </div>
        </template>
        <template #toolbar_buttons>
          <vxe-select @change="changeOrderType" v-model="orderType" :placeholder="$t('searchOrder.orderType')">
            <vxe-option value="2" :label="$t('searchOrder.regularOrders')"></vxe-option>
            <vxe-option value="-2" :label="$t('searchOrder.cancelledOrders')"></vxe-option>
            <vxe-option value="0" :label="$t('searchOrder.allOrders')"></vxe-option>
          </vxe-select>
        </template>
        <template #pager>
          <!--使用 pager 插槽-->
          <!--        'PrevJump','NextJump', -->
          <vxe-pager
              @page-change="handlePageChange"
              :layouts="[  'PrevPage', 'Jump','PageCount', 'NextPage',  'Total']"
              v-model:current-page="pageNum"
              v-model:page-size="total.pageSize"
              v-model:pager-count="total.pageTotal"
              :total="total.dataTotal"
          >
          </vxe-pager>
        </template>
      </vxe-grid>
    </div>
    <el-dialog
        :key="dialogKey"
        id="print"
        v-model="dialogTableVisible"
        destroy-on-close
        style="width: 90%;height:90%;margin-top: 3vh "
        :close-on-click-modal="false"
        :close-on-press-escape="false"
    >
    </el-dialog>
  </div>
</template>
<style scoped>
:deep(.el-tabs__content) {
  width: 100%;
  height: 86%;
}
.el-tab-pane{
  width: 100%;
  height: 100%;
}
:deep(#print .el-dialog__body){
  height: 85%;
  width: 100%;
  overflow-y: auto;
}
#child{
  width:100%;
  height: 100%;
}
:deep(.timeOut.is-checked .el-checkbox__inner) {
  background-color: orangered;
  border-color: orangered;
}
</style>
north-glass-erp/northglass-erp/src/views/sd/bom/ProductBOM.vue
New file
@@ -0,0 +1,398 @@
<script lang="ts" setup>
import request from "@/utils/request"
import deepClone from "@/utils/deepClone"
import {ElMessage} from "element-plus"
import useProductGlassTypeStore from "@/stores/sd/product/productGlassType"
import {nextTick, onUnmounted, reactive, ref, watch} from "vue"
import GlassType from "@/components/sd/product/GlassType.vue"
import {useRouter} from 'vue-router'
import {columnDrop2, sortable2} from "@/hook/columnMove"
import {useI18n} from "vue-i18n";
import ProductBomAdd from "@/views/sd/bom/ProductBomAdd.vue";
const { t } = useI18n()
let productGlassTypeStore = useProductGlassTypeStore()
let router=useRouter()
const dialogTableVisible = ref(false)
//监听玻璃类型改变
let productList = ref([])
let date=ref(['',''])
productGlassTypeStore.GlassType=['','']
let props = defineProps({
  rowIndex:{}
})
let glassType = ref([])
const getProduct = () => {
  request.post(`/product/1/100/${productGlassTypeStore.GlassType}`,filterData.value).then((res) => {
    if(res.code==200){
      pageTotal.value=res.data.total
      xGrid.value.loadData(res.data.data)
      gridOptions.loading=false
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
//定义滚动条高度
let scrollTop =ref(null)
let scrollHeight =ref(null)
let clientHeight =ref(null)
const  scrollEvnt = (row) => {
  // 内容高度
  scrollTop.value = row.$event.target.scrollTop
  scrollHeight.value = row.$event.target.scrollHeight
  clientHeight.value = row.$event.target.clientHeight
}
//筛选条件,有外键需要先定义明细里面的数据
let filterData = ref({
  basicGlassType:{
    typeName:''
  }
})
//定义页面总页数
let pageTotal=ref('')
//定义数据返回结果
let produceList = ref([])
//定义当前页数
let pageNum=$ref(1)
let pageState = null
//监听产品滚动条状态,滚动到底部向后端请求数据
watch(scrollTop,(newVal,oldVal) => {
  //判断当前状态查询状态
  if(pageState!==null){
    return;
  }
  //判断滚动条上下滚动不是左右滚动,当左右滚动直接返回
  if((newVal === oldVal && newVal===0) || oldVal===null){
    return;
  }
  //判断是否滚到底部
  if ((Math.round(scrollTop.value + clientHeight.value)+5 >= scrollHeight.value ) ) {
    if(newVal>oldVal){
      //判断当前容器长度是否为500,并且当前页小于容器总数量
      if(produceList.length===500 && pageNum<(produceList.length/100)){
        pageNum=pageNum+5
      }else{
        //判断是否是最大页面
        if (pageNum>=pageTotal.value){
          //ElMessage.warning("没有更多数据了")
          return
        }
        pageNum=pageNum+1
      }
      pageState=true
    }
  }else if(newVal===0 && oldVal>0 && pageNum>1  ){  //判断是否滚到顶部并且大于容器数量
    //判断向上滚动当前页数是否大于容器数值
    if(pageNum>5){
      pageNum=pageNum-5
    }else if((produceList.length/100)>=5) {
      pageNum=pageNum-1
    }else{
      return
    }
    pageState =false
  }
  if(pageState!==null){
    gridOptions.loading=true
    request.post(`/product/${pageNum}/100/${productGlassTypeStore.GlassType}`,filterData.value).then((res) => {
      try{
        if(res.code==200){
          if(pageState){
            produceList = produceList.concat(res.data.data)
            if(produceList.length>500){
              produceList=produceList.slice(100,600)
            }
          }else{
            produceList = res.data.data.concat(produceList)
            if(produceList.length>500){
              produceList=produceList.slice(0,500)
            }
          }
          xGrid.value.reloadData(produceList)
          pageState=null
        }else{
          ElMessage.warning(res.msg)
        }
      }finally {
        gridOptions.loading=false
      }
    })
  }
})
//第一次加载数据
request.post(`/product/1/100/${productGlassTypeStore.GlassType}`,filterData.value).then((res) => {
  if(res.code==200){
    pageTotal.value=res.data.total
    console.log(res.data.data)
    produceList = produceList.value.concat(deepClone(res.data.data))
    xGrid.value.reloadData(produceList)
    gridOptions.loading=false
  }else{
    ElMessage.warning(res.msg)
  }
})
//删除与编辑方法
const getTableRow =  (row,type) => {
  switch (type) {
    case 'edit': {
      dialogTableVisible.value = true
      break
    }
  }
}
const xGrid = ref()
const gridOptions = reactive({
  height:'100%',
  loading: true,
  border:  "full",//表格加边框
  keepSource: true,//保持源数据
  align: 'center',//文字居中
  stripe:true,//斑马纹
  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//鼠标移动或选择高亮
  id: 'SelectProduct',
  showFooter: true,//显示脚
  printConfig: {},
  importConfig: {},
  exportConfig: {},
  scrollX:{enabled: true},
  scrollY:{ enabled: true ,gt:0},//开启虚拟滚动
  showOverflow:true,
  columnConfig: {
    resizable: true,
    useKey: true
  },
  filterConfig: {   //筛选配置项
    remote: true
  },
  customConfig: {
    storage: true
  },
  editConfig: {
    trigger: 'click',
    mode: 'row',
    showStatus: true
  },
  columns:[
    {title: t('basicData.operate'), width: 120, slots: { default: 'button_slot' },fixed:"left"},
    {field:'state',title: t('basicData.review'), width: 40,filters:[{ data: '' }], slots: { default: 'state',filter: 'num2_filter' }},
    {type: 'seq',fixed:"left", title: t('basicData.Number'), width: 80 },
    {field: 'id', title: t('basicData.number'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: true},
    {field: 'productName', title: t('product.productName'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'productAbbreviation', title:t('product.msg.productAbbreviation'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'basicGlassType.typeName', title: t('product.typeName'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'query', title: t('product.query'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'remarks', title: t('basicData.remarks'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'creator', title: t('product.creator'),filters:[{ data: '' }],slots: { filter: 'num1_filter' }, sortable: false},
    {field: 'createTime', title: t('basicData.creationTime')}
  ],//表头参数
  data:null,//表格数据
  toolbarConfig: {
    buttons: [],
    slots:{
      buttons: "toolbar_buttons"
    },
    // import: false,
    // export: true,
    // print: true,
    zoom: true,
    custom: true
  },
  footerMethod ({ columns, data }) {//页脚函数
    return[
      columns.map((column, columnIndex) => {
        if (columnIndex === 0) {
          return t('basicData.total')
        }
        return ''
      })
    ]
  }
})
/*使用筛选,后端获取数据*/
const changeFilterEvent = (event, option, $panel,) => {
  // 手动触发筛选
  $panel.changeOption(event, !!option.data, option)
}
function filterChanged(column){
  gridOptions.loading=true
  //筛选条件发生变化条件发生变化
  let value = column.datas[0]!=undefined?column.datas[0]:''
  value = value.trim()
  //判断是否存在外键
  if (column.property.indexOf('.')>-1){
    const  columnArr = column.property.split('.')
    filterData.value[columnArr[0]] = {
      [columnArr[1]]:value
    }
  }else{
    filterData.value[column.property] = value
  }
  request.post("/product/1/100/"+productGlassTypeStore.GlassType,filterData.value).then((res) => {
    if(res.code==200){
      pageTotal.value=res.data.total
      pageNum=1
      produceList = deepClone(res.data.data)
      xGrid.value.loadData(produceList)
      gridOptions.loading=false
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
let emit = defineEmits([
  'changePage'
])
const emitParent = (row,type) => {
  emit('getProductRow', row,type)
}
/*后端返回结果多层嵌套展示*/
const hasDecimal = (value) => {
  const regex = /\./; // 定义正则表达式,查找小数点
  return regex.test(value); // 返回true/false
}
let initTime = null
nextTick(() => {
  // 加载完成之后在绑定拖动事件
  initTime = setTimeout(() => {
    columnDrop2(xGrid.value)
  }, 500)
})
onUnmounted(() => {
  clearTimeout(initTime)
  if (sortable2) {
    try{
      sortable2.destroy()
    }
    catch (e){
    }
  }
})
</script>
<template>
  <div style="width: 100%;height: 100%">
    <!--      <glass-type   style="float: left" />
          <el-button
              @click="getProduct"
              id="select"
              type="primary" :icon="Search">{{ $t('basicData.search') }}</el-button>-->
    <vxe-grid
        @filter-change="filterChanged"
        height="100%"
        class="mytable-scrollbar"
        ref="xGrid"
        v-bind="gridOptions"
        @scroll ="scrollEvnt"
    >
      <!--左边固定显示的插槽-->
      <template #button_slot="{ row }" >
        <el-button @click="getTableRow(row,'edit')" link type="primary" size="small">{{ $t('basicData.edit') }}</el-button>
      </template>
      <template #num2_filter="{ column, $panel }">
        <div>
          <div v-for="(option, index) in column.filters" :key="index">
            <vxe-select v-model="option.data" :placeholder="$t('processCard.pleaseSelect')"  @change="changeFilterEvent($event, option, $panel)">
              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
            </vxe-select>
          </div>
        </div>
      </template>
      <template #num1_filter="{ column, $panel }">
        <div>
          <div v-for="(option, index) in column.filters" :key="index">
            <input
                type="type"
                v-model="option.data"
                @keyup.enter.native="$panel.confirmFilter()"
                @input="changeFilterEvent($event, option, $panel)"/>
          </div>
        </div>
      </template>
      <template #state="{ row,column}">
        <el-checkbox @click.native.prevent   :checked="row[column.field]===1"/>
      </template>
      <template #toolbar_buttons>
        <glass-type  @getProduct="getProduct"  />
      </template>
    </vxe-grid>
  </div>
  <el-dialog
      id="print1"
      v-model="dialogTableVisible"
      destroy-on-close
      style="width: 90%;height:90%;margin-top: 3vh "
      :close-on-click-modal="false"
      :close-on-press-escape="false"
  >
    <product-bom-add/>
  </el-dialog>
</template>
<style scoped>
/*滚动条整体部分*/
.mytable-scrollbar ::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
:deep(#print1 .el-dialog__body){
  height: 85%;
  width: 100%;
  overflow-y: auto;
  background-color: black;
}
</style>
north-glass-erp/northglass-erp/src/views/sd/bom/ProductBomAdd.vue
New file
@@ -0,0 +1,62 @@
<script setup>
import {reactive, ref} from "vue";
import {useI18n} from "vue-i18n";
const { t } = useI18n()
const xGrid = ref()
const gridOptions = reactive({
  border:  "full",//表格加边框
  keepSource: true,//保持源数据
  align: 'center',//文字居中
  stripe:true,//斑马纹
  rowConfig: {isCurrent: true, isHover: true,height: 30, useKey: true},//鼠标移动或选择高亮
  id: 'SelectProduct111',
  showFooter: true,//显示脚
  printConfig: {},
  importConfig: {},
  exportConfig: {},
  scrollX:{enabled: true},
  scrollY:{ enabled: true ,gt:0},//开启虚拟滚动
  showOverflow:true,
  columnConfig: {
    resizable: true,
    useKey: true
  },
  customConfig: {
    storage: true
  },
  editConfig: {
    trigger: 'click',
    mode: 'row',
    showStatus: true
  },
  columns:[
    {title: t('basicData.operate'), width: 120, fixed:"left"},
    {field:'state',title: '类型' },
    {field:'state',title: '物料编号', },
    {field: 'id', title: '物料名称'},
    {field:'state',title: '消耗量' },
    {field:'state',title: '价格' }
  ],//表头参数
  data:[],//表格数据
})
</script>
<template>
  <el-card style="max-width: 480px">
    <p v-for="o in 4" :key="o" class="text item">{{ '单片' + o }}</p>
  </el-card>
  <vxe-grid
      class="mytable-scrollbar"
      ref="xGrid"
      v-bind="gridOptions"
  ></vxe-grid>
</template>
<style scoped>
</style>