chenlu
2025-09-02 d01242fe06480896c2bdd9511cbaf19323786d46
Merge branch 'master' of http://10.153.19.25:10105/r/ERP_override
3个文件已添加
6个文件已修改
995 ■■■■■ 已修改文件
north-glass-erp/northglass-erp/src/router/index.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/CreateFinishedGlassShelf.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/FinishedGlassShelf.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/FinishedGlassShelfInformation.vue 530 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/views/sd/basicData/CreateBasicData.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
north-glass-erp/northglass-erp/src/router/index.js
@@ -1285,6 +1285,32 @@
            }
          ]
        },
        {
          path: 'finishedGlassShelf',
          name: 'finishedGlassShelf',
          component: () => import('../views/mm/finishedGlassShelf/FinishedGlassShelf.vue'),
          children:[
            {
              // 料架库存
              path: 'finishedGlassShelfInformation',
              name: 'finishedGlassShelfInformation',
              component: () => import('../views/mm/finishedGlassShelf/FinishedGlassShelfInformation.vue'),
            },
            {
              // 料架库存
              path: 'createFinishedGlassShelf',
              name: 'createFinishedGlassShelf',
              component: () => import('../views/mm/finishedGlassShelf/CreateFinishedGlassShelf.vue'),
            },
            {
              path: '',
              redirect:'/main/finishedGlassShelf/finishedGlassShelfInformation'
            }
          ]
        },
        /*{
          //第三方玻璃优化
          path: 'glassOptimizeThirdParty',
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/CreateFinishedGlassShelf.vue
New file
@@ -0,0 +1,181 @@
<script lang="ts" setup>
import request from "@/utils/request"
import deepClone from "@/utils/deepClone"
import {ElMessage} from "element-plus"
import {computed, onMounted, ref} from "vue"
import {useRoute, useRouter} from "vue-router"
import  useUserInfo from "@/stores/userInfo"
import GlassType from "@/components/sd/product/GlassType.vue"
import useProductGlassTypeStore from "@/stores/sd/product/productGlassType"
import {useI18n} from "vue-i18n";
import useUserInfoStore from "@/stores/userInfo";
const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const value = ref('')
const userStore = useUserInfoStore()
let BasicData = ref([])
let ruleForm = ref({
  id:0,
  glassShelfNumber: null,
  glassShelfName: null,
  availableQuantity: null,
  totalQuantity: null,
  price: null,
  money: null,
  unit: null,
  maxWeight: null,
  maxWidth: null,
  maxHeight: null,
  remarks: null,
})
const resetForm = () => {
  ruleForm.value.glassShelfNumber=null
  ruleForm.value.glassShelfName=null
  ruleForm.value.availableQuantity=null
  ruleForm.value.totalQuantity=null
  ruleForm.value.price=null
  ruleForm.value.money=null
  ruleForm.value.unit=null
  ruleForm.value.maxWeight=null
  ruleForm.value.maxWidth=null
  ruleForm.value.maxHeight=null
  ruleForm.value.remarks=null
}
const submitForm = () => {
  let filterData=ref({
    data:ruleForm.value,
    userName:userStore.user.userName,
    userId:userStore.user.userId
  })
  console.log(filterData.value)
  /*request.post("/materialStore/saveMaterialStore", filterData.value).then((res) => {
    if(res.code==200 && res.data==="true"){
      resetForm()
      ElMessage.success(t('basicData.msg.saveSuccess'))
    }else if(res.data==="false1"){
      ElMessage.warning("该料架已存在")
    }else{
      ElMessage.warning(t('basicData.msg.saveFail'))
    }
  }).catch((err)=>{
    ElMessage.error(t('basicData.msg.ServerConnectionError'))
    router.push("/login")
  })*/
}
  //获取传过来的数据进行判断
  const str = route.query.id
  if (typeof str != 'undefined' && str != null && str !== '' && str !== '\n' && str !== '\r'){
    ruleForm.value.id = Number(str)
    request.post(`/materialStore/getSelectMaterialStore`,ruleForm.value).then((res) => {
      if(res.code==200){
        ruleForm.value=deepClone(res.data.data)
      }else{
        ElMessage.warning(res.msg)
        router.push("/login")
      }
    })
  }
</script>
<template>
 <div class="center-box">
   <el-card class="form-card">
   <el-form  size="medium" >
     <el-divider ></el-divider> <!-- 添加分隔线 -->
     <el-row gutter="20" >
       <el-col :span="10" >
         料架编号:<el-input v-model="ruleForm.glassShelfNumber"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-col :span="10" >
         料架名称:<el-input  v-model="ruleForm.glassShelfName" :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-divider ></el-divider> <!-- 添加分隔线 -->
     </el-row>
     <el-row gutter="20" >
       <el-col :span="10" >
         现有数量:<el-input  v-model="ruleForm.availableQuantity" :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-col :span="10" >
         总数量:<el-input v-model="ruleForm.totalQuantity"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-divider ></el-divider> <!-- 添加分隔线 -->
     </el-row>
     <el-row gutter="20" >
       <el-col :span="10" >
         单价:<el-input v-model="ruleForm.price"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-col :span="10" >
         单位:<el-input v-model="ruleForm.unit"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-divider ></el-divider> <!-- 添加分隔线 -->
     </el-row>
     <el-row gutter="20" >
       <el-col :span="10" >
         最大宽:<el-input v-model="ruleForm.maxWidth"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-col :span="10" >
         最大高:<el-input  v-model="ruleForm.maxHeight" :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-divider ></el-divider> <!-- 添加分隔线 -->
     </el-row>
     <el-row gutter="20" >
       <el-col :span="10" >
         最大承重:<el-input v-model="ruleForm.maxWeight"  :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-col :span="10" >
         备注:<el-input  v-model="ruleForm.remarks" :placeholder="$t('ingredients.pleaseEnterData')" style="width: 150px; height: 30px;" />
       </el-col>
       <el-divider ></el-divider> <!-- 添加分隔线 -->
     </el-row>
     <el-row  gutter="20" justify="center" >
       <el-col span="10">
         <el-button id="searchButton" type="primary" @click="resetForm" >{{$t('basicData.empty')}}</el-button>
       </el-col>
       <el-col span="10">
         <el-button id="searchButton" type="primary" @click="submitForm" >{{$t('basicData.save')}}</el-button>
       </el-col>
     </el-row>
   </el-form>
   </el-card>
 </div>
</template>
<style>
.centered-box {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
.form-card {
  width: 1000px;
  padding: 30px 30px;
}
.button-row {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}
</style>
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/FinishedGlassShelf.vue
New file
@@ -0,0 +1,73 @@
<!--  物料库存 -->
<script setup>
import {ref} from "vue";
import {ArrowLeftBold, ArrowRight, Search} from "@element-plus/icons-vue";
import request from "@/utils/request";
import deepClone from "@/utils/deepClone";
import {ElMessage} from "element-plus";
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 id="div-title">
      <el-breadcrumb :separator-icon="ArrowRight">
        <el-breadcrumb-item @click="changeRouter(1)" :class="indexFlag===1?'indexTag':''" :to="{ path: '/main/finishedGlassShelf/finishedGlassShelfInformation' }">{{$t('料架库存')}}</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(2)" :class="indexFlag===2?'indexTag':''" :to="{ path: '/main/finishedGlassShelf/materialOutbound' }">{{$t('料架出库')}}</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(3)" :class="indexFlag===3?'indexTag':''" :to="{ path: '/main/finishedGlassShelf/returnToStorage' }">{{$t('料架入库')}}</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(4)" :class="indexFlag===4?'indexTag':''" :to="{ path: '/main/finishedGlassShelf/createFinishedGlassShelf' }">{{$t('料架新增')}}</el-breadcrumb-item>
        <el-breadcrumb-item @click="changeRouter(6)" :class="indexFlag===6?'indexTag':''" :to="{ path: '/main/finishedGlassShelf/selectSurplusMaterials' }">{{$t('料架报表')}}</el-breadcrumb-item>
        <el-breadcrumb-item v-show="false" :to="{ path: '/main/order/orderReport' }">{{$t('ingredientsStock.returnToStorage')}}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <div id="main-body">
      <router-view  :key="route.fullPath" />
    </div>
  </div>
</template>
<style scoped>
#main{
  width: 100%;
  height: 100%;
}
#div-title{
  height: 5%;
  width: 100%;
}
#searchButton{
  margin-top: -5px;
  margin-left: 1rem;
}
#searchButton1{
//margin-left: 10rem;
}
/*main-body样式*/
#main-body{
  width: 99%;
  height: 92%;
  margin-top: 1%;
}
#select{
  margin-left:0.5rem;
}
:deep(.indexTag .el-breadcrumb__inner){
  color: #5CADFE !important;
}
</style>
north-glass-erp/northglass-erp/src/views/mm/finishedGlassShelf/FinishedGlassShelfInformation.vue
New file
@@ -0,0 +1,530 @@
<script setup>
import {onMounted, reactive, ref} from "vue";
import {useRouter} from  'vue-router'
import request from "@/utils/request";
import deepClone from "@/utils/deepClone";
import useUserInfoStore from "@/stores/userInfo";
import {ElMessage, ElMessageBox} from "element-plus";
import {Search} from "@element-plus/icons-vue";
import { useI18n } from 'vue-i18n'
import {addListener, toolbarButtonClickEvent} from "@/hook/mouseMove";
import {changeFilterEvent,filterChanged,filterChangeds} from "@/hook"
import {divideAuto, multiply} from "@/utils/decimal";
import companyInfo from "@/stores/sd/companyInfo";
import footSum from "@/hook/footSum";
import {copyTableCellValue} from "@/hook/copyTableCellValue";
//语言获取
const { t } = useI18n()
const userStore = useUserInfoStore()
const company = companyInfo()
const router = useRouter()
let produceList = ref([])
let sheetIndex = ref(-1)
let rowIndexData = ref(null)
let dialogTableVisible = ref(false)
let refMaterialAddition=ref()
const getTableRow = (row,type) =>{
  switch (type) {
    case 'edit' :{
      //alert('我接收到子组件传送的编辑信息')
      router.push({path: '/main/trader/CreateTrader', query: { id: row.id }})
      break
    }
    case 'delete':{
      alert('我接收到子组件传送的删除信息')
      break
    }
  }
}
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 : 100
})
let filterData = ref({
})
const values = ref('')
let selectDate = ref(["",""])
let BasicData = ref([])
let materialStore= ref([])
onMounted(() => {
  addListener(xGrid.value,gridOptions)
  //第一次调用
  // request.get(`/BasicWarehouse/BasicWarehouseType/`+t('ingredients.originalFilm')+'|'+t('ingredients.accessories')).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=null
  //       if(BasicData.value[i].OperateType==="name"){
  //         aa={field: "json."+BasicData.value[i].OperateType, width: '150',title: BasicData.value[i].OperateTypeName, sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChangeds}
  //       }else{
  //         aa={field: "json."+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)
  //
  //     }
  //     values.value=t('ingredientsStock.inventory')
  //     getInventoryWorks()
  //
  //   }else{
  //     ElMessage.warning(res.msg)
  //   }
  // })
})
const getInventoryEngineeringWork = () => {
    request.post(`/materialInventory/getSelectMaterialInventoryEngineeringDate/${pageNum.value}/${total.pageSize}/${selectDate.value}`,filterData.value).then((res) => {
      if(res.code==200){
        materialStore.value=[]
        for (let i=0;i<res.data.data.length;i++){
          materialStore.value[i]=(res.data.data[i])
          materialStore.value[i].json=(JSON.parse(res.data.data[i].json))
        }
        total.dataTotal = res.data.total.total*1
        total.pageTotal= res.data.total.pageTotal
        pageNum.value=1
        selectDate.value = res.data.selectDate
        gridOptions.toolbarConfig.buttons[2].disabled = true
        produceList = deepClone(materialStore.value)
        xGrid.value.loadData(produceList)
        gridOptions.loading=false
      }else{
        ElMessage.warning(res.msg)
        router.push("/login")
      }
    })
}
const selectOrderList = ()=>{
  request.get(`/BasicWarehouse/BasicWarehouseType/`+t('ingredients.originalFilm')+'|'+t('ingredients.accessories')).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=null
        if(BasicData.value[i].OperateType==="model"){
           aa={field: "json."+BasicData.value[i].OperateType, width: '150',title: BasicData.value[i].OperateTypeName, sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged}
        }else{
           aa={field: "json."+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)
      }
      if(values.value===t('ingredientsStock.inventory')){
        getInventoryWorkPaging()
      }else{
        getInventoryEngineeringWork()
      }
    }else{
      ElMessage.warning(res.msg)
    }
  })
}
const changeDate =  ()=>{
  selectOrderList()
}
//页脚跳转
const handlePageChange = ({ currentPage, pageSize }) => {
  selectOrderList()
  total.pageTotal = pageSize
  pageNum.value=currentPage
}
//子组件接收参数
const xGrid = ref()
const gridOptions = reactive({
  border:  "full",//表格加边框
  keepSource: true,//保持源数据
  align: 'center',//文字居中
  stripe:true,//斑马纹
  rowConfig: {isCurrent: true, isHover: true,height: 30},//鼠标移动或选择高亮
  id: 'SelectIngredientsStock',
  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:[
    { type: 'checkbox',fixed:"left", title: t('basicData.check'), width: '80' },
    {title: t('basicData.operate'), width: '110', slots: { default: 'button_slot' },fixed:'left'},
    { type: 'seq',fixed:"left", title: t('basicData.Number'), width: '80' },
    {field: 'inventoryOrganization', width:'150', title: t('料架编号'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged },
    {field: 'materialCode', width: '150',title: t('料架名称'), sortable: true,showOverflow:"ellipsis" ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'producer', width: '120',title: t('现有数量'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'id',width: '100', title: t('总数量'), sortable: true,showOverflow:"ellipsis",filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'projectNo',width: '100', title: t('单价'), sortable: true,showOverflow:"ellipsis",filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'inventoryQuantity',width: '100', title: t('金额'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'availableQuantity', width: '100',title: t('单位'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'planQuantity', width: '100',title: t('最大承重'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'totalArea',width: '100', title: t('最大高'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'dateOfManufacture',width: '100', title: t('最大宽'), sortable: true},
    {field: 'qualityGuaranteePeriod',width: '100', title: t('备注'), sortable: true,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'createTime',width: '100', title: t('创建时间'), sortable: true},
  ],//表头按钮
  toolbarConfig: {
    buttons: [
      {'code': 'add', 'name': t('添加'),status: 'primary'},
      {'code': 'out', 'name': t('出库'),status: 'primary'}
    ],
    /*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')
        }
        const List = ["inventoryQuantity",'availableQuantity','totalArea']
        if (List.includes(column.field)) {
          return footSum(data, column.field)
        }
        return ''
      })
    ]
  }
})
const gridEvents = {
  async toolbarButtonClick({code}) {
    const $grid = xGrid.value
    if ($grid) {
      switch (code) {
        case 'out': {
          $grid.clearFilter()
          const selectRecords = $grid.getCheckboxRecords()
          if (selectRecords.length === 0) {
            ElMessage.warning(t('productStock.unselectedData'))
            return
          }
          let id = ""
          const array = [];
          if (values.value===t('ingredientsStock.inventory')){
            for (let i = 0; i < selectRecords.length; i++) {
              array.push(selectRecords[i].id)
              if (i + 1 === selectRecords.length) {
                id += selectRecords[i].id
              } else {
                id += selectRecords[i].id + "|"
              }
            }
          }else{
            for (let i = 0; i < selectRecords.length; i++) {
              array.push(selectRecords[i].useId)
              if (i + 1 === selectRecords.length) {
                id += selectRecords[i].useId
              } else {
                id += selectRecords[i].useId + "|"
              }
            }
          }
          router.push({path: '/main/ingredientsStock/CreateOutbound', query: {id: id,type:values.value}})
          break
        }
        case 'add': {
          dialogTableVisible.value=true
          rowIndexData.value=null
          sheetIndex.value=1
          break
        }
        case 'update': {
          $grid.clearFilter()
          const selectRecords = $grid.getCheckboxRecords()
          if (selectRecords.length === 1) {
            dialogTableVisible.value=true
            rowIndexData.value=selectRecords[0]
            sheetIndex.value=2
          }else{
            ElMessage.warning(t('请选中一行数据'))
            return
          }
          break
        }
        case 'delete': {
          $grid.clearFilter()
          const selectRecords = $grid.getCheckboxRecords()
          if (selectRecords.length === 0) {
            ElMessage.warning(t('productStock.unselectedData'))
            return
          }
          ElMessageBox.confirm("确认删除?",
              {
                confirmButtonText: t('basicData.confirmButtonText'),
                cancelButtonText: t('basicData.cancelButtonText'),
                distinguishCancelAndClose: true,
                type: 'warning',
              }
          ).then(()=>{
            let id = ""
            const array = [];
            if (values.value===t('ingredientsStock.inventory')){
              for (let i = 0; i < selectRecords.length; i++) {
                array.push(selectRecords[i].id)
                if (i + 1 === selectRecords.length) {
                  id += selectRecords[i].id
                } else {
                  id += selectRecords[i].id + "|"
                }
              }
            }else{
              for (let i = 0; i < selectRecords.length; i++) {
                array.push(selectRecords[i].useId)
                if (i + 1 === selectRecords.length) {
                  id += selectRecords[i].useId
                } else {
                  id += selectRecords[i].useId + "|"
                }
              }
            }
            let flowData = ref({
              materialInventory: selectRecords,
              ids: id,
              creator: userStore.user.userName
            })
            request.post(`/materialInventory/deleteMaterialInventory`,flowData.value).then((res) => {
              if(res.code==200 && res.data===true){
                ElMessage.success(t('searchOrder.msgDeleteSuccess'))
                router.push({path:'/main/ingredientsStock/selectIngredientsStock', query:{random:Math.random()}})
              }else{
                ElMessage.warning(res.msg)
              }
            })
          }).catch((action)=>{
          })
          break
        }
      }
    }
  },
  cellDblclick ({row,column}) {
    copyTableCellValue(row,column)
  }
}
</script>
<template>
  <div class="main-div-customer">
    <div class="head">
      <el-date-picker
          v-model="selectDate"
          type="daterange"
          :start-placeholder="$t('basicData.startDate')"
          :end-placeholder="$t('basicData.endDate')"
          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>
    </div>
    <div class="main-table">
      <vxe-grid
          height="100%"
          class="mytable-scrollbar"
          ref="xGrid"
          v-bind="gridOptions"
          v-on="gridEvents"
      >
        <!--      @toolbar-button-click="toolbarButtonClickEvent"-->
        <!--      下拉显示所有信息插槽-->
        <template #content="{ row }">
          <ul class="expand-wrapper">
            <li  v-for="(item,index) in gridOptions.columns" v-show="item.field!=undefined ">
              <span style="font-weight: bold">{{item.title+':  '}}</span>
              <span v-if="hasDecimal(item.field)">{{ hasDecimalhtml(item.field,row) }}</span>
              <span v-else>{{ row[item.field] }}</span>
            </li>
          </ul>
        </template>
        <!--左边固定显示的插槽-->
        <template #button_slot="{ row }">
          <el-button @click="getTableRow(row,'edit')"
                     link type="primary" size="small">{{$t('basicData.edit')}}</el-button>
          <el-button @click="getTableRow(row,'delete')" link type="primary" size="small">{{$t('basicData.delete')}}</el-button>
        </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 #pager>
          &lt;!&ndash;使用 pager 插槽&ndash;&gt;
          <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 v-model="dialogTableVisible" :title="$t('ingredients.materialAddition')" style="width: 70%;height:75% ">-->
<!--      <material-addition v-if="sheetIndex===1" ref="refMaterialAddition" style="width: 100%;height: 100%"-->
<!--                         :data=rowIndexData :type=1-->
<!--                         :close-on-click-modal="false"-->
<!--                         :close-on-press-escape="false"-->
<!--      />-->
<!--      <material-addition v-if="sheetIndex===2" ref="refMaterialAddition" style="width: 100%;height: 100%"-->
<!--                         :data=rowIndexData :type=2-->
<!--                         :close-on-click-modal="false"-->
<!--                         :close-on-press-escape="false"-->
<!--      />-->
<!--    </el-dialog>-->
  </div>
</template>
<style scoped>
.main-div-customer{
  width: 99%;
  height: 100%;
}
.main-div-customers{
  width: 99%;
  height: 100%;
}
.el-col{
  margin-left: 15px;
  margin-bottom: 5px;
}
.order-primary{
  width: 100%;
}
.head{
  width: 100%;
  height: 35px;
}
.main-table{
  width: 100%;
  height: calc(100% - 35px);
}
.vxe-grid {
  /* 禁用浏览器默认选中 */
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
</style>
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeControl.vue
@@ -12,17 +12,6 @@
  
    </div>
  <div style="position: fixed; top: 93px; right: 120px; display: flex; align-items: center;">
    <label style="margin-right: 10px; color: #333;">文件保存模式:</label>
    <select
        v-model="fileSaveMode"
        style="padding: 8px; border: 1px solid #ccc; border-radius: 4px;"
    >
      <option value="1">单文件</option>
      <option value="2">多文件</option>
    </select>
  </div>
    <button @click="submitLayouts" style="position: fixed; top: 90px; right: 20px; padding: 10px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer;">
      保存OPT
    </button>
@@ -34,6 +23,7 @@
import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
import requestOptimize from "@/utils/requestOptimize";
import useUserInfoStore from "@/stores/userInfo";
const { t } = useI18n();
@@ -48,6 +38,10 @@
const optimizeLayouts = ref(null);
const fileSaveMode = ref(1);
const fileMode = ref();
const userStore = useUserInfoStore()
const username = userStore.user.userName;
// 从 localStorage 读取库存数据
const loadInventoryData = () => {
@@ -103,7 +97,26 @@
      });
};
const fetchSettings = async (username) => {
  try {
    const response = await request.post(`/glassOptimize/selectOptimizeParms/${username}`);
    if (response.code == 200) {
      if (!response.data) {
        console.error('响应数据为空');
        return;
      }
      const parsedData = JSON.parse(response.data);
      console.log('设置内容:', parsedData);
      if (parsedData.server && parsedData.server.fileMode) {
        fileMode.value = parsedData.server.fileMode;
      }
    } else {
      console.error('请求失败,状态码:', response.code);
    }
  } catch (error) {
    console.error('请求发生错误:', error);
  }
};
const selectOptimizeInfo = () => {
@@ -134,10 +147,11 @@
};
onMounted(() => {
  // 读取库存数据
  // 读取库存数据和参数设置
  loadInventoryData();
  selectLayout();
  selectOptimizeInfo();
  fetchSettings(username);
});
const submitLayouts = async () => {
@@ -154,7 +168,7 @@
      glassType:inventoryData.value[0].model,
      quantity: inventoryData.value[0].processingQuantity,
      fileType:"OPT",
      fileSaveMode:fileSaveMode.value,
      fileSaveMode:fileMode.value,
      glassIdMode:1,
      layouts: optimizeLayouts.value.layouts
    }, {
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/OptimizeParms.vue
@@ -43,6 +43,12 @@
        return;
      }
      const parsedData = JSON.parse(response.data);
      if (!parsedData.server) {
        parsedData.server = {};
      }
      if (!parsedData.server.fileMode) {
        parsedData.server.fileMode = '1'; // 默认为单文件模式
      }
      Object.assign(settings, parsedData);
      console.log('设置已更新:', settings);
    } else {
@@ -237,6 +243,28 @@
        <div class="display-settings">
          <h2>结果输出设置</h2>
          <div class="form-group">
            <label>切割文件保存模式</label>
            <div style="margin-left: 3px;"></div>
            <div class="radio-group">
              <input
                  type="radio"
                  id="singleFile"
                  value="1"
                  v-model="settings.server.fileMode"
              />
              <label for="singleFile">单文件</label>
              <input
                  type="radio"
                  id="multiFile"
                  value="2"
                  v-model="settings.server.fileMode"
                  style="margin-left: 20px;"
              />
              <label for="multiFile">多文件</label>
            </div>
          </div>
          <div class="form-group">
            <label>工程文件保存路径</label>
            <input type="text" v-model="settings.server.output_format" />
          </div>
@@ -387,7 +415,7 @@
  background-color: white;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 4 rgba(0, 0, 0, 0.1);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.sidebar-item {
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/Compute.vue
@@ -47,7 +47,7 @@
const optionVal = ref(50)
// 定义装载率
const percentage1 = ref(80)
const percentage1 = ref(50)
const percentage2 = ref(50)
// 定义其他表单数据
north-glass-erp/northglass-erp/src/views/sd/basicData/CreateBasicData.vue
@@ -1,18 +1,21 @@
<script setup>
import request from "@/utils/request"
import {onMounted, ref, watch} from "vue";
import {onMounted, ref} from "vue";
import {useI18n} from "vue-i18n"
import {ElMessage} from "element-plus"
import {useRouter,useRoute} from "vue-router"
import {useRoute, useRouter} from "vue-router"
const { t } = useI18n()
const router = useRouter()
const route = useRoute()
let iconWidth=ref(null)
let iconHeight=ref(null)
let basic = ref({
  basicType : ['',''],
  input:'',
  nickname:''
  nickname:null
})
let options=ref([
  { "label": t('orderBasicData.order'),
@@ -128,8 +131,16 @@
  if(props.rowIndex){
    basic.value.basicType[0] =  props.rowIndex.basicType
    basic.value.basicType[1] =  props.rowIndex.basicCategory
    basic.value.input =  props.rowIndex.basicName
    basic.value.nickname =  props.rowIndex.nickname
    if(basic.value.basicType[1]==="icon"){
      basic.value.input =  props.rowIndex.basicName
      basic.value.nickname =  JSON.parse(props.rowIndex.nickname).data
      iconWidth.value=JSON.parse(props.rowIndex.nickname).width
      iconHeight.value=JSON.parse(props.rowIndex.nickname).height
    }else{
      basic.value.input =  props.rowIndex.basicName
      basic.value.nickname =  props.rowIndex.nickname
    }
  }
})
@@ -139,6 +150,15 @@
    if(!basic.value.input.includes("mm")){
      basic.value.input=basic.value.input+"mm"
    }
  }
  if(basic.value.basicType[1]==="icon"){
    let nickname=basic.value.nickname
    let data={
      width: iconWidth.value,
      height: iconHeight.value,
      data: nickname
    }
    basic.value.nickname=JSON.stringify(data)
  }
  basic.value.input=basic.value.input.trim()
  request.post(`/basicData/addBasicData`, basic.value).then(res => {
@@ -153,6 +173,15 @@
    if(!basic.value.input.includes("mm")){
      basic.value.input=basic.value.input+"mm"
    }
  }
  if(basic.value.basicType[1]==="icon"){
    let nickname=basic.value.nickname
    let data={
      width: iconWidth.value,
      height: iconHeight.value,
      data: nickname
    }
    basic.value.nickname=JSON.stringify(data)
  }
  let submitArr  = props.rowIndex
  submitArr.basicType = basic.value.basicType[0]
@@ -238,6 +267,22 @@
      </el-col>
    </el-row>
    <el-row v-if="basic.basicType.length!==0 && basic.basicType[1]==='icon'" >
      <el-col :span="4">
        {{ $t('order.width') }}:
      </el-col>
      <el-col :span="12">
        <el-input  v-model="iconWidth"/>
      </el-col>
    </el-row>
    <el-row v-if="basic.basicType.length!==0 && basic.basicType[1]==='icon'" >
      <el-col :span="4">
        {{ $t('order.height') }}:
      </el-col>
      <el-col :span="12">
        <el-input  v-model="iconHeight"/>
      </el-col>
    </el-row>
    <el-row v-if="basic.basicType.length!==0 && basic.basicType[1]==='icon'" >
      <el-col :span="4"></el-col>
      <el-col :span="12">
        <el-upload
north-glass-erp/src/main/resources/mapper/pp/GlassOptimize.xml
@@ -1711,7 +1711,10 @@
                    p.creater = a.Id
                    )))
        WHERE
            ( p.state = 1 ) and p.tempering_state=0 and optimize_state=0 and p.project_no = #{projectNo}
            ( p.state = 1 ) and
#             p.tempering_state=0 and
#             optimize_state=0 and
            p.project_no = #{projectNo}
        ORDER BY
            p.create_time DESC,
            p.project_no
@@ -1881,27 +1884,40 @@
    </select>
    <select id="getOptimizeDetailsInfo" resultType="java.util.Map">
        SELECT
            0 As isRemain,
            width AS realWidth,
            height AS realHeight,
            p_width AS width,
            p_height AS height,
            process_id AS processId,
            layer,
            total_layer AS totalLayer,
            order_sort As orderSort,
            stock_id AS layoutId,
            stock_number AS glassSort,
            x_axis AS x,
            y_axis AS y,
            mark_icon AS markIcon,
            isRotate,
            glass_point AS glassPoint,
            rack_no As rackNo
            0 AS isRemain,
            od.width AS realWidth,
            od.height AS realHeight,
            od.p_width AS width,
            od.p_height AS height,
            od.process_id AS processId,
            od.layer,
            od.total_layer AS totalLayer,
            od.order_sort AS orderSort,
            od.stock_id AS layoutId,
            od.stock_number AS glassSort,
            od.x_axis AS x,
            od.y_axis AS y,
            od.mark_icon AS markIcon,
            od.isRotate,
            od.glass_point AS glassPoint,
            fc.order_id AS orderNo,
            ogd.process,
            o.customer_name AS customerName,
            o.processing_note AS processingNote,
            o.project AS projectName,
            ord.product_name AS productName,
            ord.building_number AS buildingNumber,
            COALESCE(h.layout_id, 0) as heatLayoutId,
            od.rack_no AS rackNo
        FROM
            pp.optimize_detail
            pp.optimize_detail od
                LEFT JOIN pp.flow_card fc on od.process_id = fc.process_id
                LEFT JOIN sd.order_glass_detail ogd ON fc.order_id = ogd.order_id
                LEFT JOIN sd.ORDER o ON o.order_id = fc.order_id
                LEFT JOIN sd.order_detail ord ON fc.order_id = ord.order_id
                LEFT JOIN pp.optimize_heat_detail h ON h.process_id = fc.process_id
        WHERE
            project_no = #{projectId}
            od.project_no =  #{projectId}
    </select>
    <select id="getOptimizeOffsetsInfo" resultType="java.util.Map">
        SELECT