leiqunqing
2026-02-06 15b3879cd259108e7ebb755fe02c190f28f1e20c
完善项目
已重命名1个文件
已删除5个文件
已修改39个文件
5359 ■■■■ 文件已修改
.gitignore 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/slnx.sqlite 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/components/basic/VolTable.vue 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/extension/basicinfo/formula.js 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/Home.vue 675 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/boxing.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/formula.vue 332 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/formulaDetail.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/processInfo.vue 572 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/processInfoDetail.vue 317 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/basicinfo/scanStation.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Client/src/views/quartzJob/deviceInfo.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/17.14.794.21998/CodeChunks.db 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/17.14.794.21998/SemanticSymbols.db 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/DesignTimeBuild/.dtbcache.v2 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/0f5d7584-9cfe-4074-aeb3-fa1f9e570949.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/37cbdcf3-408e-4196-9c7f-486ef5eef107.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/6b8b6a38-d1b1-459e-b415-f709208d542a.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/c99954ff-673f-45d7-b93b-30e6c1adfe58.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/.futdcache.v2 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/.suo 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/BoxingDetailService.cs 354 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/FormulaService.cs 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ProcessInfoService.cs 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ScanStationService.cs 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/PLCEnum/R_PLCDBName.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/PLCEnum/W_PLCDBName.cs 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/SocketClient.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/WIDESEAWCS_Common.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_DTO/BasicInfo/ToolingBoardSubmitDto.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IBoxingDetailService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IProcessInfoService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IScanStationService.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_Boxing.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_Formula.cs 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_FormulaDetail.cs 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ProcessInfo.cs 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ProcessInfoDetail.cs 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ScanStation.cs 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/BasicInfo/ProcessInfoController.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/BasicInfo/ScanStationController.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Log/全局日志AOP_1766486446.log 1372 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/obj/Debug/net6.0/WIDESEAWCS_TaskInfoService.AssemblyInfo.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/obj/Debug/net6.0/WIDESEAWCS_TaskInfoService.AssemblyInfoInputs.cache 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Tasks/PLCJob.cs 477 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -274,4 +274,5 @@
/项目代码/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/bin
/项目代码/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/bin
*.dll
/项目资料/虚拟串口驱动/vspd6.9
/项目资料/虚拟串口驱动/vspd6.9
**/.vs/
.vs/slnx.sqlite
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/components/basic/VolTable.vue
@@ -143,21 +143,13 @@
          >
            <div style="display: flex; align-items: center" @click.stop>
              <i
                style="
                  padding: 3px;
                  margin-right: 10px;
                  color: #8f9293;
                  cursor: pointer;
                "
                style="padding: 3px; margin-right: 10px; color: #8f9293; cursor: pointer"
                @click="showUpload(scope.row, column)"
                class="el-icon-upload"
              ></i>
              <img
                v-show="column.edit.type == 'img'"
                v-for="(file, imgIndex) in getFilePath(
                  scope.row[column.field],
                  column
                )"
                v-for="(file, imgIndex) in getFilePath(scope.row[column.field], column)"
                :key="imgIndex"
                :onerror="defaultImg"
                @click="viewImg(scope.row, column, file.path, $event)"
@@ -168,10 +160,7 @@
                style="margin-right: 8px"
                v-show="column.edit.type != 'img'"
                class="t-file"
                v-for="(file, fIndex) in getFilePath(
                  scope.row[column.field],
                  column
                )"
                v-for="(file, fIndex) in getFilePath(scope.row[column.field], column)"
                :key="fIndex"
                @click="dowloadFile(file)"
                >{{ file.name }}</a
@@ -197,8 +186,7 @@
                  v-model="scope.row[column.field]"
                  @change="
                    (val) => {
                      column.onChange &&
                        column.onChange(scope.row, column, val);
                      column.onChange && column.onChange(scope.row, column, val);
                    }
                  "
                  :type="column.edit.type"
@@ -216,8 +204,7 @@
                  v-model="scope.row[column.field]"
                  @change="
                    (val) => {
                      column.onChange &&
                        column.onChange(scope.row, column, val);
                      column.onChange && column.onChange(scope.row, column, val);
                    }
                  "
                  :placeholder="column.placeholder || column.title"
@@ -253,9 +240,7 @@
                >
                </el-switch>
                <template
                  v-else-if="
                    ['select', 'selectList'].indexOf(column.edit.type) != -1
                  "
                  v-else-if="['select', 'selectList'].indexOf(column.edit.type) != -1"
                >
                  <el-select-v2
                    style="width: 100%"
@@ -267,9 +252,7 @@
                    :placeholder="column.placeholder || column.title"
                    :autocomplete="column.autocomplete"
                    :options="column.bind.data"
                    @change="
                      column.onChange && column.onChange(scope.row, column)
                    "
                    @change="column.onChange && column.onChange(scope.row, column)"
                    clearable
                    :disabled="initColumnDisabled(scope.row, column)"
                  >
@@ -284,16 +267,12 @@
                    v-else
                    v-model="scope.row[column.field]"
                    :filterable="
                      column.filter || column.bind.data.length > 10
                        ? true
                        : false
                      column.filter || column.bind.data.length > 10 ? true : false
                    "
                    :multiple="column.edit.type == 'select'"
                    :placeholder="column.placeholder || column.title"
                    :autocomplete="column.autocomplete"
                    @change="
                      column.onChange && column.onChange(scope.row, column)
                    "
                    @change="column.onChange && column.onChange(scope.row, column)"
                    clearable
                    :disabled="initColumnDisabled(scope.row, column)"
                  >
@@ -333,10 +312,7 @@
                  :disabled="initColumnDisabled(scope.row, column)"
                ></el-input>
              </div>
              <div
                class="extra"
                v-if="column.extra && edit.rowIndex == scope.$index"
              >
              <div class="extra" v-if="column.extra && edit.rowIndex == scope.$index">
                <a
                  :style="column.extra.style"
                  style="text-decoration: none"
@@ -359,10 +335,7 @@
            ></a>
            <img
              v-else-if="column.type == 'img'"
              v-for="(file, imgIndex) in getFilePath(
                scope.row[column.field],
                column
              )"
              v-for="(file, imgIndex) in getFilePath(scope.row[column.field], column)"
              :key="imgIndex"
              :onerror="defaultImg"
              @click="viewImg(scope.row, column, file.path, $event)"
@@ -373,10 +346,7 @@
              style="margin-right: 8px"
              v-else-if="column.type == 'file' || column.type == 'excel'"
              class="t-file"
              v-for="(file, fIndex) in getFilePath(
                scope.row[column.field],
                column
              )"
              v-for="(file, fIndex) in getFilePath(scope.row[column.field], column)"
              :key="fIndex"
              @click="dowloadFile(file)"
              >{{ file.name }}</a
@@ -418,9 +388,7 @@
                :effect="column.effect"
                >{{ formatter(scope.row, column, true) }}</el-tag
              >
              <template v-else>{{
                formatter(scope.row, column, true)
              }}</template>
              <template v-else>{{ formatter(scope.row, column, true) }}</template>
            </div>
            <span v-else>{{ formatter(scope.row, column, true) }}</span>
@@ -463,9 +431,7 @@
        :max-file="currentColumn.edit.maxFile"
        :img="currentColumn.edit.type == 'img'"
        :excel="currentColumn.edit.type == 'excel'"
        :fileTypes="
          currentColumn.edit.fileTypes ? currentColumn.edit.fileTypes : []
        "
        :fileTypes="currentColumn.edit.fileTypes ? currentColumn.edit.fileTypes : []"
        :fileInfo="fileInfo"
        :upload-after="uploadAfter"
      >
@@ -477,9 +443,7 @@
        <el-button type="default" size="small" @click="uploadModel = false"
          >关闭</el-button
        >
        <el-button type="primary" size="small" @click="saveUpload"
          >保存</el-button
        >
        <el-button type="primary" size="small" @click="saveUpload">保存</el-button>
      </div>
    </template>
  </VolBox>
@@ -506,9 +470,7 @@
  },
  components: {
    "table-render": VolTableRender,
    VolUpload: defineAsyncComponent(() =>
      import("@/components/basic/VolUpload.vue")
    ),
    VolUpload: defineAsyncComponent(() => import("@/components/basic/VolUpload.vue")),
    VolBox: defineAsyncComponent(() => import("@/components/basic/VolBox.vue")),
  },
  props: {
@@ -642,7 +604,6 @@
      default: 500,
    },
    selectable: {
      type: Function,
      default: (row, index) => {
        return true;
@@ -783,33 +744,28 @@
      }
    });
    if (keys.length > 0) {
      this.http
        .post("/api/Sys_Dictionary/GetVueDictionary", keys)
        .then((dic) => {
          dic.forEach((x) => {
            if (x.data.length > this.select2Count) {
              x.data.forEach((item) => {
                item.label = item.value;
                item.value = item.key;
      this.http.post("/api/Sys_Dictionary/GetVueDictionary", keys).then((dic) => {
        dic.forEach((x) => {
          if (x.data.length > this.select2Count) {
            x.data.forEach((item) => {
              item.label = item.value;
              item.value = item.key;
            });
          }
          columnBind.forEach((c) => {
            // è½¬æ¢æ•°æ®æºçš„类型与列的类型一致(2020.04.04)
            if (c.key == x.dicNo && (c.valueTyoe == "int" || c.valueTyoe == "sbyte")) {
              x.data.forEach((d) => {
                // 2020.09.01增加对数字类型的二次判断
                if (!isNaN(d.key)) {
                  d.key = ~~d.key;
                }
              });
            }
            columnBind.forEach((c) => {
              // è½¬æ¢æ•°æ®æºçš„类型与列的类型一致(2020.04.04)
              if (
                c.key == x.dicNo &&
                (c.valueTyoe == "int" || c.valueTyoe == "sbyte")
              ) {
                x.data.forEach((d) => {
                  // 2020.09.01增加对数字类型的二次判断
                  if (!isNaN(d.key)) {
                    d.key = ~~d.key;
                  }
                });
              }
              if (c.key == x.dicNo) c.data.push(...x.data);
            });
            if (c.key == x.dicNo) c.data.push(...x.data);
          });
        });
      });
    }
    this.paginations.sort = this.pagination.sortName;
@@ -861,11 +817,7 @@
    },
    extraClick(row, column) {
      column.extra.click &&
        column.extra.click(
          row,
          column,
          this.url ? this.rowData : this.tableData
        );
        column.extra.click(row, column, this.url ? this.rowData : this.tableData);
    },
    headerClick(column, event) {
      if (this.clickEdit && this.edit.rowIndex != -1) {
@@ -885,74 +837,76 @@
    rowDbClick(row, column, event) {
      //2021.05.23增加双击行事件
      this.$emit("rowDbClick", { row, column, event });
    },rowClick(row, column, event) {
  // 2022.02.20增加点击时表格参数判断
  if (!column) {
    return;
  }
    },
    rowClick(row, column, event) {
      // 2022.02.20增加点击时表格参数判断
      if (!column) {
        return;
      }
  // ===== ä¼˜åŒ–:隔离复选框点击事件,避免冒泡干扰 å¼€å§‹ =====
  // åˆ¤æ–­ç‚¹å‡»ç›®æ ‡æ˜¯å¦æ˜¯å¤é€‰æ¡†ï¼ˆæˆ–复选框所在的单元格/图标)
  const targetEl = event.target;
  const isCheckbox = targetEl.classList.contains('el-checkbox__input') ||
                      targetEl.closest('.el-checkbox__input') ||
                      targetEl.closest('.el-table-column--selection');
  // å¦‚果点击的是复选框区域,直接返回,不执行行选中逻辑
  if (isCheckbox) {
    return;
  }
  // ===== ä¼˜åŒ–:隔离复选框点击事件 ç»“束 =====
      // ===== ä¼˜åŒ–:隔离复选框点击事件,避免冒泡干扰 å¼€å§‹ =====
      // åˆ¤æ–­ç‚¹å‡»ç›®æ ‡æ˜¯å¦æ˜¯å¤é€‰æ¡†ï¼ˆæˆ–复选框所在的单元格/图标)
      const targetEl = event.target;
      const isCheckbox =
        targetEl.classList.contains("el-checkbox__input") ||
        targetEl.closest(".el-checkbox__input") ||
        targetEl.closest(".el-table-column--selection");
      // å¦‚果点击的是复选框区域,直接返回,不执行行选中逻辑
      if (isCheckbox) {
        return;
      }
      // ===== ä¼˜åŒ–:隔离复选框点击事件 ç»“束 =====
  // ===== ä¼˜åŒ–:点击行选中/切换复选框 å¼€å§‹ =====
  // 1. åˆ¤æ–­æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†ï¼ˆck为true),不显示则无需处理
  // 2. ç¼–辑状态下不触发(避免干扰编辑功能)
  if (this.ck && this.edit.rowIndex === -1) {
    // 3. å•选场景(single为true):先清空所有选中项,再强制选中当前行(保持单选逻辑)
    if (this.single) {
      this.$refs.table.clearSelection(); // æ¸…空所有选中
      this.$refs.table.toggleRowSelection(row, true); // å•选场景强制选中当前行
    }
    // 4. å¤šé€‰åœºæ™¯ï¼ˆsingle为false):不传第二个参数,实现切换选中/取消状态
    else {
      this.$refs.table.toggleRowSelection(row); // åˆ‡æ¢çŠ¶æ€ï¼Œæ”¯æŒå–æ¶ˆé€‰ä¸­
    }
  }
  // ===== ä¼˜åŒ–:点击行选中/切换复选框 ç»“束 =====
  // æ­£åœ¨ç¼–辑时,禁止触发rowClick事件
  if (this.edit.rowIndex == -1) {
    this.$emit("rowClick", { row, column, event });
  }
  // ç‚¹å‡»è¡Œäº‹ä»¶(2020.11.07)
  if (!this.doubleEdit) {
    return;
  }
  // ç‚¹å‡»å…¶ä»–行时,如果点击的行与正在编辑的行相同,保持编辑状态
  if (this.clickEdit && this.edit.rowIndex != -1) {
    if (row.elementIndex == this.edit.rowIndex) {
      // ç‚¹å‡»çš„单元格如果不可以编辑,直接结束编辑
      // 2020.10.12修复结束编辑时,element table高版本属性获取不到的问题
      let _col = this.columns.find((x) => {
        return x.field == ((event && event.property) || column.property);
      });
      if (_col && (!_col.edit || _col.readonly)) {
        if (this.rowEndEdit(row, event)) {
          this.edit.rowIndex = -1;
      // ===== ä¼˜åŒ–:点击行选中/切换复选框 å¼€å§‹ =====
      // 1. åˆ¤æ–­æ˜¯å¦æ˜¾ç¤ºå¤é€‰æ¡†ï¼ˆck为true),不显示则无需处理
      // 2. ç¼–辑状态下不触发(避免干扰编辑功能)
      if (this.ck && this.edit.rowIndex === -1) {
        // 3. å•选场景(single为true):先清空所有选中项,再强制选中当前行(保持单选逻辑)
        if (this.single) {
          this.$refs.table.clearSelection(); // æ¸…空所有选中
          this.$refs.table.toggleRowSelection(row, true); // å•选场景强制选中当前行
        }
        // 4. å¤šé€‰åœºæ™¯ï¼ˆsingle为false):不传第二个参数,实现切换选中/取消状态
        else {
          this.$refs.table.toggleRowSelection(row); // åˆ‡æ¢çŠ¶æ€ï¼Œæ”¯æŒå–æ¶ˆé€‰ä¸­
        }
      }
      return;
    }
    if (this.rowEndEdit(row, event && event.property ? event : column)) {
      this.edit.rowIndex = -1;
    }
    //当正在编辑,且点击到其他行时,在原编辑的行结束编辑后,触发新行的rowClick事件
    //正在编辑时,禁止触发rowClick事件
    if (this.edit.rowIndex == -1) {
      this.$emit("rowClick", { row, column, event });
    }
  }
  this.rowBeginEdit(row, column);
},
      // ===== ä¼˜åŒ–:点击行选中/切换复选框 ç»“束 =====
      // æ­£åœ¨ç¼–辑时,禁止触发rowClick事件
      if (this.edit.rowIndex == -1) {
        this.$emit("rowClick", { row, column, event });
      }
      // ç‚¹å‡»è¡Œäº‹ä»¶(2020.11.07)
      if (!this.doubleEdit) {
        return;
      }
      // ç‚¹å‡»å…¶ä»–行时,如果点击的行与正在编辑的行相同,保持编辑状态
      if (this.clickEdit && this.edit.rowIndex != -1) {
        if (row.elementIndex == this.edit.rowIndex) {
          // ç‚¹å‡»çš„单元格如果不可以编辑,直接结束编辑
          // 2020.10.12修复结束编辑时,element table高版本属性获取不到的问题
          let _col = this.columns.find((x) => {
            return x.field == ((event && event.property) || column.property);
          });
          if (_col && (!_col.edit || _col.readonly)) {
            if (this.rowEndEdit(row, event)) {
              this.edit.rowIndex = -1;
            }
          }
          return;
        }
        if (this.rowEndEdit(row, event && event.property ? event : column)) {
          this.edit.rowIndex = -1;
        }
        //当正在编辑,且点击到其他行时,在原编辑的行结束编辑后,触发新行的rowClick事件
        //正在编辑时,禁止触发rowClick事件
        if (this.edit.rowIndex == -1) {
          this.$emit("rowClick", { row, column, event });
        }
      }
      this.rowBeginEdit(row, column);
    },
    //   //正在编辑时,禁止出发rowClick事件
    //   if (this.edit.rowIndex == -1) {
@@ -1028,9 +982,7 @@
        if (column.base64) {
          fileInfo.push({
            name: "",
            path:
              (file.indexOf("data") == -1 ? "data:image/png;base64," : "") +
              file,
            path: (file.indexOf("data") == -1 ? "data:image/png;base64," : "") + file,
          });
        } else if (file.indexOf(".") != -1) {
          let splitFile = file.split("/");
@@ -1200,9 +1152,7 @@
          this.edit.rowIndex = -1;
          return;
        }
        let row = (this.url ? this.rowData : this.tableData)[
          this.edit.rowIndex
        ];
        let row = (this.url ? this.rowData : this.tableData)[this.edit.rowIndex];
        for (let index = 0; index < this.columns.length; index++) {
          const _column = this.columns[index];
          if (_column.edit) {
@@ -1300,9 +1250,7 @@
      let data = this.url ? this.rowData : this.tableData;
      let indexArr = this.getSelectedIndex();
      if (indexArr.length == 0) {
        return this.$Message.error(
          "删除操作必须设置VolTable的属性index='true'"
        );
        return this.$Message.error("删除操作必须设置VolTable的属性index='true'");
      }
      // if (indexArr.length == 0 || !this.key) {
      //   return this.$message.error(
@@ -1393,19 +1341,17 @@
      }
      if (remoteInfo.length == 0) return;
      // ha= Object.assign([], ha, hb)
      this.http
        .post("/api/Sys_Dictionary/GetTableDictionary", remoteInfo)
        .then((dic) => {
          dic.forEach((x) => {
            this.remoteColumns.forEach((column) => {
              if (column.bind.key == x.key) {
                column.bind.data = Object.assign([], column.bind.data, x.data);
                // column.bind.data.push(...x.data);
              }
            });
      this.http.post("/api/Sys_Dictionary/GetTableDictionary", remoteInfo).then((dic) => {
        dic.forEach((x) => {
          this.remoteColumns.forEach((column) => {
            if (column.bind.key == x.key) {
              column.bind.data = Object.assign([], column.bind.data, x.data);
              // column.bind.data.push(...x.data);
            }
          });
          this.$emit("dicInited", dic);
        });
        this.$emit("dicInited", dic);
      });
    },
    load(query, isResetPage) {
      // isResetPage重置分页数据
@@ -1504,9 +1450,7 @@
        if (data.summary.hasOwnProperty(col.field)) {
          let sum = data.summary[col.field];
          if (sum) {
            sum =
              (sum * 1.0).toFixed(col.numberLength || 2).replace(".00", "") *
              1.0;
            sum = (sum * 1.0).toFixed(col.numberLength || 2).replace(".00", "") * 1.0;
          }
          this.summaryData.push(sum);
        } else {
@@ -1633,11 +1577,7 @@
          : column.bind.data
        ).forEach((x) => {
          // 2020.06.06修复数据源为selectList时,key为数字0时不能转换文本的问题
          if (
            x.key !== "" &&
            x.key !== undefined &&
            x.key + "" == valArr[index] + ""
          ) {
          if (x.key !== "" && x.key !== undefined && x.key + "" == valArr[index] + "") {
            valArr[index] = x.label || x.value;
          }
        });
@@ -1669,9 +1609,7 @@
        if (column.summary == "avg") {
          sum = sum / (this.rowData.length || this.tableData.length || 1);
        }
        sum =
          (sum * 1.0).toFixed(column.numberLength || 2).replace(".00", "") *
          1.0;
        sum = (sum * 1.0).toFixed(column.numberLength || 2).replace(".00", "") * 1.0;
      }
      this.summaryData[this.summaryIndex[column.field]] = sum;
    },
@@ -1696,8 +1634,7 @@
        return true;
      }
      return (
        date1.valueOf() <
        (typeof date2 == "number" ? date2 : new Date(date2).valueOf())
        date1.valueOf() < (typeof date2 == "number" ? date2 : new Date(date2).valueOf())
      );
    },
    getDateOptions(date, item) {
@@ -1709,9 +1646,7 @@
        //不设置时分秒,后面会自动加上 08:00
        item.min = item.min + " 00:00:000";
      }
      return (
        this.compareDate(date, item.min) || !this.compareDate(date, item.max)
      );
      return this.compareDate(date, item.min) || !this.compareDate(date, item.max);
    },
    getDateFormat(column) {
      //见https://day.js.org/docs/zh-CN/display/format
@@ -1761,17 +1696,14 @@
      if (this.currentColumn.edit.url === undefined) {
        this.uploadUrl =
          "api/" +
          (this.url || "").replace("/api", "api").split("/")[1] +
          "/upload";
          "api/" + (this.url || "").replace("/api", "api").split("/")[1] + "/upload";
      } else {
        this.uploadUrl = this.currentColumn.edit.url;
      }
      this.uploadModel = true;
    },
    uploadAfter(result, files) {
      this.currentColumn.uploadAfter &&
        this.currentColumn.uploadAfter(result, files);
      this.currentColumn.uploadAfter && this.currentColumn.uploadAfter(result, files);
      return true;
    },
    saveUpload() {
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/extension/basicinfo/formula.js
@@ -1,9 +1,8 @@
let extension = {
    components: {//动态扩充组件或组件路径
        //表单header、content、footer对应位置扩充的组件
        gridHeader:'',
        gridBody: '',
        gridbody:'',
        gridFooter: '',
        //弹出框(修改、编辑、查看)header、content、footer对应位置扩充的组件
        modelHeader: '',
@@ -13,13 +12,7 @@
    buttons: [],//扩展的按钮
    methods: {//事件扩展
        onInit() {
            var detailImport = this.detailOptions.buttons.find(item=>item.value == 'import');
      if(detailImport){
        detailImport.onClick = () => {
          this.$refs.gridBody.open();
        }
      }
    },
        },
        onInited() {
        }
    }
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/Home.vue
@@ -1,42 +1,17 @@
<template>
  <div class="container">
    <!-- å·¦ä¾§åŒºåŸŸ - æ— ä»»ä½•标题标注 -->
    <!-- å·¦ä¾§åŒºåŸŸ - ä»…保留信号灯+成品/零件区域 -->
    <div class="left-area">
      <div class="left-top">
        <!-- æŒ‰é’®+信号 æ¨ªå‘排列容器 -->
        <div class="btn-signal-group">
          <!-- æŒ‰é’®ç»„ - ä¿®æ”¹ä¸ºä¸Šä¸‹æŽ’列 -->
          <div class="btn-group">
            <button
              class="btn"
              :class="isPLCStarted ? 'stop-btn' : 'start-btn'"
              @click="handleToggle"
        <div class="signal-status">
          <div class="signal-item" v-for="(signal, index) in signalStates" :key="index">
            <div
              class="signal-light"
              :class="signal ? 'signal-active' : 'signal-inactive'"
            >
              <i class="icon" :class="isPLCStarted ? 'icon-stop' : 'icon-start'"></i>
              {{ isPLCStarted ? "关闭" : "启动" }}
            </button>
            <button
              class="btn"
              :class="isPLCPaused ? 'resume-btn' : 'pause-btn'"
              @click="handlePauseToggle"
              :disabled="!isPLCStarted"
            >
              <i class="icon" :class="isPLCPaused ? 'icon-resume' : 'icon-pause'"></i>
              {{ isPLCPaused ? "恢复" : "暂停" }}
            </button>
          </div>
          <!-- ä¿¡å·ç¯ç»„ å ä¸¤ä¸ªæŒ‰é’®å®½åº¦ + æ•´ä½“放大 -->
          <div class="signal-status">
            <div class="signal-item" v-for="(signal, index) in signalStates" :key="index">
              <div
                class="signal-light"
                :class="signal ? 'signal-active' : 'signal-inactive'"
              >
                <div class="signal-light-inner"></div>
              </div>
              <span class="signal-label">{{ signalLabels[index] }}</span>
              <div class="signal-light-inner"></div>
            </div>
            <span class="signal-label">{{ signalLabels[index] }}</span>
          </div>
        </div>
      </div>
@@ -65,6 +40,7 @@
                class="part-checkbox"
                v-model="leftPartChecked[index]"
                @change="handlePartCheck(index)"
                :disabled="checkLoading[index]"
              />
              <span class="checkmark"></span>
              <span class="checkbox-label">{{
@@ -76,32 +52,19 @@
      </div>
    </div>
    <!-- å³ä¾§åŒºåŸŸ - æ— ä»»ä½•标题标注 ã€å·²åˆ é™¤æ¸…空+保存按钮】 -->
    <!-- å³ä¾§åŒºåŸŸ - ä¿ç•™åŽŸæœ‰å½•å…¥+提交+清除功能 -->
    <div class="right-area">
      <div class="right-top">
        <div class="form-row">
        <div class="form-row input-submit-row">
          <span class="label">录入框:</span>
          <!-- âœ… åªä¿ç•™çº¯å½•入框,清空/保存按钮已删除 -->
          <input type="text" class="input-box" v-model="rightTopInput" />
          <button class="btn save-btn submit-input-btn" @click="saveData">
            <i class="icon icon-submit"></i>提交
          </button>
        </div>
      </div>
      <div class="right-bottom">
        <div class="form-row tooling-board-row">
          <span class="short-label">工装板编号:</span>
          <input
            type="text"
            class="input-box short-input"
            v-model="toolingBoardNo"
            placeholder="请输入工装板编号"
          />
          <button class="btn clear-btn" @click="clearToolingBoardNo">
            <i class="icon icon-clear"></i>清除
          </button>
          <button class="btn save-btn" @click="saveToolingBoardNo">
            <i class="icon icon-submit"></i>提交
          </button>
        </div>
        <div class="parts-list">
          <div class="form-row part-item finished-product-row">
            <span class="label">成品编号:</span>
@@ -143,23 +106,19 @@
export default {
  setup() {
    // åŸºç¡€æ•°æ®å®šä¹‰ - 1:1精准对接后端 æˆå“ç¼–号+零件编号 æ— å†—余兼容
    const finishedProduct = ref(""); // å·¦ä¾§æˆå“ç¼–号(GetLeftInitialData接口返回)
    const finishedProductId = ref("");
    const rightTopInput = ref("");
    // åŸºç¡€æ•°æ®å®šä¹‰
    const finishedProduct = ref(""); // å·¦ä¾§æˆå“ç¼–号(接口返回)
    const finishedProductId = ref(""); // å·¦ä¾§æˆå“ID(接口返回)
    const rightTopInput = ref(""); // å³ä¾§æ ¸å¿ƒå½•入框
    const leftPartCodes = ref(Array(10).fill("")); // å·¦ä¾§é›¶ä»¶ç¼–号数组
    const rightPartCodes = ref(Array(10).fill("")); // å³ä¾§é›¶ä»¶ç¼–号数组
    const leftPartChecked = ref(Array(10).fill(false));
    const toolingBoardNo = ref("");
    const fillIndex = ref(-1);
    const leftPartIds = ref(Array(10).fill(""));
    const finishedProductCode = ref(""); // å³ä¾§æˆå“ç¼–号(工装板接口返回)
    const leftPartChecked = ref(Array(10).fill(false)); // å·¦ä¾§é›¶ä»¶å‹¾é€‰çŠ¶æ€
    const leftPartIds = ref(Array(10).fill("")); // å·¦ä¾§é›¶ä»¶ID(接口返回)
    const finishedProductCode = ref(""); // å³ä¾§æˆå“ç¼–号输入框
    const fillIndex = ref(-1); // å½•入框自动填充索引
    const checkLoading = ref(Array(10).fill(false)); // é›¶ä»¶å‹¾é€‰åŠ è½½é”
    // PLC状态
    const isPLCStarted = ref(false);
    const isPLCPaused = ref(false);
    // ä¿¡å·ç›¸å…³
    // ä¿¡å·ç¯ç›¸å…³
    const signalStates = ref([false, false, false, false, false]);
    const signalLabels = ref([
      "心跳信号",
@@ -169,34 +128,27 @@
      "故障信号",
    ]);
    // å®šæ—¶è½®è¯¢æ ¸å¿ƒé…ç½®
    // å®šæ—¶/防抖相关变量
    let pollingTimer = null;
    const pollingInterval = 5000;
    const pollingInterval = 5000; // ä¿¡å·ç¯è½®è¯¢é—´éš”5秒
    let checkDebounceTimer = null;
    let destroyDelayTimer = null;
    const destroyDelayTime = 500; // âœ… æ ¸å¿ƒï¼šå¡«å……+清空 éƒ½å»¶è¿Ÿ500毫秒
    let boardCodeDebounceTimer = null;
    // âœ… æ–°å¢žï¼šè‡ªåŠ¨æäº¤é˜²æŠ–å®šæ—¶å™¨ï¼Œé˜²æ­¢é‡å¤æäº¤
    const destroyDelayTime = 500; // å½•入框填充延迟500ms
    let autoSubmitDebounceTimer = null;
    // âœ… æ–°å¢žï¼šæäº¤é”ï¼Œé˜²æ­¢æ— å‹¾é€‰æ—¶é‡å¤è§¦å‘提交
    let submitLock = ref(false);
    let submitLock = ref(false); // æäº¤é”ï¼Œé˜²æ­¢é‡å¤æäº¤
    // âœ… âœ… âœ… æ ¸å¿ƒæ–°å¢ž1:计算属性 - å®žæ—¶ç»Ÿè®¡å·¦ä¾§å‹¾é€‰çš„复选框数量 (自动更新)
    // è®¡ç®—属性 - ç»Ÿè®¡æœ‰æ•ˆå‹¾é€‰/填充数量(过滤空值)
    const checkedCount = computed(() => {
      // ç»Ÿè®¡leftPartChecked数组中为true的数量
      return leftPartChecked.value.filter((checked) => checked === true).length;
    });
    // âœ… âœ… âœ… æ ¸å¿ƒæ–°å¢ž2:计算属性 - å®žæ—¶ç»Ÿè®¡å³ä¾§å·²å¡«å……的零件数量 (自动更新)
    const filledPartCount = computed(() => {
      // ç»Ÿè®¡rightPartCodes数组中有值(非空)的零件数量
      return rightPartCodes.value.filter((code) => code.trim() !== "").length;
    });
    // âœ… èŽ·å–å·¦ä¾§åˆå§‹æ•°æ® - å¯¹æŽ¥ /api/scanStation/GetLeftInitialData
    // èŽ·å–å·¦ä¾§åˆå§‹æ•°æ®ï¼ˆæˆå“+零件+勾选状态)
    const fetchLeftInitialData = async () => {
      try {
        console.log("正在获取左侧初始数据(成品编号+零件编号+勾选状态+零件ID)...");
        console.log("正在获取左侧初始数据...");
        const response = await axios.get("/api/scanStation/GetLeftInitialData", {
          timeout: 5000,
        });
@@ -206,14 +158,12 @@
          const data = resData.Data || resData.data || {};
          if (data.finishedProductId) finishedProductId.value = data.finishedProductId;
          if (data.finishedProduct) finishedProduct.value = data.finishedProduct;
          // èµ‹å€¼å·¦ä¾§é›¶ä»¶ç¼–号
          if (Array.isArray(data.leftPartCodes) && data.leftPartCodes.length >= 10) {
            for (let i = 0; i < 10; i++) {
              leftPartCodes.value[i] = data.leftPartCodes[i] || "";
              leftPartIds.value[i] = data.leftPartIds?.[i] || "";
            }
          }
          // èµ‹å€¼å‹¾é€‰çŠ¶æ€
          if (Array.isArray(data.leftPartChecked) && data.leftPartChecked.length >= 10) {
            for (let i = 0; i < 10; i++) {
              leftPartChecked.value[i] = !!data.leftPartChecked[i];
@@ -225,7 +175,7 @@
      }
    };
    // âœ… èŽ·å–ä¿¡å·+PLC状态
    // èŽ·å–ä¿¡å·ç¯çŠ¶æ€ï¼ˆå®šæ—¶è½®è¯¢ï¼‰
    const fetchSignalAndPLCStates = async () => {
      try {
        const response = await axios.get("/api/scanStation/GetSignalStates", {
@@ -237,63 +187,13 @@
          const data = resData.Data || resData.data || {};
          const newSignalStates = data.signalStates || [];
          for (let i = 0; i < 5; i++) signalStates.value[i] = newSignalStates[i] ?? false;
          const plcStatus = data.plcStatus || data.plc_status || {};
          isPLCStarted.value = plcStatus.isStarted ?? isPLCStarted.value;
          // âœ… ä¿®å¤BUG:原代码是 isPLCStarted.value å¯¼è‡´æš‚停状态赋值错误
          isPLCPaused.value = plcStatus.isPaused ?? isPLCPaused.value;
        }
      } catch (error) {
        console.error("获取信号和PLC状态失败:", error);
        console.error("获取信号状态失败:", error);
      }
    };
    // âœ… ã€æ ¸å¿ƒä¿®æ”¹ã€‘工装板查询接口 - æœ‰æ•°æ®å°±å¡«å……,无数据/失败 å®Œå…¨ä¿ç•™åŽŸæœ‰å†…å®¹ï¼Œä¸åšä»»ä½•æ¸…ç©ºæ“ä½œ
    const fetchProductAndPartsByBoardCode = async (boardCode) => {
      if (!boardCode.trim()) return;
      try {
        console.log(`工装板编号变更,请求数据:${boardCode}`);
        const response = await axios.get(
          "/api/boxingDetail/GetProductAndPartsByBoardNo",
          {
            params: { palletCode: boardCode.trim() },
            timeout: 5000,
          }
        );
        const resData = response.data;
        const isSuccess = resData.Status === true || resData.status === true;
        // âœ… åªæœ‰ã€æŽ¥å£æˆåŠŸ+有返回数据】的时候,才执行赋值覆盖
        if (isSuccess) {
          const data = resData.Data || resData.data || {};
          // æœ‰æˆå“ç¼–号就赋值,没有就不操作
          if (data.finishedProductCode) {
            finishedProductCode.value = data.finishedProductCode;
          }
          // æœ‰é›¶ä»¶åˆ—表就填充,没有就不操作
          const partsList = Array.isArray(data.partsList) ? data.partsList : [];
          if (partsList.length > 0) {
            for (let i = 0; i < 10; i++) {
              if (partsList[i]) {
                rightPartCodes.value[i] = partsList[i];
              }
            }
          }
          console.log("✅ å·¥è£…板查询成功,成品编号+零件编号填充完成");
        } else {
          // âœ… æ— å¯¹åº”数据:只弹提示,不清空任何内容
          alert(
            "获取数据失败:" + (resData.Message || resData.message || "无对应工装板数据")
          );
        }
      } catch (error) {
        // âœ… è¯·æ±‚失败:只弹提示,不清空任何内容
        alert("工装板数据请求失败,请检查网络或接口!");
        console.error("工装板接口请求失败:", error);
      } finally {
        boardCodeDebounceTimer = null;
      }
    };
    // å¯åЍ/停止定时轮询
    // å¯åЍ/停止信号灯轮询
    const startPolling = () => {
      if (pollingTimer) clearInterval(pollingTimer);
      fetchSignalAndPLCStates();
@@ -304,63 +204,13 @@
      pollingTimer = null;
    };
    // PLC启动/关闭逻辑
    const handleToggle = async () => {
      try {
        const response = await axios.get("/api/scanStation/StartPLC", {
          params: { isStop: isPLCStarted.value },
          timeout: 5000,
        });
        const resData = response.data;
        const isSuccess = resData.Status === true || resData.status === true;
        if (isSuccess) {
          isPLCStarted.value = !isPLCStarted.value;
          isPLCPaused.value = false;
          fetchSignalAndPLCStates();
        } else {
          alert(
            resData.Message ||
              resData.message ||
              (isPLCStarted.value ? "关闭失败" : "启动失败")
          );
        }
      } catch (error) {
        alert(isPLCStarted.value ? "关闭PLC失败" : "启动PLC失败");
        console.error("PLC启停失败:", error);
      }
    };
    // PLC暂停/恢复逻辑
    const handlePauseToggle = async () => {
      try {
        const response = await axios.get("/api/scanStation/PausePLC", {
          params: { isPause: !isPLCPaused.value },
          timeout: 5000,
        });
        const resData = response.data;
        const isSuccess = resData.Status === true || resData.status === true;
        if (isSuccess) {
          isPLCPaused.value = !isPLCPaused.value;
          fetchSignalAndPLCStates();
        } else {
          alert(
            resData.Message ||
              resData.message ||
              (isPLCPaused.value ? "恢复失败" : "暂停失败")
          );
        }
      } catch (error) {
        alert(isPLCPaused.value ? "恢复PLC失败" : "暂停PLC失败");
        console.error("PLC暂停恢复失败:", error);
      }
    };
    // é›¶ä»¶å‹¾é€‰çŠ¶æ€å˜æ›´å¤„ç†
    // å·¦ä¾§é›¶ä»¶å‹¾é€‰çŠ¶æ€å˜æ›´å¤„ç†ï¼ˆæ›´æ–°åŽç«¯çŠ¶æ€ï¼‰
    const handlePartCheck = async (index) => {
      const isChecked = leftPartChecked.value[index];
      const partCode = leftPartCodes.value[index];
      const partId = leftPartIds.value[index];
      // å‰ç½®æ ¡éªŒ
      if (!finishedProductId.value) {
        alert("成品ID不存在,无法更新零件扫码状态!");
        leftPartChecked.value[index] = !isChecked;
@@ -377,67 +227,60 @@
        return;
      }
      if (checkDebounceTimer) clearTimeout(checkDebounceTimer);
      checkDebounceTimer = setTimeout(async () => {
        try {
          const response = await axios.post(
            "/api/scanStation/UpdatePartScannedStatus",
            { Id: partId, IsScanned: isChecked ? 1 : 0 },
            { timeout: 5000 }
          );
          const resData = response.data;
          const isSuccess = resData.Status === true || resData.status === true;
          if (isSuccess) {
            console.log(`零件${index + 1}扫码状态更新成功`);
            // âœ… å‹¾é€‰çŠ¶æ€å˜åŒ–æ—¶ï¼Œé‡ç½®æäº¤é”
            submitLock.value = false;
          } else {
            leftPartChecked.value[index] = !isChecked;
            alert(
              `零件${index + 1}状态更新失败:${
                resData.Message || resData.message || "未知错误"
              }`
            );
          }
        } catch (error) {
      checkLoading.value[index] = true;
      try {
        const response = await axios.post(
          "/api/scanStation/UpdatePartScannedStatus",
          { Id: partId, IsScanned: isChecked ? 1 : 0 },
          { timeout: 5000 }
        );
        const resData = response.data;
        const isSuccess = resData.Status === true || resData.status === true;
        if (isSuccess) {
          console.log(`零件${index + 1}扫码状态更新成功`);
        } else {
          leftPartChecked.value[index] = !isChecked;
          alert(`零件${index + 1}状态更新请求失败,请检查网络或接口!`);
          console.error(`更新零件${index + 1}扫码状态失败:`, error);
        } finally {
          checkDebounceTimer = null;
          alert(
            `零件${index + 1}状态更新失败:${
              resData.Message || resData.message || "未知错误"
            }`
          );
        }
      }, 500);
      } catch (error) {
        leftPartChecked.value[index] = !isChecked;
        alert(`零件${index + 1}状态更新请求失败,请检查网络或接口!`);
        console.error(`更新零件${index + 1}扫码状态失败:`, error);
      } finally {
        checkLoading.value[index] = false;
        if (checkDebounceTimer) clearTimeout(checkDebounceTimer);
        checkDebounceTimer = null;
      }
    };
    // âœ… æ ¸å¿ƒä¿®æ”¹ï¼šå»¶è¿Ÿ0.5秒填充 + å»¶è¿Ÿ0.5秒清空 åŒæ­¥æ‰§è¡Œ æ— éœ€æ‰‹åŠ¨æŒ‰é’®
    // å³ä¾§å½•入框延迟填充逻辑(成品→零件依次填充)
    const fillContent = () => {
      if (!rightTopInput.value.trim()) return;
      const inputValue = rightTopInput.value.trim();
      // æ¸…除旧定时器,防止重复执行
      if (destroyDelayTimer) clearTimeout(destroyDelayTimer);
      // ç»Ÿä¸€å»¶è¿Ÿ500ms执行【填充+清空】
      destroyDelayTimer = setTimeout(() => {
        if (!toolingBoardNo.value.trim()) {
          toolingBoardNo.value = inputValue;
        } else if (!finishedProductCode.value.trim()) {
        if (!finishedProductCode.value.trim()) {
          finishedProductCode.value = inputValue;
        } else if (fillIndex.value < 10) {
          rightPartCodes.value[fillIndex.value] = inputValue;
          fillIndex.value++;
        } else {
          alert("工装板编号、成品编号和零件1-10已全部填充完成,无法继续录入!");
          alert("成品编号和零件1-10已全部填充完成,无法继续录入!");
          rightTopInput.value = "";
          destroyDelayTimer = null;
          return;
        }
        // å¡«å……完成后 è‡ªåŠ¨æ¸…ç©ºå½•å…¥æ¡†
        rightTopInput.value = "";
        destroyDelayTimer = null;
      }, destroyDelayTime);
    };
    // âœ… ç›‘听录入框内容变化自动触发填充逻辑
    // ç›‘听右侧录入框输入,触发自动填充
    watch(
      rightTopInput,
      (newVal) => {
@@ -446,116 +289,119 @@
      { immediate: false }
    );
    // ç›‘听工装板编号变化查询数据
    watch(
      toolingBoardNo,
      (newVal) => {
        const boardCode = newVal.trim();
        if (boardCode) {
          if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer);
          boardCodeDebounceTimer = setTimeout(
            () => fetchProductAndPartsByBoardCode(boardCode),
            300
          );
        } else {
          if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer);
        }
      },
      { immediate: false }
    );
    // å³ä¾§é¡µé¢æ“ä½œæ–¹æ³• (已删除清空/保存录入框的方法,无冗余)
    const clearToolingBoardNo = () => (toolingBoardNo.value = "");
    // å³ä¾§è¾“入框清除方法
    const clearRightPart = (index) => (rightPartCodes.value[index] = "");
    const clearFinishedProductCode = () => (finishedProductCode.value = "");
    // æäº¤å·¥è£…板数据到后端
    const saveToolingBoardNo = async () => {
      if (!toolingBoardNo.value.trim()) {
        alert("工装板编号不能为空,请输入后再提交!");
    // æ ¸å¿ƒä¿®æ”¹ï¼šæ¢å¤æˆå“ç¼–号必填校验,未填写直接提示并终止提交
    const saveData = async () => {
      // 1. æˆå“ç¼–号必填校验【核心新增】
      const productCode = finishedProductCode.value.trim();
      if (!productCode) {
        alert("请先填写成品编号,成品编号为必填项!");
        return;
      }
      if (!finishedProductCode.value.trim()) {
        alert("成品编号不能为空,请输入后再提交!");
        return;
      }
      // 2. æäº¤é”ï¼šé˜²æ­¢é‡å¤ç‚¹å‡»
      if (submitLock.value) return;
      submitLock.value = true;
      try {
        // 3. ä¼ å‚适配:后端Dto是大驼峰字段!必须严格匹配(FinishedProductCode/PartsList)
        const submitData = {
          toolingBoardNo: toolingBoardNo.value.trim(),
          finishedProductCode: finishedProductCode.value.trim(),
          partsList: rightPartCodes.value.map((item) => item.trim()),
          FinishedProductCode: productCode, // ç›´æŽ¥ä½¿ç”¨å·²æ ¡éªŒçš„非空值
          PartsList: rightPartCodes.value.map((item) => item.trim()),
        };
        console.log("✅ æäº¤å·¥è£…板数据:", submitData);
        console.log("📤 æäº¤åˆ°SaveToolingBoardNo的参数(匹配后端Dto):", submitData);
        // 4. è°ƒç”¨åŽç«¯æŽ¥å£ï¼Œå»¶é•¿è¶…时时间(后端有PLC交互,500ms休眠,设为10秒)
        const response = await axios.post(
          "/api/boxingDetail/SaveToolingBoardNo",
          submitData,
          { timeout: 5000 }
          { timeout: 10000 }
        );
        const resData = response.data;
        const isSuccess = resData.Status === true || resData.status === true;
        if (isSuccess) {
          alert("✅ æäº¤æˆåŠŸï¼");
          toolingBoardNo.value = "";
        console.log("📥 SaveToolingBoardNo接口返回:", resData);
        // 5. é€‚配后端返回格式:status为true表示成功,否则取message错误信息
        if (resData.status === true) {
          finishedProductCode.value = "";
          rightPartCodes.value = Array(10).fill("");
          rightTopInput.value = "";
          fillIndex.value = -1;
          // âœ… æäº¤æˆåŠŸåŽï¼Œé‡ç½®æäº¤é”
          submitLock.value = false;
        } else {
          alert("提交失败:" + (resData.Message || resData.message || "未知错误"));
          // ä¸šåŠ¡é”™è¯¯ï¼šç›´æŽ¥å±•ç¤ºåŽç«¯è¿”å›žçš„message(如物料错误、无配方)
          const errorMsg = resData.message || "提交失败,未知业务错误";
          alert(`提交失败:${errorMsg}`);
        }
      } catch (error) {
        alert("提交请求失败,请检查网络或接口!");
        console.error("提交接口失败:", error);
        // âœ… è¯·æ±‚失败也重置锁
        // 6. å¼‚常捕获:兼容后端未捕获异常(如PLC通讯异常、数组越界、500错误)
        let errorMsg = "提交请求异常!";
        if (error.code === "ECONNABORTED") {
          errorMsg = "提交请求超时!后端PLC交互/数据库操作耗时过长";
        } else if (error.response) {
          // æœåС噍500错误:后端抛出未捕获异常(如PLC未连接、零件不匹配)
          errorMsg = `服务器错误:${error.response.status} - ${error.response.statusText},请检查PLC通讯或配方配置`;
          console.error("❌ åŽç«¯æœåŠ¡å™¨é”™è¯¯è¯¦æƒ…ï¼š", error.response.data);
        } else if (error.request) {
          errorMsg = "网络异常!未收到后端响应,请检查接口地址和网络";
        } else {
          errorMsg = `请求错误:${error.message}`;
        }
        alert(errorMsg);
        console.error("❌ æäº¤æŽ¥å£å¼‚常详情:", error);
      } finally {
        // 7. é‡Šæ”¾æäº¤é”ï¼šæ— è®ºæˆåŠŸ/失败都要释放
        submitLock.value = false;
      }
    };
    // âœ… âœ… âœ… æ ¸å¿ƒå‡çº§ï¼šè‡ªåŠ¨æäº¤åˆ¤æ–­é€»è¾‘ - æ–°å¢žæ— å‹¾é€‰æ—¶æˆå“ç¼–号填充即提交
    // æ ¸å¿ƒä¿®æ”¹ï¼šè‡ªåŠ¨æäº¤é€»è¾‘åŒæ­¥å¢žåŠ æˆå“ç¼–å·å¿…å¡«æ ¡éªŒï¼ˆæ— æˆå“ç¼–å·ä¸è§¦å‘è‡ªåŠ¨æäº¤ï¼‰
    const checkAutoSubmit = () => {
      // é˜²æŠ–:防止短时间内多次触发提交
      if (autoSubmitDebounceTimer) clearTimeout(autoSubmitDebounceTimer);
      autoSubmitDebounceTimer = setTimeout(() => {
        const needCheckNum = checkedCount.value; // å·¦ä¾§å‹¾é€‰çš„æ•°é‡
        const filledNum = filledPartCount.value; // å³ä¾§å¡«å……的零件数量
        const hasBoardNo = toolingBoardNo.value.trim() !== ""; // å·¥è£…板有值
        const hasProductCode = finishedProductCode.value.trim() !== ""; // æˆå“æœ‰å€¼
        const needCheckNum = checkedCount.value; // å·¦ä¾§å‹¾é€‰é›¶ä»¶æ•°
        const filledNum = filledPartCount.value; // å³ä¾§æœ‰æ•ˆå¡«å……é›¶ä»¶æ•°
        const productCode = finishedProductCode.value.trim(); // æˆå“ç¼–号(去空格)
        const hasProductCode = !!productCode; // æˆå“ç¼–号是否有效【保留原逻辑,实际是必填校验】
        console.log(`✅ è‡ªåŠ¨æäº¤æ ¡éªŒï¼šå·¦ä¾§å‹¾é€‰${needCheckNum}个,右侧填充${filledNum}个`);
        console.log(
          `✅ è‡ªåŠ¨æäº¤æ ¡éªŒï¼šå‹¾é€‰${needCheckNum}个 | å¡«å……${filledNum}个 | æˆå“å·²å¡«${hasProductCode}`
        );
        // åˆ†æ”¯1:左侧有勾选 â†’ åŽŸæœ‰é€»è¾‘ï¼šé›¶ä»¶å¡«å……æ•°â‰¥å‹¾é€‰æ•° æ‰æäº¤
        if (needCheckNum > 0) {
          if (hasBoardNo && hasProductCode && filledNum >= needCheckNum) {
            console.log("✅ æ»¡è¶³å‹¾é€‰æ•°é‡æ¡ä»¶ï¼Œæ‰§è¡Œè‡ªåŠ¨æäº¤ï¼");
            saveToolingBoardNo();
        // å‰ç½®æ€»æ ¡éªŒï¼šæˆå“ç¼–号未填写,直接不触发任何自动提交【核心强化】
        if (!hasProductCode) {
          console.log("⚠️ æˆå“ç¼–号未填写,跳过自动提交");
          autoSubmitDebounceTimer = null;
          return;
        }
        // åœºæ™¯1:左侧无勾选 â†’ ä»…成品编号有效即提交(已满足hasProductCode)
        if (needCheckNum === 0) {
          if (!submitLock.value) {
            console.log("✅ æ— é›¶ä»¶å‹¾é€‰ï¼Œæˆå“å·²å¡«ï¼Œæ‰§è¡Œè‡ªåŠ¨æäº¤ï¼");
            saveData();
          }
        }
        // åˆ†æ”¯2:左侧无勾选 â†’ æ–°å¢žé€»è¾‘:工装板+成品都有值 å°±æäº¤ (加锁防重复)
        // åœºæ™¯2:左侧有勾选 â†’ æˆå“æœ‰æ•ˆ + å¡«å……æ•°=勾选数 æ‰æäº¤ï¼ˆå·²æ»¡è¶³hasProductCode)
        else {
          if (hasBoardNo && hasProductCode && !submitLock.value) {
            console.log("✅ å·¦ä¾§æ— å‹¾é€‰ï¼Œæˆå“ç¼–号填充完成,执行自动提交!");
            submitLock.value = true; // åŠ é”é˜²æ­¢é‡å¤æäº¤
            saveToolingBoardNo();
          if (filledNum === needCheckNum && !submitLock.value) {
            console.log("✅ é›¶ä»¶æ•°é‡åŒ¹é…ï¼Œæˆå“å·²å¡«ï¼Œæ‰§è¡Œè‡ªåŠ¨æäº¤ï¼");
            saveData();
          }
        }
        autoSubmitDebounceTimer = null;
      }, 300);
      }, 300); // 300ms防抖,避免输入频繁触发
    };
    // âœ… âœ… âœ… æ ¸å¿ƒæ–°å¢ž4:监听关键数据变化,触发自动提交校验
    watch(
      [checkedCount, filledPartCount, toolingBoardNo, finishedProductCode],
      () => {
        checkAutoSubmit();
      },
      { deep: true, immediate: false }
    );
    // ç›‘听自动提交相关数据变化,触发校验
    watch([checkedCount, filledPartCount, finishedProductCode], () => checkAutoSubmit(), {
      deep: true,
      immediate: false,
    });
    // è‡ªåŠ¨æ£€æµ‹å¡«å……ç´¢å¼•é€»è¾‘
    // è‡ªåŠ¨æ£€æµ‹å¡«å……ç´¢å¼•ï¼ˆæˆå“å¡«å®ŒåŽï¼ŒæŒ‡å‘ç¬¬ä¸€ä¸ªç©ºé›¶ä»¶æ¡†ï¼‰
    const detectFillIndex = () => {
      if (!toolingBoardNo.value.trim() || !finishedProductCode.value.trim()) {
      if (!finishedProductCode.value.trim()) {
        fillIndex.value = -1;
        return;
      }
@@ -568,49 +414,40 @@
      fillIndex.value = 10;
    };
    watch(
      [toolingBoardNo, finishedProductCode, () => [...rightPartCodes.value]],
      detectFillIndex,
      {
        immediate: true,
        deep: true,
      }
    );
    // ç›‘听成品/零件输入,更新填充索引
    watch([finishedProductCode, () => [...rightPartCodes.value]], detectFillIndex, {
      immediate: true,
      deep: true,
    });
    // é¡µé¢æŒ‚è½½/卸载生命周期
    // ç”Ÿå‘½å‘¨æœŸï¼šæŒ‚载时加载初始数据+启动轮询
    onMounted(async () => {
      await fetchLeftInitialData();
      startPolling();
      detectFillIndex();
    });
    // ç”Ÿå‘½å‘¨æœŸï¼šå¸è½½æ—¶æ¸…除所有定时器/防抖,防止内存泄漏
    onUnmounted(() => {
      stopPolling();
      if (checkDebounceTimer) clearTimeout(checkDebounceTimer);
      if (destroyDelayTimer) clearTimeout(destroyDelayTimer);
      if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer);
      if (autoSubmitDebounceTimer) clearTimeout(autoSubmitDebounceTimer);
      [checkDebounceTimer, destroyDelayTimer, autoSubmitDebounceTimer].forEach(
        (t) => t && clearTimeout(t)
      );
    });
    // æš´éœ²æ¨¡æ¿æ‰€éœ€å±žæ€§/方法
    return {
      finishedProduct,
      finishedProductId,
      rightTopInput,
      leftPartCodes,
      rightPartCodes,
      leftPartChecked,
      leftPartIds,
      toolingBoardNo,
      isPLCStarted,
      isPLCPaused,
      signalStates,
      signalLabels,
      finishedProductCode,
      handleToggle,
      handlePauseToggle,
      checkLoading,
      handlePartCheck,
      clearToolingBoardNo,
      saveToolingBoardNo,
      saveData,
      clearRightPart,
      clearFinishedProductCode,
    };
@@ -619,12 +456,12 @@
</script>
<style scoped>
/* åŸºç¡€æ ·å¼é‡ç½®ä¸Žå…¨å±€æ ·å¼ */
/* åŸºç¡€æ ·å¼é‡ç½® */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Microsoft Yahei", "PingFang SC", "Inter", sans-serif;
  font-family: "Microsoft Yahei", "PingFang SC", sans-serif;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
@@ -639,18 +476,17 @@
  font-size: 14px;
}
/* å®¹å™¨æ ·å¼ - æ”¾å¤§ é—´è·åР宽 */
/* ä¸»å®¹å™¨ */
.container {
  display: flex;
  width: 100%;
  height: 100vh;
  margin: 0;
  gap: 15px;
  padding: 15px;
  overflow: hidden;
}
/* é¢æ¿é€šç”¨æ ·å¼ - ç»Ÿä¸€å†…边距 ç¡®ä¿å·¦å³å¯¹é½ */
/* å·¦å³åŒºåŸŸé€šç”¨æ ·å¼ */
.left-area,
.right-area {
  flex: 1;
@@ -666,36 +502,26 @@
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
/* æŒ‰é’®+信号 æ¨ªå‘排列容器 - æ ¸å¿ƒå¸ƒå±€ */
.btn-signal-group {
/* å·¦ä¾§é¡¶éƒ¨-信号灯区域 */
.left-top {
  background: #f8fafc;
  padding: 20px 15px;
  border-radius: 12px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 20px;
  width: 100%;
}
.btn-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex-shrink: 0;
  justify-content: center;
}
.signal-status {
  display: flex;
  justify-content: flex-start;
  justify-content: center;
  align-items: center;
  gap: 18px;
  flex-shrink: 0;
  padding: 0;
}
.left-top {
  background: #f8fafc;
  padding: 15px;
  border-radius: 12px;
  gap: 25px;
  flex-shrink: 0;
  width: 100%;
}
/* ä¸Šä¸‹åŒºåŸŸé€šç”¨ */
.left-bottom,
.right-bottom {
  display: flex;
@@ -704,7 +530,6 @@
  flex: 1;
  overflow: hidden !important;
}
.right-top {
  padding: 15px;
  background: #f8fafc;
@@ -712,7 +537,7 @@
  flex-shrink: 0;
}
/* è¡¨å•行样式 - ç»Ÿä¸€é«˜åº¦å’Œé—´è· ç¡®ä¿å·¦å³å¯¹é½ */
/* è¡¨å•行通用样式 */
.form-row {
  display: flex;
  align-items: center;
@@ -726,31 +551,46 @@
  flex-shrink: 0;
  width: 100%;
}
.input-submit-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;
  padding: 6px 10px;
  border-radius: 8px;
  transition: all 0.2s ease;
  height: 48px;
  line-height: 48px;
  flex-shrink: 0;
  width: 100%;
}
.form-row:hover {
  background: #f8fafc;
}
.finished-product-row {
/* æˆå“ç¼–号行样式 */
.right-bottom .finished-product-row {
  margin-top: 16px;
  background: #eff6ff;
  border-left: 4px solid #3b82f6;
  padding-top: 2px;
  padding-bottom: 2px;
}
.left-bottom .finished-product-row {
  background: #eff6ff;
  border-left: 4px solid #3b82f6;
}
.tooling-board-row {
  background: #f0fdf4;
  border-left: 4px solid #22c55e;
}
/* é›¶ä»¶é¡¹æ ·å¼ */
.part-item {
  border-bottom: 1px solid #f1f5f9;
  margin-bottom: 3px;
}
.part-item:last-child {
  border-bottom: none;
}
/* æ ‡ç­¾æ ·å¼ - ç»Ÿä¸€å®½åº¦ ç¡®ä¿å·¦å³å¯¹é½ */
/* æ ‡ç­¾æ ·å¼ */
.label {
  width: 90px;
  text-align: right;
@@ -760,16 +600,7 @@
  flex-shrink: 0;
}
.short-label {
  width: 110px;
  text-align: right;
  color: #334155;
  font-size: 15px;
  font-weight: 600;
  flex-shrink: 0;
}
/* è¾“入框样式 - ç»Ÿä¸€å°ºå¯¸ ç¡®ä¿å·¦å³å¯¹é½ */
/* è¾“入框样式 */
.input-box {
  flex: 1;
  min-width: 100px;
@@ -782,29 +613,21 @@
  transition: all 0.2s ease;
  background-color: #ffffff;
}
.short-input {
  width: 150px !important;
  flex: none !important;
}
.input-box:focus {
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
}
.input-box:disabled {
  background-color: #f1f5f9;
  color: #64748b;
  cursor: not-allowed;
}
.input-box::placeholder {
  color: #94a3b8;
  font-size: 14px;
}
/* æŒ‰é’®æ ·å¼ - å›ºå®šå®½åº¦ ä¸å˜ */
/* æŒ‰é’®é€šç”¨æ ·å¼ */
.btn {
  width: 120px;
  height: 42px;
@@ -823,14 +646,23 @@
  position: relative;
  overflow: hidden;
}
.submit-input-btn {
  width: 110px !important;
  height: 42px !important;
  flex: none !important;
  padding: 0 15px !important;
  font-size: 15px !important;
}
.submit-input-btn .icon {
  width: 20px !important;
  height: 20px !important;
}
.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}
.btn::after {
  content: "";
  position: absolute;
@@ -841,12 +673,11 @@
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.5s ease;
}
.btn:hover::after {
  left: 100%;
}
/* å›¾æ ‡æ ·å¼ - å›¾æ ‡æ”¾å¤§ */
/* å›¾æ ‡æ ·å¼ */
.icon {
  display: inline-block;
  width: 18px;
@@ -855,68 +686,14 @@
  background-repeat: no-repeat;
  background-position: center;
}
.icon-start {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E");
}
.icon-stop {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 6h12v12H6z'/%3E%3C/svg%3E");
}
.icon-pause {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 19h4V5H6v14zm8-14v14h4V5h-4z'/%3E%3C/svg%3E");
}
.icon-resume {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M11 5L6 9H2v6h4l5 4V5zm7 0v14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E");
}
.icon-clear {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E");
}
.icon-submit {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M2.01 21L15 13.4 23 21V5H2.01V21zM17 15l-5-5-5 5V7h10v8z'/%3E%3C/svg%3E");
}
/* æŒ‰é’®ç±»åž‹æ ·å¼ - ä¸å˜ */
.start-btn {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  color: #fff;
}
.start-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(16, 185, 129, 0.2);
}
.stop-btn {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  color: #fff;
}
.stop-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(239, 68, 68, 0.2);
}
.pause-btn {
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
  color: #fff;
}
.pause-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(245, 158, 11, 0.2);
}
.resume-btn {
  background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
  color: #fff;
}
.resume-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(139, 92, 246, 0.2);
}
/* æŒ‰é’®ä¸»é¢˜æ ·å¼ */
.clear-btn {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  color: #fff;
@@ -926,7 +703,6 @@
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(239, 68, 68, 0.15);
}
.save-btn {
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
  color: #fff;
@@ -937,7 +713,7 @@
  box-shadow: 0 4px 8px rgba(59, 130, 246, 0.15);
}
/* ä¿¡å·ç¯æ ·å¼ é†’目放大 */
/* ä¿¡å·ç¯æ ·å¼ */
.signal-item {
  display: flex;
  flex-direction: column;
@@ -949,9 +725,6 @@
  font-size: 14px;
  color: #334155;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  text-align: center;
  font-weight: 600;
}
@@ -994,7 +767,7 @@
  }
}
/* è‡ªå®šä¹‰å¤é€‰æ¡†æ ·å¼ - æ”¾å¤§ ç‚¹å‡»åŒºåŸŸæ›´å¤§ */
/* è‡ªå®šä¹‰å¤é€‰æ¡†æ ·å¼ */
.checkbox-container {
  display: flex;
  align-items: center;
@@ -1006,6 +779,10 @@
}
.part-checkbox {
  display: none;
}
.checkbox-container:has(.part-checkbox:disabled) {
  opacity: 0.6;
  cursor: not-allowed;
}
.checkmark {
  width: 22px;
@@ -1052,25 +829,21 @@
    width: 100%;
    flex: none;
  }
  .btn-signal-group {
    flex-direction: column;
    align-items: flex-start;
  }
  .signal-status {
    width: 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
    justify-content: center;
  }
}
@media (max-width: 768px) {
  .form-row {
  .form-row,
  .input-submit-row {
    flex-direction: column;
    align-items: flex-start;
    height: auto;
    line-height: normal;
  }
  .label,
  .short-label {
  .label {
    width: 100%;
    text-align: left;
    margin-bottom: 6px;
@@ -1078,17 +851,13 @@
  .input-box {
    width: 100%;
  }
  .short-input {
  .btn,
  .submit-input-btn {
    width: 100% !important;
  }
  .btn {
    width: 100%;
    margin-top: 6px;
  }
  .btn-group {
    flex-direction: column;
    gap: 10px;
    width: 100%;
  .right-bottom .finished-product-row {
    margin-top: 0 !important;
  }
}
</style>
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/boxing.vue
@@ -28,11 +28,13 @@
      sortName: "createDate",
    });
    // ç¼–辑表单字段 - æ–°å¢žboxingNo
    const editFormFields = ref({
      id: "",
      palletCode: "",
      productCode: "",
      productName: "",
      boxingNo: "", // æµæ°´å·å­—段
    });
    const editFormOptions = ref([
      [
@@ -41,7 +43,6 @@
          field: "palletCode",
          type: "input",
          width: 200,
          link: true,
          require: true,
        },
        {
@@ -54,6 +55,14 @@
        {
          title: "成品名称",
          field: "productName",
          type: "input",
          width: 200,
          require: true,
        },
        // æ–°å¢žï¼šæµæ°´å·ç¼–辑项(和实体一致非空,故设require: true)
        {
          title: "流水号",
          field: "boxingNo",
          type: "input",
          width: 200,
          require: true,
@@ -71,10 +80,12 @@
      ],
    ]);
    // æŸ¥è¯¢è¡¨å•字段 - æ–°å¢žboxingNo
    const searchFormFields = ref({
      palletCode: "",
      productCode: "",
      productName: "",
      boxingNo: "", // æµæ°´å·æŸ¥è¯¢å­—段
      creater: "",
      createDate: "",
    });
@@ -84,6 +95,8 @@
        { title: "工装板编号", field: "palletCode", type: "like" },
        { title: "成品编号", field: "productCode", type: "like" },
        { title: "成品名称", field: "productName", type: "like" },
        // æ–°å¢žï¼šæµæ°´å·æŸ¥è¯¢é¡¹ï¼ˆæ¨¡ç³ŠæŸ¥è¯¢like,和其他编号保持一致)
        { title: "流水号", field: "boxingNo", type: "like" },
      ],
      [
        { title: "创建人", field: "creater", type: "like" },
@@ -91,6 +104,7 @@
      ],
    ]);
    // è¡¨æ ¼åˆ—配置 - æ–°å¢žboxingNo列
    const columns = ref([
      {
        field: "id",
@@ -120,6 +134,14 @@
      {
        field: "productName",
        title: "成品名称",
        type: "string",
        width: 200,
        align: "left",
      },
      // æ–°å¢žï¼šæµæ°´å·è¡¨æ ¼åˆ—(宽度和其他编号保持200,可根据需求调整)
      {
        field: "boxingNo",
        title: "流水号",
        type: "string",
        width: 200,
        align: "left",
@@ -164,7 +186,7 @@
    const detail = ref({
      cnName: "组盘详细信息",
      table: "boxingDetail",
      table: "DoxingDetail",
      columns: [
        {
          field: "boxingId",
@@ -180,6 +202,7 @@
          field: "componentCode",
          title: "零件编号",
          type: "string",
          edit: { type: "" },
          width: 200,
          align: "left",
        },
@@ -187,6 +210,7 @@
          field: "componentName",
          title: "零件名称",
          type: "string",
          edit: { type: "" },
          width: 200,
          align: "left",
        },
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/formula.vue
@@ -28,25 +28,30 @@
      sortName: "createDate",
    });
    // ç¼–辑表单字段 - æ–°å¢žpressFastenTorque(压装位紧固扭矩)
    const editFormFields = ref({
      id: "",
      productCode: "",
      productName: "",
      productLength: 0,
      productWidth: 0,
      productHeight: 0,
      screwDownsetDistance: 0,
      screwTorqueOutput: 0,
      dintAutoScrewOn: 0,
      xDirectionDistance1: 0,
      yDirectionHeight1: 0,
      xDirectionDistance2: 0,
      yDirectionHeight2: 0,
      xDirectionDistance3: 0,
      yDirectionHeight3: 0,
      productLength: "",
      productWidth: "",
      productHeight: "",
      pressNoTighten: "",
      screwDownsetDistance: "",
      screwTorqueOutput: "",
      pressFastenTorque: "", // ã€æ–°å¢žã€‘压装位紧固扭矩
      dintAutoScrewOn: "",
      p0P1Width: "",
      p0P2Width: "",
      p0P3Width: "",
      p1P3Height: "",
      p2P3Height: "",
      productImagePath: "",
    });
    // ç¼–辑表单配置-新增压装位紧固扭矩,布局适配原有紧凑性
    const editFormOptions = ref([
      // ç¬¬ä¸€è¡Œï¼šåŸºç¡€æ ‡è¯†
      [
        {
          title: "成品编号",
@@ -63,16 +68,142 @@
          require: true,
        },
        {
          title: "主键ID",
          field: "id",
          title: "拧紧程序号",
          field: "dintAutoScrewOn",
          type: "input",
          width: 100,
          hidden: true,
          readonly: true,
          inputType: "number",
          width: 180,
          placeholder: "请输入整数",
        },
        {
          title: "产品长度",
          field: "productLength",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
      ],
      [
        {
          title: "产品宽度",
          field: "productWidth",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "产品高度",
          field: "productHeight",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "压装位不拧紧",
          field: "pressNoTighten",
          type: "select",
          width: 120,
          align: "center",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "保压压力",
          field: "screwDownsetDistance",
          type: "input",
          inputType: "number",
          width: 150,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
      ],
      [
        {
          title: "中心高度",
          field: "screwTorqueOutput",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "紧固扭矩",
          field: "pressFastenTorque",
          type: "input",
          inputType: "number",
          width: 150,
          placeholder: "保留2位小数,默认0.00",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "P0P1宽度",
          field: "p0P1Width",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "P0P2宽度",
          field: "p0P2Width",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
      ],
      // ç¬¬å››è¡Œï¼šP系列高度 + äº§å“å›¾ç‰‡è·¯å¾„
      [
        {
          title: "P0P3宽度",
          field: "p0P3Width",
          type: "input",
          inputType: "number",
          width: 120,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "P1P3高度",
          field: "p1P3Height",
          type: "input",
          inputType: "number",
          width: 150,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "P2P3高度",
          field: "p2P3Height",
          type: "input",
          inputType: "number",
          width: 150,
          placeholder: "保留2位小数",
          attrs: { step: 0.01, min: 0 },
        },
        {
          title: "产品图片路径",
          field: "productImagePath",
          type: "textarea",
          width: 400,
          rows: 2,
          placeholder: "请输入图片完整路径,支持500字符以内",
        },
      ],
    ]);
    // æœç´¢è¡¨å•字段 - æ— éœ€ä¿®æ”¹
    const searchFormFields = ref({
      productCode: "",
      productName: "",
@@ -80,89 +211,202 @@
      createDate: "",
    });
    // æœç´¢è¡¨å•配置 - æ— éœ€ä¿®æ”¹
    const searchFormOptions = ref([
      [
        { title: "成品编号", field: "productCode", type: "like" },
        { title: "成品名称", field: "productName", type: "like" },
        { title: "成品编号", field: "productCode", type: "like", width: 200 },
        { title: "成品名称", field: "productName", type: "like", width: 200 },
      ],
      [
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        { title: "创建人", field: "creater", type: "like", width: 200 },
        { title: "创建时间", field: "createDate", type: "datetime", width: 380 },
      ],
    ]);
    // è¡¨æ ¼åˆ—配置 - æ–°å¢žåŽ‹è£…ä½ç´§å›ºæ‰­çŸ©åˆ—
    const columns = ref([
      {
        field: "id",
        title: "序号",
        type: "int",
        width: 90,
        width: 80,
        hidden: true,
        readonly: true,
        require: true,
        align: "left",
        align: "center",
      },
      {
        field: "productCode",
        title: "成品编号",
        type: "string",
        link: true,
        width: 200,
        width: 150,
        align: "left",
      },
      {
        field: "productName",
        title: "成品名称",
        type: "string",
        width: 200,
        width: 150,
        align: "left",
      },
      {
        field: "productLength",
        title: "产品长度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "productWidth",
        title: "产品宽度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "productHeight",
        title: "产品高度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "pressNoTighten",
        title: "压装位不拧紧",
        type: "select",
        width: 100,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "screwDownsetDistance",
        title: "保压压力",
        type: "decimal",
        width: 110,
        align: "center",
      },
      {
        field: "screwTorqueOutput",
        title: "中心高度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "pressFastenTorque", // ã€æ–°å¢žã€‘表格列
        title: "压装位紧固扭矩",
        type: "decimal",
        width: 120,
        align: "center",
      },
      {
        field: "dintAutoScrewOn",
        title: "拧紧程序号",
        type: "int",
        width: 100,
        align: "center",
      },
      // P系列宽度
      {
        field: "p0P1Width",
        title: "P0P1宽度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "p0P2Width",
        title: "P0P2宽度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "p0P3Width",
        title: "P0P3宽度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      // P系列高度
      {
        field: "p1P3Height",
        title: "P1P3高度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "p2P3Height",
        title: "P2P3高度",
        type: "decimal",
        width: 90,
        align: "center",
      },
      {
        field: "productImagePath",
        title: "图片路径",
        type: "string",
        width: 200,
        align: "left",
        overflow: "ellipsis",
      },
      // å…¬å…±å­—段
      {
        field: "creater",
        title: "创建人",
        type: "string",
        width: 90,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "createDate",
        title: "创建时间",
        type: "datetime",
        width: 150,
        align: "left",
        width: 160,
        align: "center",
      },
      {
        field: "modifier",
        title: "修改人",
        type: "string",
        width: 100,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
        align: "center",
      },
    ]);
    // é…æ–¹æ˜Žç»†é…ç½® - æ— éœ€ä¿®æ”¹
    const detail = ref({
      cnName: "零件详细信息",
      table: "componentDetail",
      cnName: "配方信息详情",
      table: "FormulaDetail",
      columns: [
        {
          field: "formulaId",
          title: "ID",
          title: "配方ID",
          type: "int",
          width: 90,
          hidden: true,
          readonly: true,
          require: true,
          align: "left",
          align: "center",
        },
        {
          field: "componentCode",
          title: "零件编号",
          type: "string",
          edit: { type: "" },
          width: 120,
          require: true,
          align: "left",
@@ -171,14 +415,24 @@
          field: "componentName",
          title: "零件名称",
          type: "string",
          edit: { type: "" },
          width: 150,
          require: true,
          align: "left",
        },
        {
          field: "supplierCode",
          title: "供方代码",
          type: "string",
          edit: { type: "" },
          width: 150,
          align: "left",
        },
        {
          title: "是否扫码",
          field: "isScanned",
          type: "select",
          width: 100,
          align: "center",
          bind: {
            key: "value",
            data: [
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/formulaDetail.vue
@@ -19,6 +19,7 @@
export default defineComponent({
  setup() {
    // è¡¨æ ¼åŸºç¡€é…ç½®
    const table = ref({
      key: "id",
      footer: "Foots",
@@ -28,13 +29,17 @@
      sortName: "createDate",
    });
    // ç¼–辑表单绑定字段(新增supplierCode)
    const editFormFields = ref({
      id: "",
      formulaId: "",
      componentCode: "",
      componentName: "",
      supplierCode: "",
      isScanned: "",
    });
    // ç¼–辑表单配置项(新增供方代码输入项)
    const editFormOptions = ref([
      [
        {
@@ -59,6 +64,12 @@
          require: true,
        },
        {
          title: "供方代码",
          field: "supplierCode",
          type: "input",
          width: 200,
        },
        {
          title: "是否扫码",
          field: "isScanned",
          type: "select",
@@ -80,19 +91,24 @@
      ],
    ]);
    // æœç´¢è¡¨å•绑定字段(新增supplierCode)
    const searchFormFields = ref({
      formulaId: "",
      componentCode: "",
      componentName: "",
      supplierCode: "",
      creater: "",
      createDate: "",
      isScanned: "",
    });
    // æœç´¢è¡¨å•配置项(新增供方代码模糊搜索)
    const searchFormOptions = ref([
      [
        { title: "配方信息主键", field: "formulaId", type: "int" },
        { title: "零件编号", field: "componentCode", type: "like" },
        { title: "零件名称", field: "componentName", type: "like" },
        { title: "供方代码", field: "supplierCode", type: "like" },
        {
          title: "是否扫码",
          field: "isScanned",
@@ -109,6 +125,7 @@
      ],
    ]);
    // è¡¨æ ¼åˆ—配置(新增供方代码列)
    const columns = ref([
      {
        field: "id",
@@ -137,6 +154,13 @@
      {
        field: "componentName",
        title: "零件名称",
        type: "string",
        width: 200,
        align: "left",
      },
      {
        field: "supplierCode",
        title: "供方代码",
        type: "string",
        width: 200,
        align: "left",
@@ -183,6 +207,7 @@
      },
    ]);
    // è¯¦æƒ…页配置(暂未使用,保持原有)
    const detail = ref({
      cnName: "",
      table: "",
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/processInfo.vue
@@ -19,328 +19,526 @@
export default defineComponent({
  setup() {
    // è¡¨æ ¼åŸºç¡€é…ç½®
    const table = ref({
      key: "id",
      footer: "Foots",
      cnName: "加工信息",
      name: "processInfo",
      url: "/processInfo/",
      sortName: "createDate",
      url: "/processInfo/",
      sortName: "createDate",
      sortOrder: "desc", // æ–°å¢žï¼šåˆ›å»ºæ—¶é—´é»˜è®¤å€’序,符合常规使用
    });
    // ç¼–辑表单字段 - å®Œå…¨åŒ¹é…åŽç«¯Dt_ProcessInfo实体
    // æ–°å¢žï¼špressPressure(压装位下压压力),补全所有后端字段
    const editFormFields = ref({
      id: "",
      palletCode: "",
      palletCode: "",
      productCode: "",
      productName: "",
      componentQty: "",
      torsioValue: "",
      torsioValueStandard: "",
      stiffnessValue: "",
      stiffnessValueStandard: "",
      testResult: "",
      pressHeight: "",
      screwTorque: "",
      screwAngle: "",
      height1: "",
      height2: "",
      height3: "",
      productSn: "", // æµæ°´å·
      pressTightenNg: "", // åŽ‹è£…æ‹§ç´§_拧紧NG
      pressTightenOk: "", // åŽ‹è£…æ‹§ç´§_拧紧OK
      pressTightenUnfinished: "", // åŽ‹è£…æ‹§ç´§_本次加工未完成
      checkUnfinished: "", // æ£€æµ‹_本次检测未完成
      //componentQty: "", // é›¶ä»¶æ•°é‡
      // torsioValue: "", // æ‰­åЛ值
      // torsioValueStandard: "", // æ‰­åŠ›å€¼æ ‡å‡†
      // stiffnessValue: "", // åˆšåº¦å€¼
      // stiffnessValueStandard: "", // åˆšåº¦å€¼æ ‡å‡†
      // testResult: "", // æµ‹è¯•结果
      pressHeight: "", // åŽ‹è£…ä½ä¸‹åŽ‹é«˜åº¦
      screwTorque: "", // åŽ‹è£…ä½æ‹§ç´§æ‰­åŠ›
      screwAngle: "", // åŽ‹è£…ä½æ‹§ç´§è§’åº¦
      pressPressure: "", // ã€æ–°å¢žã€‘压装位下压压力(匹配后端实体)
      height1: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦1
      height2: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦2
      height3: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦3
    });
    // ç¼–辑表单配置-【取消分类,均匀排布】,保留所有原有校验/默认值/属性
    const editFormOptions = ref([
      // ç¬¬ä¸€è¡Œï¼š5个字段(基础标识+1个状态),宽度协调
      [
        {
          title: "工装板编号",
          field: "palletCode",
          type: "input",
          width: 200,
          require: true
          width: 160,
          require: true,
          placeholder: "请输入工装板编号",
        },
        {
          title: "成品编号",
          field: "productCode",
          type: "input",
          width: 200,
          require: true
          width: 160,
          require: true,
          placeholder: "请输入成品编号",
        },
        {
          title: "成品名称",
          field: "productName",
          type: "input",
          width: 200,
          require: true
        }
          width: 160,
          require: true,
          placeholder: "请输入成品名称",
        },
        {
          title: "流水号",
          field: "productSn",
          type: "input",
          width: 180,
          require: false,
          placeholder: "请输入产品流水号",
        },
      ],
      [
        {
          title: "零件数量",
          field: "componentQty",
          type: "input",
          width: 200,
          require: true
          title: "拧紧NG",
          field: "pressTightenNg",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "扭力值",
          field: "torsioValue",
          type: "input",
          width: 200,
          require: false
          title: "拧紧OK",
          field: "pressTightenOk",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "扭力值标准",
          field: "torsioValueStandard",
          type: "input",
          width: 200,
          require: false
        }
      ],
      [
        {
          title: "刚度值",
          field: "stiffnessValue",
          type: "input",
          width: 200,
          require: false
          title: "拧紧未完成",
          field: "pressTightenUnfinished",
          type: "select",
          width: 170,
          align: "center",
          defaultValue: "0",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "刚度值标准",
          field: "stiffnessValueStandard",
          type: "input",
          width: 200,
          require: false
          title: "检测未完成",
          field: "checkUnfinished",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "测试结果",
          field: "testResult",
          type: "input",
          width: 200,
          require: false
        }
      ],
      [
        {
          title: "压装位下压检测高度",
          field: "pressHeight",
          type: "input",
          width: 200,
          require: false
        },
        {
          title: "压装位拧紧检测扭力",
          field: "screwTorque",
          type: "input",
          width: 200,
          require: false
        },
        {
          title: "压装位拧紧检测角度",
          field: "screwAngle",
          type: "input",
          width: 200,
          require: false
        }
      ],
      [
        {
          title: "拧紧位检测高度1",
          field: "height1",
          type: "input",
          width: 200,
          require: false
        },
        {
          title: "拧紧位检测高度2",
          field: "height2",
          type: "input",
          width: 200,
          require: false
        },
        {
          title: "拧紧位检测高度3",
          field: "height3",
          type: "input",
          width: 200,
          require: false
        }
      ],
      [
        // {
        //   title: "零件数量",
        //   field: "componentQty",
        //   type: "input",
        //   inputType: "number",
        //   width: 140,
        //   require: false,
        //   attrs: { min: 0, step: 1 },
        //   placeholder: "请输入正整数",
        // },
        {
          title: "主键ID",
          field: "id",
          type: "input",
          width: 100,
          hidden: true,
          readonly: true
        }
      ]
          readonly: true,
        },
      ],
      // // ç¬¬ä¸‰è¡Œï¼š5个字段(扭力/刚度相关+测试结果),小数校验
      // [
      //   {
      //     title: "扭力值",
      //     field: "torsioValue",
      //     type: "input",
      //     inputType: "number",
      //     width: 140,
      //     require: false,
      //     attrs: { step: 0.01, min: 0 },
      //     placeholder: "保留2位小数",
      //   },
      //   {
      //     title: "扭力值标准",
      //     field: "torsioValueStandard",
      //     type: "input",
      //     inputType: "number",
      //     width: 160,
      //     require: false,
      //     attrs: { step: 0.01, min: 0 },
      //     placeholder: "保留2位小数",
      //   },
      //   {
      //     title: "刚度值",
      //     field: "stiffnessValue",
      //     type: "input",
      //     inputType: "number",
      //     width: 140,
      //     require: false,
      //     attrs: { step: 0.01, min: 0 },
      //     placeholder: "保留2位小数",
      //   },
      //   {
      //     title: "刚度值标准",
      //     field: "stiffnessValueStandard",
      //     type: "input",
      //     inputType: "number",
      //     width: 160,
      //     require: false,
      //     attrs: { step: 0.01, min: 0 },
      //     placeholder: "保留2位小数",
      //   },
      //   {
      //     title: "测试结果",
      //     field: "testResult",
      //     type: "input",
      //     inputType: "number",
      //     width: 140,
      //     require: false,
      //     placeholder: "请输入数字结果",
      //   },
      // ],
      // ç¬¬å››è¡Œï¼š4个字段(压装位全参数),小数校验,新增压装压力
      [
        {
          title: "压装高度",
          field: "pressHeight",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "压装压力",
          field: "pressPressure",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "压装扭力",
          field: "screwTorque",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "拧紧角度",
          field: "screwAngle",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
      ],
      // ç¬¬äº”行:3个字段(拧紧位检测高度),小数校验,居中排布
      [
        {
          title: "检测高度1",
          field: "height1",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "检测高度2",
          field: "height2",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "检测高度3",
          field: "height3",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
      ],
    ]);
    // æœç´¢è¡¨å•字段 - æ ¸å¿ƒæœç´¢é¡¹ï¼ˆæµæ°´å·+基础信息+创建信息)
    const searchFormFields = ref({
      palletCode: "",
      productCode: "",
      productName: "",
      productSn: "", // æµæ°´å·æœç´¢
      creater: "",
      createDate: "",
    });
    // æœç´¢è¡¨å•配置 - ä¼˜åŒ–宽度,匹配布局
    const searchFormOptions = ref([
      [
        { title: "工装板编号", field: "palletCode", type: "like" },
        { title: "成品编号", field: "productCode", type: "like" },
        { title: "成品名称", field: "productName", type: "like" },
        { title: "工装板编号", field: "palletCode", type: "like", width: 180 },
        { title: "成品编号", field: "productCode", type: "like", width: 180 },
        { title: "成品名称", field: "productName", type: "like", width: 180 },
        { title: "流水号", field: "productSn", type: "like", width: 200 },
      ],
      [
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        { title: "创建人", field: "creater", type: "like", width: 200 },
        { title: "创建时间", field: "createDate", type: "datetime", width: 380 },
      ],
    ]);
    // è¡¨æ ¼åˆ—配置 - å®Œå…¨åŒ¹é…åŽç«¯å®žä½“,新增pressPressure列,优化列宽/对齐
    const columns = ref([
      {
        field: "id",
        title: "序号",
        type: "int",
        width: 90,
        width: 80,
        hidden: true,
        readonly: true,
        require: true,
        align: "left",
        align: "center",
      },
      {
        field: "palletCode",
        title: "工装板编号",
        type: "string",
        width: 200,
        width: 140,
        align: "left",
      },
      {
        field: "productCode",
        title: "成品编号",
        type: "string",
        width: 200,
        width: 140,
        align: "left",
      },
      {
        field: "productName",
        title: "成品名称",
        type: "string",
        width: 200,
        width: 150,
        align: "left",
      },
      {
        field: "componentQty",
        title: "零件数量",
        type: "int",
        width: 200,
        field: "productSn",
        title: "流水号",
        type: "string",
        width: 180,
        align: "left",
        overflow: "ellipsis",
      },
      // 4个状态列 - æ˜¯å¦æ ¼å¼åŒ–显示
      {
        field: "pressTightenNg",
        title: "拧紧NG",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "torsioValue",
        title: "扭力值",
        type: "float",
        width: 200,
        align: "left",
        field: "pressTightenOk",
        title: "拧紧OK",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "torsioValueStandard",
        title: "扭力值标准",
        type: "float",
        width: 200,
        align: "left",
        field: "pressTightenUnfinished",
        title: "拧紧未完成",
        type: "select",
        width: 140,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "stiffnessValue",
        title: "刚度值",
        type: "float",
        width: 200,
        align: "left",
        field: "checkUnfinished",
        title: "检测未完成",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "stiffnessValueStandard",
        title: "刚度值标准",
        type: "float",
        width: 200,
        align: "left",
      },
      {
        field: "testResult",
        title: "测试结果",
        type: "int",
        width: 200,
        align: "left",
      },
      // {
      //   field: "componentQty",
      //   title: "零件数量",
      //   type: "int",
      //   width: 90,
      //   align: "center",
      // },
      // // æ‰­åŠ›/刚度相关 - decimal类型(保留2位小数)
      // {
      //   field: "torsioValue",
      //   title: "扭力值",
      //   type: "decimal",
      //   width: 90,
      //   align: "center",
      // },
      // {
      //   field: "torsioValueStandard",
      //   title: "扭力标准",
      //   type: "decimal",
      //   width: 100,
      //   align: "center",
      // },
      // {
      //   field: "stiffnessValue",
      //   title: "刚度值",
      //   type: "decimal",
      //   width: 90,
      //   align: "center",
      // },
      // {
      //   field: "stiffnessValueStandard",
      //   title: "刚度标准",
      //   type: "decimal",
      //   width: 100,
      //   align: "center",
      // },
      // {
      //   field: "testResult",
      //   title: "测试结果",
      //   type: "int",
      //   width: 90,
      //   align: "center",
      // },
      // åŽ‹è£…ä½æ£€æµ‹å‚æ•° - ã€æ–°å¢žpressPressure列】decimal类型
      {
        field: "pressHeight",
        title: "压装位下压检测高度",
        type: "float",
        width: 200,
        align: "left",
        title: "压装高度",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "pressPressure", // ã€æ–°å¢žã€‘压装位下压压力
        title: "压装压力",
        type: "decimal",
        width: 100,
        align: "center",
        columnDescription: "压装位下压压力",
      },
      {
        field: "screwTorque",
        title: "压装位拧紧检测扭力",
        type: "float",
        width: 200,
        align: "left",
        title: "压装扭力",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "screwAngle",
        title: "压装位拧紧检测角度",
        type: "float",
        width: 200,
        align: "left",
        title: "拧紧角度",
        type: "decimal",
        width: 100,
        align: "center",
      },
      // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦
      {
        field: "height1",
        title: "拧紧位检测高度1",
        type: "float",
        width: 200,
        align: "left",
        title: "检测高度1",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "height2",
        title: "拧紧位检测高度2",
        type: "float",
        width: 200,
        align: "left",
        title: "检测高度2",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "height3",
        title: "拧紧位检测高度3",
        type: "float",
        width: 200,
        align: "left",
        title: "检测高度3",
        type: "decimal",
        width: 100,
        align: "center",
      },
      // å…¬å…±å­—段 - åˆ›å»º/修改信息
      {
        field: "creater",
        title: "创建人",
        type: "string",
        width: 90,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "createDate",
        title: "创建时间",
        type: "datetime",
        width: 150,
        align: "left",
        width: 160,
        align: "center",
      },
      {
        field: "modifier",
        title: "修改人",
        type: "string",
        width: 100,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
        align: "center",
      },
    ]);
    // åŠ å·¥ä¿¡æ¯æ— æ˜Žç»†ï¼Œä¿æŒç©ºé…ç½®
    const detail = ref({
      cnName: "",
      table: "",
@@ -361,4 +559,4 @@
    };
  },
});
</script>
</script>
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/processInfoDetail.vue
@@ -19,6 +19,7 @@
export default defineComponent({
  setup() {
    // è¡¨æ ¼åŸºç¡€é…ç½® - æ–°å¢žé»˜è®¤å€’序、统一规范
    const table = ref({
      key: "id",
      footer: "Foots",
@@ -26,40 +27,116 @@
      name: "processInfoDetail",
      url: "/processInfoDetail/",
      sortName: "createDate",
      sortOrder: "desc", // æ–°å¢žï¼šåˆ›å»ºæ—¶é—´é»˜è®¤å€’序,和主页面保持一致
    });
    // ç¼–辑表单字段 - åŒæ­¥ä¸»é¡µé¢ï¼Œæ–°å¢žpressPressure(压装压力),匹配后端实体
    const editFormFields = ref({
      id: "",
      palletCode: "",
      productCode: "",
      productName: "",
      productSn: "", // æµæ°´å·
      pressTightenNg: "", // åŽ‹è£…æ‹§ç´§_拧紧NG
      pressTightenOk: "", // åŽ‹è£…æ‹§ç´§_拧紧OK
      pressTightenUnfinished: "", // åŽ‹è£…æ‹§ç´§_本次加工未完成
      checkUnfinished: "", // æ£€æµ‹_本次检测未完成
      pressHeight: "", // åŽ‹è£…ä½ä¸‹åŽ‹é«˜åº¦
      screwTorque: "", // åŽ‹è£…ä½æ‹§ç´§æ‰­åŠ›
      screwAngle: "", // åŽ‹è£…ä½æ‹§ç´§è§’åº¦
      pressPressure: "", // ã€æ–°å¢žã€‘压装位下压压力(匹配后端实体)
      height1: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦1
      height2: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦2
      height3: "", // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦3
    });
    // ç¼–辑表单配置 - å–消冗余分类、均匀排布,新增压装压力项,补全默认值/校验,统一宽度
    const editFormOptions = ref([
      // ç¬¬ä¸€è¡Œï¼šåŸºç¡€æ ‡è¯†ï¼Œå®½åº¦åè°ƒï¼Œå’Œä¸»é¡µé¢å¸ƒå±€ä¸€è‡´
      [
        {
          title: "工装板编号",
          field: "palletCode",
          type: "input",
          width: 200,
          width: 160,
          require: true,
          placeholder: "请输入工装板编号",
        },
        {
          title: "成品编号",
          field: "productCode",
          type: "input",
          width: 200,
          width: 160,
          require: true,
          placeholder: "请输入成品编号",
        },
        {
          title: "成品名称",
          field: "productName",
          type: "input",
          width: 200,
          width: 160,
          require: true,
          placeholder: "请输入成品名称",
        },
        {
          title: "流水号",
          field: "productSn",
          type: "input",
          width: 180,
          require: false,
          placeholder: "请输入产品流水号",
        },
      ],
      // ç¬¬äºŒè¡Œï¼š4个状态列+主键,补全默认值0(否),统一宽度/对齐,隐藏主键
      [
        {
          title: "拧紧NG",
          field: "pressTightenNg",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0", // æ–°å¢žé»˜è®¤å€¼ï¼Œå’Œä¸»é¡µé¢ä¸€è‡´
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "拧紧OK",
          field: "pressTightenOk",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0", // æ–°å¢žé»˜è®¤å€¼
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "拧紧未完成",
          field: "pressTightenUnfinished",
          type: "select",
          width: 170,
          align: "center",
          defaultValue: "0",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "检测未完成",
          field: "checkUnfinished",
          type: "select",
          width: 150,
          align: "center",
          defaultValue: "0", // æ–°å¢žé»˜è®¤å€¼ï¼Œç»Ÿä¸€è§„范
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
        {
          title: "主键ID",
          field: "id",
@@ -69,90 +146,286 @@
          readonly: true,
        },
      ],
      [
        {
          title: "压装高度",
          field: "pressHeight",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "压装压力",
          field: "pressPressure", // æ–°å¢žåŽ‹è£…åŽ‹åŠ›é¡¹
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "压装扭力",
          field: "screwTorque",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "拧紧角度",
          field: "screwAngle",
          type: "input",
          inputType: "number",
          width: 160,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
      ],
      // ç¬¬äº”行:拧紧位检测高度,小数校验,居中排布,统一宽度
      [
        {
          title: "检测高度1",
          field: "height1",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "检测高度2",
          field: "height2",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
        {
          title: "检测高度3",
          field: "height3",
          type: "input",
          inputType: "number",
          width: 200,
          require: false,
          attrs: { step: 0.01, min: 0 },
          placeholder: "保留2位小数",
        },
      ],
    ]);
    // æœç´¢è¡¨å•字段 - ä¿æŒå’Œä¸»é¡µé¢ã€åŽŸæœ‰ä»£ç ä¸€è‡´ï¼Œæ ¸å¿ƒæœç´¢é¡¹æ— è°ƒæ•´
    const searchFormFields = ref({
      palletCode: "",
      productCode: "",
      productName: "",
      productSn: "", // æµæ°´å·æœç´¢
      creater: "",
      createDate: "",
    });
    // æœç´¢è¡¨å•配置 - ä¼˜åŒ–宽度匹配布局,和主页面完全一致
    const searchFormOptions = ref([
      [
        { title: "工装板编号", field: "palletCode", type: "like" },
        { title: "成品编号", field: "productCode", type: "like" },
        { title: "成品名称", field: "productName", type: "like" },
        { title: "工装板编号", field: "palletCode", type: "like", width: 180 },
        { title: "成品编号", field: "productCode", type: "like", width: 180 },
        { title: "成品名称", field: "productName", type: "like", width: 180 },
        { title: "流水号", field: "productSn", type: "like", width: 200 },
      ],
      [
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
        { title: "创建人", field: "creater", type: "like", width: 200 },
        { title: "创建时间", field: "createDate", type: "datetime", width: 380 },
      ],
    ]);
    // è¡¨æ ¼åˆ—配置 - ã€æ–°å¢žpressPressure列】,统一列名/宽度/类型,修复首字母大写问题,优化对齐
    const columns = ref([
      {
        field: "id",
        title: "序号",
        type: "int",
        width: 90,
        width: 80,
        hidden: true,
        readonly: true,
        require: true,
        align: "left",
        align: "center",
      },
      {
        field: "palletCode",
        title: "工装板编号",
        type: "string",
        width: 200,
        width: 140,
        align: "left",
      },
      {
        field: "productCode",
        title: "成品编号",
        type: "string",
        width: 200,
        width: 140,
        align: "left",
      },
      {
        field: "productName",
        title: "成品名称",
        type: "string",
        width: 200,
        width: 150,
        align: "left",
      },
      {
        field: "productSn",
        title: "流水号",
        type: "string",
        width: 180,
        align: "left",
        overflow: "ellipsis",
      },
      // 4个状态列 - ä¿®å¤åŽŸæœ‰PressTightenNg首字母大写问题,统一规范
      {
        field: "pressTightenNg",
        title: "拧紧NG",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "pressTightenOk",
        title: "拧紧OK",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "pressTightenUnfinished",
        title: "拧紧未完成",
        type: "select",
        width: 140,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "checkUnfinished",
        title: "检测未完成",
        type: "select",
        width: 120,
        align: "center",
        bind: {
          key: "value",
          data: [
            { key: "0", value: "否" },
            { key: "1", value: "是" },
          ],
        },
      },
      {
        field: "pressHeight",
        title: "压装高度",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "pressPressure", // æ–°å¢žåŽ‹è£…åŽ‹åŠ›åˆ—
        title: "压装压力",
        type: "decimal",
        width: 100,
        align: "center",
        columnDescription: "压装位下压压力",
      },
      {
        field: "screwTorque",
        title: "压装扭力",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "screwAngle",
        title: "拧紧角度",
        type: "decimal",
        width: 100,
        align: "center",
      },
      // æ‹§ç´§ä½æ£€æµ‹é«˜åº¦
      {
        field: "height1",
        title: "检测高度1",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "height2",
        title: "检测高度2",
        type: "decimal",
        width: 100,
        align: "center",
      },
      {
        field: "height3",
        title: "检测高度3",
        type: "decimal",
        width: 100,
        align: "center",
      },
      // å…¬å…±å­—段 - åˆ›å»º/修改信息,和主页面一致
      {
        field: "creater",
        title: "创建人",
        type: "string",
        width: 90,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "createDate",
        title: "创建时间",
        type: "datetime",
        width: 150,
        align: "left",
        width: 160,
        align: "center",
      },
      {
        field: "modifier",
        title: "修改人",
        type: "string",
        width: 100,
        align: "left",
        width: 80,
        align: "center",
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
        align: "center",
      },
    ]);
    // æ— äºŒçº§æ˜Žç»†ï¼Œä¿æŒç©ºé…ç½®ä¸å˜
    const detail = ref({
      cnName: "",
      table: "",
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/basicinfo/scanStation.vue
@@ -32,11 +32,15 @@
      sortName: "createDate",
    });
    // ã€ä¿®æ”¹1】新增组装人员、首件/末件流水号字段,移除不存在的isScanned
    const editFormFields = ref({
      id: "",
      stationCode: "",
      stationName: "",
      stationEndProduct: "",
      assembleUser: "", // ç»„装人员
      firstProductSn: "", // é¦–件流水号
      lastProductSn: "", // æœ«ä»¶æµæ°´å·
    });
    const editFormOptions = ref([
@@ -68,6 +72,36 @@
          require: false,
        },
      ],
      // ã€ä¿®æ”¹2】移除isScanned下拉框,新增组装人员输入框
      [
        {
          title: "组装人员",
          field: "assembleUser",
          type: "input",
          width: 200,
          require: false, // åŽç«¯å…è®¸ä¸ºç©ºï¼Œæ•…设为非必填
        },
      ],
      // ã€æ–°å¢žã€‘首件流水号输入框
      [
        {
          title: "首件流水号",
          field: "firstProductSn",
          type: "input",
          width: 300, // æµæ°´å·è¾ƒé•¿ï¼ŒåŠ å®½è¾“å…¥æ¡†
          require: false,
        },
      ],
      // ã€æ–°å¢žã€‘末件流水号输入框
      [
        {
          title: "末件流水号",
          field: "lastProductSn",
          type: "input",
          width: 300,
          require: false,
        },
      ],
      [
        {
          title: "主键ID",
@@ -80,10 +114,12 @@
      ],
    ]);
    // ã€ä¿®æ”¹3】搜索表单移除isScanned,新增组装人员(流水号一般不做搜索,故不新增)
    const searchFormFields = ref({
      stationCode: "",
      stationName: "",
      stationEndProduct: "",
      assembleUser: "", // æ–°å¢žç»„装人员搜索
      creater: "",
      createDate: "",
    });
@@ -98,8 +134,10 @@
          type: "select-search",
          data: stationEndProductList, // ç»‘定全局接口数据
        },
        { title: "组装人员", field: "assembleUser", type: "like" }, // æ–°å¢žç»„装人员模糊搜索
      ],
      [
        // ã€ä¿®æ”¹4】移除搜索栏的isScanned下拉框
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
      ],
@@ -142,6 +180,28 @@
        width: 200,
        align: "left",
      },
      // ã€ä¿®æ”¹5】移除表格的isScanned列,新增以下三列
      {
        field: "assembleUser",
        title: "组装人员",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "firstProductSn",
        title: "首件流水号",
        type: "string",
        width: 220,
        align: "left",
      },
      {
        field: "lastProductSn",
        title: "末件流水号",
        type: "string",
        width: 220,
        align: "left",
      },
      {
        field: "creater",
        title: "创建人",
@@ -171,7 +231,6 @@
        align: "left",
      },
    ]);
    const detail = ref({
      cnName: "",
      table: "",
@@ -180,6 +239,7 @@
      key: "",
    });
    // ã€ä¿ç•™åŽŸæœ‰é€»è¾‘ã€‘èŽ·å–ç«™å°æˆå“ä¸‹æ‹‰æ•°æ®
    const getStationEndProductData = async () => {
      try {
        const res = await axios.get("/api/formula/getEndProductList");
´úÂë¹ÜÀí/WIDESEAWCS_Client/src/views/quartzJob/deviceInfo.vue
@@ -1,5 +1,4 @@
 <template>
<template>
  <view-grid
    ref="grid"
    :columns="columns"
@@ -309,14 +308,6 @@
          require: true,
          align: "left",
          edit: { type: "" },
        },
        {
          field: "creater",
          title: "创建人",
          type: "string",
          width: 90,
          align: "left",
          sortable: true,
        },
        {
          field: "creater",
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/17.14.794.21998/CodeChunks.db
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/CopilotIndices/17.14.794.21998/SemanticSymbols.db
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/DesignTimeBuild/.dtbcache.v2
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/0f5d7584-9cfe-4074-aeb3-fa1f9e570949.vsidx
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/37cbdcf3-408e-4196-9c7f-486ef5eef107.vsidx
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/6b8b6a38-d1b1-459e-b415-f709208d542a.vsidx
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/FileContentIndex/c99954ff-673f-45d7-b93b-30e6c1adfe58.vsidx
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/.futdcache.v2
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/.suo
Binary files differ
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/BoxingDetailService.cs
@@ -4,11 +4,15 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.PLCEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
namespace WIDESEAWCS_BasicInfoService
{
@@ -39,18 +43,55 @@
        /// <summary>
        /// æ¯”较零件是否齐全
        /// </summary>
        /// <param name="boxingDetails"></param>
        /// <param name="formulaDetails"></param>
        /// <returns></returns>
        public bool IsComponentCodesEqual(List<Dt_BoxingDetail> boxingDetails, List<Dt_FormulaDetail> formulaDetails)
        /// <param name="boxingDetails">实际装箱的零件集合</param>
        /// <param name="formulaDetails">配方要求的零件集合</param>
        /// <returns>是否完全匹配</returns>
        public bool CheckComponentsMatchExactly(List<string> boxingDetails, List<string> formulaDetails)
        {
            // 1. åŸºç¡€æ ¡éªŒï¼šç©ºå€¼/数量不一致直接返回不匹配
            if (boxingDetails == null || formulaDetails == null || boxingDetails.Count != formulaDetails.Count)
            {
                return false;
            }
            List<string> BoxingIdList = boxingDetails.Select(x => x.ComponentCode).ToList();
            List<string> FormulaIdList = formulaDetails.Select(x => x.ComponentCode).ToList();
            return !BoxingIdList.Except(FormulaIdList).Any() && !FormulaIdList.Except(BoxingIdList).Any();
            // 2. ä¸¤ä¸ªç©ºé›†åˆç›´æŽ¥åˆ¤å®šä¸ºåŒ¹é…ï¼ˆæ— é›¶ä»¶=零件齐全)
            if (boxingDetails.Count == 0)
            {
                return true;
            }
            // 3. ç»Ÿè®¡ç¬¬ä¸€ä¸ªé›†åˆçš„元素出现次数(严格键匹配,处理重复元素)
            var elementCountDict = new Dictionary<string, int>();
            foreach (var item in boxingDetails)
            {
                // å¤„理集合中的null元素,转为空字符串避免字典键为null报错
                var key = item ?? string.Empty;
                if (elementCountDict.ContainsKey(key))
                {
                    elementCountDict[key]++;
                }
                else
                {
                    elementCountDict[key] = 1;
                }
            }
            // 4. éåŽ†ç¬¬äºŒä¸ªé›†åˆï¼ŒæŠµæ¶ˆè®¡æ•°ï¼šæ— æ­¤å…ƒç´ /数量不匹配直接返回false
            foreach (var item in formulaDetails)
            {
                var key = item ?? string.Empty;
                if (!elementCountDict.ContainsKey(key))
                {
                    return false; // å­˜åœ¨é…æ–¹æ²¡æœ‰/装箱多出来的零件
                }
                elementCountDict[key]--;
                if (elementCountDict[key] == 0)
                {
                    elementCountDict.Remove(key); // è®¡æ•°æ¸…零则移除,避免干扰最终判断
                }
            }
            // 5. å­—典为空 = æ‰€æœ‰å…ƒç´ ç§ç±»+数量完全匹配
            return elementCountDict.Count == 0;
        }
@@ -100,135 +141,194 @@
                    {
                        return WebResponseContent.Instance.Error("提交参数不能为空");
                    }
                    string palletCode = toolingBoardSubmitDto.ToolingBoardNo?.Trim();
                    string productCode = toolingBoardSubmitDto.FinishedProductCode?.Trim();
                    if (string.IsNullOrWhiteSpace(palletCode))
                    if (!string.IsNullOrWhiteSpace(productCode))
                    {
                        return WebResponseContent.Instance.Error("工装板编号不能为空");
                    }
                    if (string.IsNullOrWhiteSpace(productCode))
                    {
                        return WebResponseContent.Instance.Error("成品编码不能为空");
                    }
                        string proCode = string.Empty;
                        string proOther = string.Empty;
                    // 2. æŸ¥è¯¢æˆå“é…æ–¹ä¿¡æ¯
                    Dt_Formula formulaModel = _formulaService.Repository.QueryFirst(x => x.ProductCode == productCode);
                    if (formulaModel == null)
                    {
                        return WebResponseContent.Instance.Error("无成品配方,请核对成品编码");
                    }
                    List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formulaModel.Id && x.IsScanned == 1);
                    List<string> Codelist = dt_FormulaDetails.Select(x => x.ComponentCode).ToList();
                    string IsCode = IsComponentCodesEqual(toolingBoardSubmitDto.PartsList, Codelist);
                    if (IsCode != null)
                    {
                        return WebResponseContent.Instance.Error($"物料【{IsCode}】错误,请核对物料编号");
                    }
                    // 3. æ ¸å¿ƒåˆ¤æ–­ï¼šæ ¹æ®å·¥è£…板编号查询是否存在【新增/修改】的主表数据
                    Dt_Boxing existBoxinModel = _boxingService.Repository.QueryFirst(x => x.PalletCode == palletCode);
                    if (existBoxinModel == null)
                    {
                        #region æ–°å¢žé€»è¾‘ - åŽŸé€»è¾‘ä¼˜åŒ–ç‰ˆ
                        Dt_Boxing dt_boxin = new Dt_Boxing()
                        var proCodeMatch = System.Text.RegularExpressions.Regex.Match(productCode, @"TX(\d+)(?=\s|\||$)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                        if (proCodeMatch.Success)
                        {
                            PalletCode = palletCode,
                            ProductCode = productCode,
                            ProductName = formulaModel.ProductName.Trim(),
                            Creater = "admin",
                            CreateDate = DateTime.Now
                        };
                        int newBoxingId = _boxingService.Repository.AddData(dt_boxin);
                        // æ‰¹é‡æ·»åŠ æ˜Žç»†è¡¨æ•°æ®
                        if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                        {
                            List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                            foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                            {
                                if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                                string ComponentCodeTrim = ComponentCode.Trim();
                                Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                                if (formulaDetail == null)
                                {
                                    return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料编号");
                                }
                                Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                                {
                                    BoxingId = newBoxingId,
                                    ComponentCode = ComponentCodeTrim,
                                    ComponentName = formulaDetail.ComponentName,
                                    Creater = "admin",
                                    CreateDate = DateTime.Now
                                };
                                detailList.Add(detailModel);
                            }
                            if (detailList.Count > 0)
                            {
                                BaseDal.AddData(detailList);
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region ä¿®æ”¹é€»è¾‘ - æ–°å¢žæ ¸å¿ƒé€»è¾‘
                        // 1. æ›´æ–°ä¸»è¡¨æ•°æ®
                        existBoxinModel.ProductCode = productCode;
                        existBoxinModel.ProductName = formulaModel.ProductName.Trim();
                         existBoxinModel.Modifier = "admin";
                        existBoxinModel.ModifyDate = DateTime.Now;
                        _boxingService.Repository.UpdateData(existBoxinModel);
                        int boxingId = existBoxinModel.Id;
                        // 2. åˆ é™¤è¯¥ç»„盘下的【原有全部明细表数据】
                        List<Dt_BoxingDetail> oldDetailList = BaseDal.QueryData(x => x.BoxingId == boxingId);
                        if (oldDetailList != null && oldDetailList.Count > 0)
                        {
                            BaseDal.DeleteData(oldDetailList);
                            proCode = $"TX{proCodeMatch.Groups[1].Value.Trim()}"; // æ‹¼æŽ¥TX+数字,保持格式统一
                        }
                        // 3. é‡æ–°æ’入修改后的明细表数据
                        if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                        // æ­£åˆ™2:匹配连续的10位纯数字(全局匹配,取第一个符合的即可)
                        var proOtherMatch = System.Text.RegularExpressions.Regex.Match(productCode, @"\d{10}");
                        if (proOtherMatch.Success)
                        {
                            List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                            foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                            {
                                if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                                string ComponentCodeTrim = ComponentCode.Trim();
                                Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                                if (formulaDetail == null)
                                {
                                    return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料名称");
                                }
                                Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                                {
                                    BoxingId = boxingId,
                                    ComponentCode = ComponentCodeTrim,
                                    ComponentName = formulaDetail.ComponentName,
                                    Creater = "admin",
                                    CreateDate = DateTime.Now
                                };
                                detailList.Add(detailModel);
                            }
                            if (detailList.Count > 0)
                            {
                                BaseDal.AddData(detailList);
                            }
                            proOther = proOtherMatch.Value.Trim();
                        }
                        #endregion
                        toolingBoardSubmitDto.PartsList = toolingBoardSubmitDto.PartsList.Where(code => !string.IsNullOrEmpty(code)).ToList();
                        // 2. æŸ¥è¯¢æˆå“é…æ–¹ä¿¡æ¯
                        Dt_Formula formulaModel = _formulaService.Repository.QueryFirst(x => x.ProductCode == proCode);
                        if (formulaModel == null)
                        {
                            return WebResponseContent.Instance.Error("无成品配方,请核对成品编码");
                        }
                        List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formulaModel.Id && x.IsScanned == 1);
                        List<string> Codelist = dt_FormulaDetails.Select(x => x.ComponentCode).ToList();
                        string IsCode = IsComponentCodesEqual(toolingBoardSubmitDto.PartsList, Codelist);
                        if (IsCode != null)
                        {
                            return WebResponseContent.Instance.Error($"物料【{IsCode}】错误,请核对物料编号");
                        }
                        //Dt_Boxing existBoxinModel = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        //if (existBoxinModel == null)
                        //{
                        //    return WebResponseContent.Instance.Error($"托盘未添加,请稍后重试");
                        //}
                        if (!CheckComponentsMatchExactly(toolingBoardSubmitDto.PartsList, Codelist))
                        {
                            throw new InvalidOperationException("零件与配方表中不同");
                        }
                        var PalletCode = TcpClientExample.Start("192.168.2.120", 2001);
                        if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                        {
                            throw new InvalidOperationException("托盘码未扫到,请重试");
                        }
                        Dt_Boxing existBoxinModel = new Dt_Boxing();
                        existBoxinModel.PalletCode = PalletCode;
                        existBoxinModel.ProductCode = proCode;
                        existBoxinModel.BoxingNo = proOther;
                        int id = _boxingService.Repository.AddData(existBoxinModel);
                        foreach (var item in dt_FormulaDetails)
                        {
                            Dt_BoxingDetail dt_BoxingDetail = new Dt_BoxingDetail()
                            {
                                BoxingId = id,
                                ComponentCode = item.ComponentCode,
                                ComponentName = item.ComponentName,
                                Creater = "admin",
                                CreateDate = new DateTime()
                            };
                            BaseDal.AddData(dt_BoxingDetail);
                        }
                        uow.Commit();
                    }
                    uow.Commit();
                    string msg = existBoxinModel == null ? "组盘信息新增成功!" : "组盘信息修改成功!";
                    return WebResponseContent.Instance.OK(msg);
                    OtherDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceName == "主控PLC") as OtherDevice;
                    if (device == null) throw new Exception("未找到主控PLC设备信息");
                    if (!device.IsConnected) throw new Exception($"主控PLC设备通讯异常");
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                    Thread.Sleep(500);
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, false);
                    //    if (existBoxinModel == null)
                    //{
                    //    #region æ–°å¢žé€»è¾‘ - åŽŸé€»è¾‘ä¼˜åŒ–ç‰ˆ
                    //    Dt_Boxing dt_boxin = new Dt_Boxing()
                    //    {
                    //        PalletCode = palletCode,
                    //        ProductCode = productCode,
                    //        ProductName = formulaModel.ProductName.Trim(),
                    //        Creater = "admin",
                    //        CreateDate = DateTime.Now
                    //    };
                    //    int newBoxingId = _boxingService.Repository.AddData(dt_boxin);
                    //    // æ‰¹é‡æ·»åŠ æ˜Žç»†è¡¨æ•°æ®
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料编号");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = newBoxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //else
                    //{
                    //    #region ä¿®æ”¹é€»è¾‘ - æ–°å¢žæ ¸å¿ƒé€»è¾‘
                    //    // 1. æ›´æ–°ä¸»è¡¨æ•°æ®
                    //    existBoxinModel.ProductCode = productCode;
                    //    existBoxinModel.ProductName = formulaModel.ProductName.Trim();
                    //     existBoxinModel.Modifier = "admin";
                    //    existBoxinModel.ModifyDate = DateTime.Now;
                    //    _boxingService.Repository.UpdateData(existBoxinModel);
                    //    int boxingId = existBoxinModel.Id;
                    //    // 2. åˆ é™¤è¯¥ç»„盘下的【原有全部明细表数据】
                    //    List<Dt_BoxingDetail> oldDetailList = BaseDal.QueryData(x => x.BoxingId == boxingId);
                    //    if (oldDetailList != null && oldDetailList.Count > 0)
                    //    {
                    //        BaseDal.DeleteData(oldDetailList);
                    //    }
                    //    // 3. é‡æ–°æ’入修改后的明细表数据
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料名称");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = boxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //uow.Commit();
                    //string msg = existBoxinModel == null ? "组盘信息新增成功!" : "组盘信息修改成功!";
                    return WebResponseContent.Instance.OK();
                }
                catch (Exception ex)
                {
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/FormulaService.cs
@@ -24,38 +24,37 @@
            return base.AddData(saveModel);
        }
        public override WebResponseContent UpdateData(SaveModel saveModel)
        {
            Dt_Formula dt_Formula=new Dt_Formula()
            {
                Id = saveModel.MainData["id"].ObjToInt(),
                ProductCode = saveModel.MainData["productCode"].ToString(),
                ProductName = saveModel.MainData["productName"].ToString(),
                ProductLength = decimal.Parse(saveModel.MainData["productLength"].ToString()),
                ProductWidth = decimal.Parse(saveModel.MainData["productWidth"].ToString()),
                ProductHeight = decimal.Parse(saveModel.MainData["productHeight"].ToString()),
                ScrewDownsetDistance = decimal.Parse(saveModel.MainData["screwDownsetDistance"].ToString()),
                ScrewTorqueOutput = decimal.Parse(saveModel.MainData["screwTorqueOutput"].ToString()),
                DintAutoScrewOn = saveModel.MainData["dintAutoScrewOn"].ObjToInt(),
                XDirectionDistance1 = decimal.Parse(saveModel.MainData["xDirectionDistance1"].ToString()),
                YDirectionHeight1 = decimal.Parse(saveModel.MainData["yDirectionHeight1"].ToString()),
                XDirectionDistance2 = decimal.Parse(saveModel.MainData["xDirectionDistance2"].ToString()),
                YDirectionHeight2 = decimal.Parse(saveModel.MainData["yDirectionHeight2"].ToString()),
                XDirectionDistance3 = decimal.Parse(saveModel.MainData["xDirectionDistance3"].ToString()),
                YDirectionHeight3 = decimal.Parse(saveModel.MainData["yDirectionHeight3"].ToString())
        //public override WebResponseContent UpdateData(SaveModel saveModel)
        //{
        //    Dt_Formula dt_Formula = new Dt_Formula()
        //    {
        //        Id = saveModel.MainData["id"].ObjToInt(),
        //        ProductCode = saveModel.MainData["productCode"].ToString(),
        //        ProductName = saveModel.MainData["productName"].ToString(),
        //        ProductLength = decimal.Parse(saveModel.MainData["productLength"].ToString()),
        //        ProductWidth = decimal.Parse(saveModel.MainData["productWidth"].ToString()),
        //        ProductHeight = decimal.Parse(saveModel.MainData["productHeight"].ToString()),
        //        ScrewDownsetDistance = decimal.Parse(saveModel.MainData["screwDownsetDistance"].ToString()),
        //        ScrewTorqueOutput = decimal.Parse(saveModel.MainData["screwTorqueOutput"].ToString()),
        //        DintAutoScrewOn = saveModel.MainData["dintAutoScrewOn"].ObjToInt(),
        //        P0P1Width = decimal.Parse(saveModel.MainData["p0P1Width"].ToString()),
        //        P0P2Width = decimal.Parse(saveModel.MainData["p0P2Width"].ToString()),
        //        P0P3Width = decimal.Parse(saveModel.MainData["p0P3Width"].ToString()),
        //        P1P3Height = decimal.Parse(saveModel.MainData["p1P3Height"].ToString()),
        //        P2P3Height = decimal.Parse(saveModel.MainData["p2P3Height"].ToString()),
                //ScrewTorque = float.Parse(saveModel.MainData["ScrewTorque"].ToString()),
                //UpdateBy = saveModel.UpdateBy,
                //UpdateTime = DateTime.Now
            };
            return UpdateData(dt_Formula);
            //return base.UpdateData(saveModel);
        }
        //        //ScrewTorque = float.Parse(saveModel.MainData["ScrewTorque"].ToString()),
        //        //UpdateBy = saveModel.UpdateBy,
        //        //UpdateTime = DateTime.Now
        //    };
        //    return UpdateData(dt_Formula);
        //    //return base.UpdateData(saveModel);
        //}
        public override WebResponseContent UpdateData(Dt_Formula entity)
        {
            return base.UpdateData(entity);
        }
        //public override WebResponseContent UpdateData(Dt_Formula entity)
        //{
        //    return base.UpdateData(entity);
        //}
        /// <summary>
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ProcessInfoService.cs
@@ -3,6 +3,7 @@
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_Model.Models;
@@ -10,46 +11,20 @@
{
    public class ProcessInfoService : ServiceBase<Dt_ProcessInfo, IRepository<Dt_ProcessInfo>>, IProcessInfoService
    {
        public ProcessInfoService(IRepository<Dt_ProcessInfo> BaseDal) : base(BaseDal)
        private readonly IFormulaService _formulaService;
        private readonly IFormulaDetailService _formulaDetailService;
        public ProcessInfoService(
            IRepository<Dt_ProcessInfo> BaseDal,
            IFormulaService formulaService,
            IFormulaDetailService formulaDetailService
            ) : base(BaseDal)
        {
            _formulaService = formulaService;
            _formulaDetailService = formulaDetailService;
        }
        public IRepository<Dt_ProcessInfo> Repository => BaseDal;
        /// <summary>
        /// ä¸‹è½½æµç¨‹å¡
        /// </summary>
        /// <param name="dt_ProcessInfo"></param>
        /// <returns></returns>
        public WebResponseContent ExportData(Dt_ProcessInfo dt_ProcessInfo)
        {
                string fileName = $"{DateTime.Now.ToString("yyyyMMddHHssmm")}.xlsx";
                string templatePath = $"{AppDomain.CurrentDomain.BaseDirectory}ExprotTemplate\\发电机弹性支撑信息化流程卡.xlsx";//模板路径
                string savePath = $"{AppDomain.CurrentDomain.BaseDirectory}Download\\{fileName}";//保存文件路径
                using Stream templateStream = new FileStream(templatePath, FileMode.Open);
                using Stream saveStream = new FileStream(savePath, FileMode.Create);
                using ExcelPackage package = new ExcelPackage(saveStream, templateStream);
                ExcelWorksheet worksheet = package.Workbook.Worksheets["流程卡"];
                worksheet.Cells[3, 5].Value = dt_ProcessInfo.ProductCode;//成品编号
                package.Save();
                string pdfFileName = $"{DateTime.Now.ToString("yyyyMMddHHssmm")}.pdf";
                string pdfPath = $"{AppDomain.CurrentDomain.BaseDirectory}Download\\{pdfFileName}";
                Workbook workbook = new Workbook();
                workbook.LoadFromFile(savePath);
                // è½¬æ¢ç¬¬ä¸€ä¸ªå·¥ä½œè¡¨åˆ°PDF
                workbook.SaveToFile(pdfPath, FileFormat.PDF);
                return WebResponseContent.Instance.OK(data: new { path = pdfPath, fileName = pdfFileName });
            }
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ScanStationService.cs
@@ -1,4 +1,6 @@
using Autofac.Core;
using OfficeOpenXml;
using Spire.Xls;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -8,7 +10,9 @@
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_IBasicInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -18,14 +22,21 @@
    {
        private readonly IFormulaService _formulaService;
        private readonly IFormulaDetailService _formulaDetailService;
        private readonly IProcessInfoService _processInfoService;
        private readonly IProcessInfoDetailService _processInfoDetailService;
        public ScanStationService(IRepository<Dt_ScanStation> BaseDal,
        public ScanStationService(IRepository<Dt_ScanStation> BaseDal,
            IFormulaService formulaService,
            IFormulaDetailService formulaDetailService
            IFormulaDetailService formulaDetailService,
            IProcessInfoService processInfoService,
            IProcessInfoDetailService processInfoDetailService
            ) : base(BaseDal)
        {
            _formulaService = formulaService;
            _formulaDetailService = formulaDetailService;
            _processInfoService = processInfoService;
            _processInfoDetailService = processInfoDetailService;
        }
        public IRepository<Dt_ScanStation> Repository => BaseDal;
@@ -57,7 +68,7 @@
                var Error = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolError);
                if (Heart && !EMG && OnlineExecuting && !Error)
                {
                {
                    device.SetValue(W_PLCDBName.wboolAutoStart, true);
                    //暂停信号
                    device.SetValue(W_PLCDBName.wboolAutoPause, false);
@@ -89,7 +100,7 @@
                var Heart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolHeart);
                var EMG = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolEMG);
                var Error = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolError);
                if(!device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolAutoStart))
                if (!device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolAutoStart))
                {
                    return WebResponseContent.Instance.Error("设备未启动");
                }
@@ -214,11 +225,161 @@
                }
                return WebResponseContent.Instance.Error("更新错误");
            }
            catch (Exception ex)
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error("获取数据失败");
            }
        }
        /// <summary>
        /// ä¸‹è½½æµç¨‹å¡
        /// </summary>
        /// <param name="dt_ProcessInfo"></param>
        /// <returns></returns>
        public WebResponseContent ExportData(Dt_ScanStation dt_ScanStation)
        {
            string fileName = $"{DateTime.Now.ToString("yyyyMMddHHssmm")}.xlsx";
            string templatePath = $"{AppDomain.CurrentDomain.BaseDirectory}ExprotTemplate\\发电机弹性支撑信息化流程卡.xlsx";//模板路径
            string savePath = $"{AppDomain.CurrentDomain.BaseDirectory}Download\\{fileName}";//保存文件路径
            using Stream templateStream = new FileStream(templatePath, FileMode.Open);
            using Stream saveStream = new FileStream(savePath, FileMode.Create);
            using ExcelPackage package = new ExcelPackage(saveStream, templateStream);
            ExcelWorksheet worksheet = package.Workbook.Worksheets["流程卡"];
            Dt_Formula formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_ScanStation.StationEndProduct);
            List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formula.Id && x.IsScanned == 1).ToList();
            for (int i = dt_FormulaDetails.Count; i < 10; i++)
            {
                dt_FormulaDetails.Add(new Dt_FormulaDetail());
            }
            worksheet.Cells[3, 5].Value = dt_ScanStation.StationEndProduct;//成品编号
            worksheet.Cells[3, 17].Value = dt_ScanStation.LastProductSn.ObjToInt() - dt_ScanStation.FirstProductSn.ObjToInt() + 1;//数量;
            worksheet.Cells[3, 29].Value = dt_ScanStation.FirstProductSn + "-" + dt_ScanStation.LastProductSn;//流水号
            worksheet.Cells[4, 5].Value = DateTime.Now.ToString("yyyy/MM/dd");//组装日期
            worksheet.Cells[4, 17].Value = dt_ScanStation.AssembleUser;//组装人员
            int row = 7;
            for (int j = 0; j < 5; j++)
            {
                worksheet.Cells[row, 1].Value = dt_FormulaDetails[j].ComponentName;
                worksheet.Cells[row, 5].Value = dt_FormulaDetails[j].ComponentCode;
                worksheet.Cells[row, 12].Value = dt_FormulaDetails[j].SupplierCode;
                worksheet.Cells[row, 19].Value = dt_FormulaDetails[j + 5].ComponentName;
                worksheet.Cells[row, 23].Value = dt_FormulaDetails[j + 5].ComponentCode;
                worksheet.Cells[row, 30].Value = dt_FormulaDetails[j + 5].SupplierCode;
                row++;
            }
            row = 13;
            for (int j = 0; j < 4; j++)
            {
                worksheet.Cells[row + j, 12].Value = "☑ æ˜¯     â–¡ å¦";
                worksheet.Cells[row + j, 30].Value = "☑ æ˜¯     â–¡ å¦";
            }
            worksheet.Cells[17, 12].Value = "☑ æ˜¯     â–¡ å¦";
            worksheet.Cells[23, 5].Value = "☑ æ˜¯     â–¡ å¦";
            List<Dt_ProcessInfoDetail> dt_ProcessInfoDetails = _processInfoDetailService.Repository
                .QueryData(x => x.ProductCode == dt_ScanStation.StationEndProduct
                && x.ProductSn.CompareTo(dt_ScanStation.LastProductSn) >= 0
                && x.ProductSn.CompareTo(dt_ScanStation.LastProductSn) <= 0)
                .OrderBy(x => x.CreateDate)
                .ToList();
            row = 27;
            ExcelRange baseStyleRow = worksheet.Cells[$"{row}:{row}"];
            foreach (var item in dt_ProcessInfoDetails)
            {
                if (row > 61)
                {
                    var sourceRange = worksheet.Cells[row - 1, 1, row - 1, 36];
                    var targetRange = worksheet.Cells[row, 1, row, 36];
                    // 1. å¤åˆ¶åˆå¹¶è§„则(原有逻辑保留)
                    this.CopyCellMerge(worksheet, sourceRange, targetRange);
                    // 2. å¤åˆ¶æ ·å¼ï¼ˆå…¼å®¹æ‰€æœ‰EPPlus版本)
                    targetRange.StyleID = sourceRange.StyleID;
                    // 3. åŒæ­¥è¡Œé«˜
                    worksheet.Row(row).Height = worksheet.Row(row - 1).Height;
                }
                worksheet.Cells[row, 1].Value = item.ProductSn;
                worksheet.Cells[row, 7].Value = item.Height2;
                worksheet.Cells[row, 13].Value = item.Height1;
                worksheet.Cells[row, 19].Value = item.PressPressure;
                worksheet.Cells[row, 25].Value = item.ScrewTorque;
                if (item.PressTightenUnfinished == 1)
                {
                    worksheet.Cells[row, 31].Value = "压装拧紧异常";
                }
                else if (item.CheckUnfinished == 1)
                {
                    worksheet.Cells[row, 31].Value = "检测异常";
                }
                else
                {
                    worksheet.Cells[row, 31].Value = "正常";
                }
                row++;
            }
            //worksheet.DeleteRow(row, worksheet.Dimension.End.Row - row + 1);
            package.Save();
            string pdfFileName = $"{DateTime.Now.ToString("yyyyMMddHHssmm")}.pdf";
            string pdfPath = $"{AppDomain.CurrentDomain.BaseDirectory}Download\\{pdfFileName}";
            Workbook workbook = new Workbook();
            workbook.LoadFromFile(savePath);
            // è½¬æ¢ç¬¬ä¸€ä¸ªå·¥ä½œè¡¨åˆ°PDF
            workbook.SaveToFile(pdfPath, FileFormat.PDF);
            return WebResponseContent.Instance.OK(data: new { path = pdfPath, fileName = pdfFileName });
        }
        // <summary>
        /// è‡ªå®šä¹‰Excel单元格合并规则复制方法(兼容低版本EPPlus)
        /// </summary>
        /// <param name="worksheet">Excel工作表</param>
        /// <param name="sourceRange">源单元格范围</param>
        /// <param name="targetRange">目标单元格范围</param>
        public void CopyCellMerge(ExcelWorksheet worksheet, ExcelRange sourceRange, ExcelRange targetRange)
        {
            if (sourceRange == null || targetRange == null) return;
            if (sourceRange.Worksheet != worksheet || targetRange.Worksheet != worksheet) return;
            // 1. å…ˆå°†æºèŒƒå›´å†…的合并区域提取到临时列表中
            var sourceMergeList = new List<string>();
            foreach (var merge in worksheet.MergedCells)
            {
                var mergeRange = worksheet.Cells[merge];
                if (mergeRange.Start.Row >= sourceRange.Start.Row && mergeRange.End.Row <= sourceRange.End.Row
                    && mergeRange.Start.Column >= sourceRange.Start.Column && mergeRange.End.Column <= sourceRange.End.Column)
                {
                    sourceMergeList.Add(merge);
                }
            }
            // 2. éåŽ†ä¸´æ—¶åˆ—è¡¨ï¼Œå®‰å…¨åœ°åˆ›å»ºç›®æ ‡åˆå¹¶åŒºåŸŸ
            foreach (var merge in sourceMergeList)
            {
                var mergeRange = worksheet.Cells[merge];
                int rowOffset = targetRange.Start.Row - sourceRange.Start.Row;
                int colOffset = targetRange.Start.Column - sourceRange.Start.Column;
                var targetMergeRange = worksheet.Cells[
                    mergeRange.Start.Row + rowOffset,
                    mergeRange.Start.Column + colOffset,
                    mergeRange.End.Row + rowOffset,
                    mergeRange.End.Column + colOffset
                ];
                targetMergeRange.Merge = true;
            }
        }
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/PLCEnum/R_PLCDBName.cs
@@ -46,6 +46,19 @@
        /// </summary>
        rboolLocation4ScanStart,
        /// <summary>
        /// å·¥ä½2物料信息确认启动
        /// </summary>
        rboolLocation5ScanStart,
        /// <summary>
        /// åŽ‹è£…å®ŒæˆåŽä¿¡æ¯ä¸Šä¼ å¯åŠ¨
        /// </summary>
        rboolLocation6ScanStart,
        /// <summary>
        /// æ£€æµ‹å®ŒæˆåŽä¿¡æ¯ä¸Šä¼ å¯åЍ
        /// </summary>
        rboolLocation7ScanStart,
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹æ£€æµ‹é«˜åº¦
        /// </summary>
        rrealDetectPressHeight,
@@ -58,6 +71,26 @@
        /// </summary>
        rrealDetectScrewAngle,
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹åŽ‹åŠ›
        /// </summary>
        rrealDetectPressForce,
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_by拧紧NG
        /// </summary>
        rrealPressScrewByScrewNG,
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_by拧紧OK
        /// </summary>
        rrealPressScrewByScrewOK,
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_by本次加工未完成
        /// </summary>
        rrealPressScrewByProcessUnfinished,
        /// <summary>
        /// æ£€æµ‹_by本次检测未完成
        /// </summary>
        rrealDetectByInspectUnfinished,
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦1
        /// </summary>
        rrealDetectHeight1,
@@ -69,5 +102,14 @@
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦3
        /// </summary>
        rrealDetectHeight3,
        /// <summary>
        /// åŽ‹è£…ä½æ‰˜ç›˜ç ä¿å­˜
        /// </summary>
        rrealPressPalletCode,
        /// <summary>
        /// æ£€æµ‹ä½æ‰˜ç›˜ç ä¿å­˜
        /// </summary>
        rrealCheckPalletCode,
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/PLCEnum/W_PLCDBName.cs
@@ -33,6 +33,23 @@
        /// </summary>
        wboolLocation4ScanDone,
        /// <summary>
        /// å·¥ä½2物料信息确认完成
        /// </summary>
        wboolLocation5ScanDone,
        /// <summary>
        /// åŽ‹è£…å®ŒæˆåŽä¿¡æ¯ä¸Šä¼ å®Œæˆ
        /// </summary>
        wboolLocation6ScanDone,
        /// <summary>
        /// æ£€æµ‹å®ŒæˆåŽä¿¡æ¯ä¸Šä¼ å®Œæˆ
        /// </summary>
        wboolLocation7ScanDone,
        /// <summary>
        /// åŽ‹è£…ä½ä¸æ‹§ç´§
        /// </summary>
        wboolLocation8ScanDone,
        /// <summary>
        /// åŽ‹è£…ä½äº§å“é•¿åº¦
        /// </summary>
        wrealProductLength,
@@ -51,34 +68,40 @@
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ‰­åŠ›
        /// </summary>
        wrealScrewTorqueOutput,
        wrealScrewTorque,
        /// <summary>
        /// åŽ‹è£…ä½è‡ªåŠ¨æ‹§ç´§æ‰“å¼€
        /// åŽ‹è£…ä½è‡ªåŠ¨æ‹§ç´§ç¨‹åºå·
        /// </summary>
        wDintAutoScrewOn,
        wrealAutoScrewProgramNo,
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离1
        /// P0P2宽度
        /// </summary>
        wrealXDirectionDistance1,
        wrealP0P2Width,
        /// <summary>
        /// æ£€æµ‹ä½Z高度1
        /// P0P3宽度
        /// </summary>
        wrealYDirectionHeight1,
        wrealP0P3Width,
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离2
        /// P1P3高度
        /// </summary>
        wrealXDirectionDistance2,
        wrealP1P3Height,
        /// <summary>
        /// æ£€æµ‹ä½Z高度2
        /// P2P3高度
        /// </summary>
        wrealYDirectionHeight2,
        wrealP2P3Height,
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离3
        /// P0P1宽度
        /// </summary>
        wrealXDirectionDistance3,
        wrealP0P1Width,
        /// <summary>
        /// æ£€æµ‹ä½Z高度3
        /// åŽ‹è£…ä½æ‰˜ç›˜ç 
        /// </summary>
        wrealYDirectionHeight3
        wrealPressPalletCode,
        /// <summary>
        /// æ£€æµ‹ä½æ‰˜ç›˜ç 
        /// </summary>
        wrealCheckPalletCode,
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/SocketClient.cs
ÎļþÃû´Ó ´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketClient.cs ÐÞ¸Ä
@@ -5,9 +5,8 @@
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_DTO.System;
namespace WIDESEAWCS_Tasks
namespace WIDESEAWCS_Common
{
    public class TcpClientExample
    {
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Common/WIDESEAWCS_Common.csproj
@@ -6,4 +6,10 @@
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Spire.XLS">
      <HintPath>..\WIDESEAWCS_BasicInfoService\Spire.XLS.dll</HintPath>
    </Reference>
  </ItemGroup>
</Project>
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_DTO/BasicInfo/ToolingBoardSubmitDto.cs
@@ -8,10 +8,6 @@
{
    public class ToolingBoardSubmitDto
    {
        /// <summary>
        /// å·¥è£…板编号 (必填)
        /// </summary>
        public string ToolingBoardNo { get; set; }
        /// <summary>
        /// æˆå“ç¼–号 (必填)
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IBoxingDetailService.cs
@@ -15,8 +15,7 @@
    {
        public IRepository<Dt_BoxingDetail> Repository { get; }
        //比较零件是否齐全
        public bool IsComponentCodesEqual(List<Dt_BoxingDetail> boxingDetails, List<Dt_FormulaDetail> formulaDetails);
        public bool CheckComponentsMatchExactly(List<string> boxingDetails, List<string> formulaDetails);
        //添加组盘信息
        public WebResponseContent SaveToolingBoardNo(ToolingBoardSubmitDto toolingBoardSubmitDto);
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IProcessInfoService.cs
@@ -14,7 +14,6 @@
    {
        public IRepository<Dt_ProcessInfo> Repository { get; }
        // ä¸‹è½½æµç¨‹å¡
        public WebResponseContent ExportData(Dt_ProcessInfo dt_ProcessInfo);
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_IBasicInfoService/IScanStationService.cs
@@ -1,4 +1,5 @@
using System;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -28,5 +29,9 @@
        public WebResponseContent GetLeftInitialData();
        //更新扫码状态
        public WebResponseContent UpdatePartScannedStatus(UpdatePartScannedStatusRequest updatePartScannedStatusRequest);
        // ä¸‹è½½æµç¨‹å¡
        public WebResponseContent ExportData(Dt_ScanStation dt_ScanStation);
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_Boxing.cs
@@ -26,15 +26,21 @@
        /// <summary>
        /// æˆå“ç¼–号
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "成品编号")]
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "成品编号")]
        public string ProductCode { get; set; }
        /// <summary>
        /// æˆå“åç§°
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "成品名称")]
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "成品名称")]
        public string ProductName { get; set; }
        /// <summary>
        /// æµæ°´å·
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "流水号")]
        public string BoxingNo { get; set; }
        [SugarColumn(IsIgnore = true)]//不参与数据库映射,测试使用
        [Navigate(NavigateType.OneToMany, nameof(Dt_BoxingDetail.BoxingId), nameof(Id))]
        public List<Dt_BoxingDetail> Details { get; set; }
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_Formula.cs
@@ -33,77 +33,89 @@
        /// <summary>
        /// åŽ‹è£…ä½äº§å“é•¿åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits =2, ColumnDescription = "压装位产品长度")]
        public decimal ProductLength { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位产品长度")]
        public decimal? ProductLength { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½äº§å“å®½åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位产品宽度")]
        public decimal ProductWidth { get; set; }
        public decimal? ProductWidth { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½äº§å“é«˜åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位产品高度")]
        public decimal ProductHeight { get; set; }
        public decimal? ProductHeight { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½ä¸æ‹§ç´§
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装位不拧紧")]
        public int? PressNoTighten { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§ä¸‹é™é«˜åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧下降高度")]
        public decimal ScrewDownsetDistance { get; set; }
        public decimal? ScrewDownsetDistance { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ‰­åŠ›
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧扭力")]
        public decimal ScrewTorqueOutput { get; set; }
        public decimal? ScrewTorqueOutput { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½è‡ªåŠ¨æ‹§ç´§æ‰“å¼€
        /// åŽ‹è£…ä½è‡ªåŠ¨æ‹§ç´§ç¨‹åºå·
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位自动拧紧打开")]
        public int DintAutoScrewOn { get; set; }
        [SugarColumn(IsNullable = true, ColumnDescription = "压装位自动拧紧程序号")]
        public int? DintAutoScrewOn { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离1
        /// åŽ‹è£…ä½ç´§å›ºæ‰­çŸ©
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位X偏移距离1")]
        public decimal XDirectionDistance1 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位紧固扭矩", DefaultValue = "0.00")]
        public decimal? PressFastenTorque { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½Z高度1
        /// P0P1宽度
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位Z高度1")]
        public decimal YDirectionHeight1 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "P0P1宽度")]
        public decimal? P0P1Width { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离2
        /// P0P2宽度
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位X偏移距离2")]
        public decimal XDirectionDistance2 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "P0P2宽度")]
        public decimal? P0P2Width { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½Z高度2
        /// P0P3宽度
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位Z高度2")]
        public decimal YDirectionHeight2 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "P0P3宽度")]
        public decimal? P0P3Width { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½X偏移距离3
        /// P1P3高度
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位X偏移距离3")]
        public decimal XDirectionDistance3 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "P1P3高度")]
        public decimal? P1P3Height { get; set; }
        /// <summary>
        /// æ£€æµ‹ä½Z高度3
        /// P2P3高度
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "检测位Z高度3")]
        public decimal YDirectionHeight3 { get; set; }
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "P2P3高度")]
        public decimal? P2P3Height { get; set; }
        /// <summary>
        /// äº§å“å›¾ç‰‡è·¯å¾„
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "产品图片路径")]
        public string ProductImagePath { get; set; }
        [SugarColumn(IsIgnore = true)]//不参与数据库映射,测试使用
        [Navigate(NavigateType.OneToMany, nameof(Dt_FormulaDetail.FormulaId), nameof(Id))]
        public List<Dt_FormulaDetail> Details { get; set; }
    }
}
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_FormulaDetail.cs
@@ -25,19 +25,25 @@
        /// <summary>
        /// é›¶ä»¶ç¼–号
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "零件编号")]
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件编号")]
        public string ComponentCode { get; set; }
        /// <summary>
        /// é›¶ä»¶åç§°
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "零件名称")]
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件名称")]
        public string ComponentName { get; set; }
        /// <summary>
        /// ä¾›æ–¹ä»£ç 
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "供方代码")]
        public string SupplierCode { get; set; }
        /// <summary>
        /// æ˜¯å¦æ‰«ç 
        /// </summary>
         [SugarColumn(IsNullable = false, DefaultValue = "0", ColumnDescription = "是否扫码")]
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "是否扫码")]
        public int IsScanned { get; set; }
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ProcessInfo.cs
@@ -36,75 +36,111 @@
        public string ProductName { get; set; }
        /// <summary>
        /// æµæ°´å·
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "流水号")]
        public string ProductSn { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_拧紧NG
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_拧紧NG")]
        public int? PressTightenNg { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_拧紧OK
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_拧紧OK")]
        public int? PressTightenOk { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_本次加工未完成
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_本次加工未完成")]
        public int? PressTightenUnfinished { get; set; }
        /// <summary>
        /// æ£€æµ‹_本次检测未完成
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "检测_本次检测未完成")]
        public int? CheckUnfinished { get; set; }
        /// <summary>
        /// é›¶ä»¶æ•°é‡
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "零件数量")]
        public int ComponentQty { get; set; }
        [SugarColumn(IsNullable = true, ColumnDescription = "零件数量")]
        public int? ComponentQty { get; set; }
        /// <summary>
        /// æ‰­åЛ值
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "扭力值")]
        public decimal TorsioValue { get; set; }
        public decimal? TorsioValue { get; set; }
        /// <summary>
        /// æ‰­åŠ›å€¼æ ‡å‡†
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "扭力值标准")]
        public decimal TorsioValueStandard { get; set; }
        public decimal? TorsioValueStandard { get; set; }
        /// <summary>
        /// åˆšåº¦å€¼
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "刚度值")]
        public decimal StiffnessValue { get; set; }
        public decimal? StiffnessValue { get; set; }
        /// <summary>
        /// åˆšåº¦å€¼æ ‡å‡†
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "刚度值标准")]
        public decimal StiffnessValueStandard { get; set; }
        public decimal? StiffnessValueStandard { get; set; }
        /// <summary>
        /// æµ‹è¯•结果
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "测试结果")]
        public int TestResult { get; set; }
        [SugarColumn(IsNullable = true, ColumnDescription = "测试结果")]
        public int? TestResult { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹æ£€æµ‹é«˜åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位下压检测高度")]
        public decimal PressHeight { get; set; }
        public decimal? PressHeight { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ£€æµ‹æ‰­åŠ›
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧检测扭力")]
        public decimal ScrewTorque { get; set; }
        public decimal? ScrewTorque { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ£€æµ‹è§’åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧检测角度")]
        public decimal ScrewAngle { get; set; }
        public decimal? ScrewAngle { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹åŽ‹åŠ›
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位下压压力")]
        public decimal? PressPressure { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦1
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度1")]
        public decimal Height1 { get; set; }
        public decimal? Height1 { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦2
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度2")]
        public decimal Height2 { get; set; }
        public decimal? Height2 { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦3
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度3")]
        public decimal Height3 { get; set; }
        public decimal? Height3 { get; set; }
    }
}
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ProcessInfoDetail.cs
@@ -34,5 +34,114 @@
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "成品名称")]
        public string ProductName { get; set; }
        /// <summary>
        /// æµæ°´å·
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "流水号")]
        public string ProductSn { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_拧紧NG
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_拧紧NG")]
        public int? PressTightenNg { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_拧紧OK
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_拧紧OK")]
        public int? PressTightenOk { get; set; }
        /// <summary>
        /// åŽ‹è£…æ‹§ç´§_本次加工未完成
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "压装拧紧_本次加工未完成")]
        public int? PressTightenUnfinished { get; set; }
        /// <summary>
        /// æ£€æµ‹_本次检测未完成
        /// </summary>
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "检测_本次检测未完成")]
        public int? CheckUnfinished { get; set; }
        /// <summary>
        /// é›¶ä»¶æ•°é‡
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "零件数量")]
        public int? ComponentQty { get; set; }
        /// <summary>
        /// æ‰­åЛ值
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "扭力值")]
        public decimal? TorsioValue { get; set; }
        /// <summary>
        /// æ‰­åŠ›å€¼æ ‡å‡†
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "扭力值标准")]
        public decimal? TorsioValueStandard { get; set; }
        /// <summary>
        /// åˆšåº¦å€¼
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "刚度值")]
        public decimal? StiffnessValue { get; set; }
        /// <summary>
        /// åˆšåº¦å€¼æ ‡å‡†
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "刚度值标准")]
        public decimal? StiffnessValueStandard { get; set; }
        /// <summary>
        /// æµ‹è¯•结果
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "测试结果")]
        public int? TestResult { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹æ£€æµ‹é«˜åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位下压检测高度")]
        public decimal? PressHeight { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ£€æµ‹æ‰­åŠ›
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧检测扭力")]
        public decimal? ScrewTorque { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½æ‹§ç´§æ£€æµ‹è§’åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位拧紧检测角度")]
        public decimal? ScrewAngle { get; set; }
        /// <summary>
        /// åŽ‹è£…ä½ä¸‹åŽ‹åŽ‹åŠ›
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "压装位下压压力")]
        public decimal? PressPressure { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦1
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度1")]
        public decimal? Height1 { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦2
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度2")]
        public decimal? Height2 { get; set; }
        /// <summary>
        /// æ‹§ç´§ä½æ£€æµ‹é«˜åº¦3
        /// </summary>
        [SugarColumn(IsNullable = true, DecimalDigits = 2, ColumnDescription = "拧紧位检测高度3")]
        public decimal? Height3 { get; set; }
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_ScanStation.cs
@@ -36,61 +36,85 @@
        public string StationEndProduct { get; set; }
        /// <summary>
        /// é›¶ä»¶æ•°é‡
        /// ç»„装人员
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "零件数量")]
        public int StationComponentQty { get; set; }
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "组装人员")]
        public string AssembleUser { get; set; }
        /// <summary>
        /// é›¶ä»¶1
        /// é¦–件流水号
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件1")]
        public string StationComponent1 { get; set; }
        [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "首件流水号")]
        public string FirstProductSn { get; set; }
        /// <summary>
        /// é›¶ä»¶2
        /// æœ«ä»¶æµæ°´å·
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件2")]
        public string StationComponent2 { get; set; }
        [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "末件流水号")]
        public string LastProductSn { get; set; }
        /// <summary>
        /// é›¶ä»¶3
        /// æ˜¯å¦æ‰«ç 
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件3")]
        public string StationComponent3 { get; set; }
        /// <summary>
        /// é›¶ä»¶4
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件4")]
        public string StationComponent4 { get; set; }
        /// <summary>
        /// é›¶ä»¶5
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件5")]
        public string StationComponent5 { get; set; }
        /// <summary>
        /// é›¶ä»¶6
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件6")]
        public string StationComponent6 { get; set; }
        /// <summary>
        /// é›¶ä»¶7
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件7")]
        public string StationComponent7 { get; set; }
        /// <summary>
        /// é›¶ä»¶8
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件8")]
        public string StationComponent8 { get; set; }
        /// <summary>
        /// é›¶ä»¶9
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件9")]
        public string StationComponent9 { get; set; }
        /// <summary>
        /// é›¶ä»¶10
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件10")]
        public string StationComponent10 { get; set; }
        [SugarColumn(IsNullable = true, DefaultValue = "0", ColumnDescription = "是否扫码")]
        public int IsScanned { get; set; }
        ///// <summary>
        ///// é›¶ä»¶æ•°é‡
        ///// </summary>
        //[SugarColumn(IsNullable = true, ColumnDescription = "零件数量")]
        //public int StationComponentQty { get; set; }
        ///// <summary>
        ///// é›¶ä»¶1
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件1")]
        //public string StationComponent1 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶2
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件2")]
        //public string StationComponent2 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶3
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件3")]
        //public string StationComponent3 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶4
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件4")]
        //public string StationComponent4 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶5
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件5")]
        //public string StationComponent5 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶6
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件6")]
        //public string StationComponent6 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶7
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件7")]
        //public string StationComponent7 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶8
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件8")]
        //public string StationComponent8 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶9
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件9")]
        //public string StationComponent9 { get; set; }
        ///// <summary>
        ///// é›¶ä»¶10
        ///// </summary>
        //[SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "零件10")]
        //public string StationComponent10 { get; set; }
    }
}
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/BasicInfo/ProcessInfoController.cs
@@ -19,17 +19,5 @@
        }
        /// <summary>
        /// ä¸‹è½½æµç¨‹å¡
        /// </summary>
        /// <param name="dt_ProcessInfo"></param>
        /// <returns></returns>
        [HttpPost, Route("ExportData"), AllowAnonymous]
        public WebResponseContent ExportData([FromBody]  Dt_ProcessInfo dt_ProcessInfo)
        {
            return Service.ExportData(dt_ProcessInfo);
        }
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/BasicInfo/ScanStationController.cs
@@ -77,5 +77,16 @@
            return Service.UpdatePartScannedStatus(updatePartScannedStatusRequest);
        }
        /// <summary>
        /// ä¸‹è½½æµç¨‹å¡
        /// </summary>
        /// <param name="dt_ProcessInfo"></param>
        /// <returns></returns>
        [HttpPost, Route("ExportData"), AllowAnonymous]
        public WebResponseContent ExportData([FromBody] Dt_ScanStation dt_ScanStation)
        {
            return Service.ExportData(dt_ScanStation);
        }
    }
}
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server/Log/È«¾ÖÈÕÖ¾AOP_1766486446.log
ÎļþÒÑɾ³ý
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/obj/Debug/net6.0/WIDESEAWCS_TaskInfoService.AssemblyInfo.cs
@@ -14,7 +14,7 @@
[assembly: System.Reflection.AssemblyCompanyAttribute("WIDESEAWCS_TaskInfoService")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2eea48595c784d1d6d58d526f1da12427dfa0a25")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ba8aa925e7901381ceb394adb53eca8723d1c4c5")]
[assembly: System.Reflection.AssemblyProductAttribute("WIDESEAWCS_TaskInfoService")]
[assembly: System.Reflection.AssemblyTitleAttribute("WIDESEAWCS_TaskInfoService")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/obj/Debug/net6.0/WIDESEAWCS_TaskInfoService.AssemblyInfoInputs.cache
@@ -1 +1 @@
c9c87e496556920f27ef09770ceb3d9cdc2a9b9b20ce0dfcd54bba65b5fd5b5e
c6989e39d044e493a5b0c470e8b5c9f7045d0148725be4e9d86c645b9e91d362
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Tasks/PLCJob.cs
@@ -1,10 +1,15 @@
using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using Quartz;
using System.Linq;
using System.Text;
using WIDESEAWCS_BasicInfoService;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.PLCEnum;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_IBasicInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -45,7 +50,7 @@
        }
        public Task Execute(IJobExecutionContext context)
        {
            bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
            if (flag && value != null)
            {
@@ -54,33 +59,43 @@
                    OtherDevice device = (OtherDevice)value;
                    try
                    {
                        if (!device.IsConnected) throw new Exception(device.DeviceName + "连接失败");
                        var Heart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolHeart);
                        var EMG = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolEMG);
                        var AutoExecuting = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolAutoExecuting);
                        var OnlineExecuting = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolOnlineExecuting);
                        var Error = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolError);
                        if (Heart && !EMG && AutoExecuting && OnlineExecuting && !Error)
                        if (/*Heart &&*/ !EMG && AutoExecuting && OnlineExecuting && !Error)
                        {
                            #region ä¸Šçº¿æ‰«ç 
                            HandleOnlineScan(device);
                            #endregion
                            //#region é›¶ä»¶æ£€æµ‹
                            //HandlePartDetection(device);
                            //#endregion
                            //#region ä¸Šçº¿æ‰«ç 
                            //HandleOnlineScan(device);
                            //#endregion
                            #region åŽ‹è£…æ‰«ç 
                            HandlePressScan(device);
                            #endregion
                            #region åŽ‹è£…ä¿¡æ¯ä¸Šä¼ 
                            HandlePressInfoUpload(device);
                            #endregion
                            #region æ£€æµ‹æ‰«ç 
                            HandleDetectScan(device);
                            #endregion
                            #region æ£€æµ‹ä¿¡æ¯ä¸Šä¼ 
                            HandleDetectInfoUpload(device);
                            #endregion
                            #region ä¸‹çº¿æ‰«ç 
                            HandleOfflineScan(device);
                            #endregion
                        }
                    }
                    catch (Exception ex)
                    {
@@ -91,50 +106,159 @@
            return Task.CompletedTask;
        }
        /// <summary>
        /// é›¶ä»¶æ£€æµ‹
        /// </summary>
        /// <param name="device"></param>
        /// <exception cref="InvalidOperationException"></exception>
        private void HandlePartDetection(OtherDevice device)
        {
            //DB800.1.4
            var Location5ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation5ScanStart);
            var Location5ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation5ScanDone);
            if (Location5ScanStart && !Location5ScanDone)
            {
                try
                {
                    if (_scanStationService.Repository.QueryFirst(x => x.StationCode == "001").IsScanned == 0)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                        return;
                    }
                    Dt_Boxing dt_Boxing = _boxingService.Repository.QueryData(x => true, 1, "Id desc").FirstOrDefault();
                    if (dt_Boxing == null)
                    {
                        throw new InvalidOperationException("无组盘数据");
                    }
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_Boxing.ProductCode);
                    if (dt_Formula == null)
                    {
                        throw new InvalidOperationException("无成品配方");
                    }
                    List<Dt_BoxingDetail> dt_BoxingDetails = _boxingDetailService.Repository.QueryData(x => x.BoxingId == dt_Boxing.Id);
                    List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == dt_Formula.Id && x.IsScanned == 1);
                    if (!_boxingDetailService.CheckComponentsMatchExactly(dt_BoxingDetails.Select(x => x.ComponentCode).ToList(), dt_FormulaDetails.Select(x => x.ComponentCode).ToList()))
                    {
                        throw new InvalidOperationException("零件与配方表中不同");
                    }
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                }
                catch (Exception ex)
                {
                    WriteError(device.DeviceName, "检测零件流程执行异常", ex);
                }
            }
            else if (!Location5ScanStart && Location5ScanDone)
            {
                device.SetValue(W_PLCDBName.wboolLocation5ScanDone, false);
            }
        }
        /// <summary>
        /// ä¸Šçº¿æ‰«ç 
        /// </summary>
        /// <param name="device"></param>
        private void HandleOnlineScan(OtherDevice device)
        {
            var Location1ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation1ScanStart);
            var Location1ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation1ScanDone);
            if (Location1ScanStart && !Location1ScanDone)//控制扫码枪扫描托盘码,根据托盘码查询组盘数据,判断托盘绑定成品是否已绑定所有所需零件
            //DB800.1.4
            var Location5ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation5ScanStart);
            var Location5ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation5ScanDone);
            if (Location5ScanStart && !Location5ScanDone)//控制扫码枪扫描托盘码,根据托盘码查询组盘数据,判断托盘绑定成品是否已绑定所有所需零件
            {
                Dt_Boxing dt_Boxing1 = _boxingService.Repository.QueryData(x => true, 1, "Id desc").FirstOrDefault();
                if (dt_Boxing1 != null && dt_Boxing1.ProductCode == null)
                {
                    return;
                }
                //var PalletCode = "PL111";
                var PalletCode = TcpClientExample.Start("192.168.2.120", 2001);
                try
                {
                    if (!PalletCode.IsNotEmptyOrNull())
                    if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                    {
                        throw new InvalidOperationException("托盘为空");
                    }
                    var boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                    if (boxing == null)
                    if (_boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode && x.ProductCode != null) != null)
                    {
                        throw new InvalidOperationException("未添加组盘信息");
                        device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                        throw new InvalidOperationException("托盘以存在");
                    }
                    List<Dt_BoxingDetail> dt_BoxingDetails = _boxingDetailService.Repository.QueryData(x => x.BoxingId == boxing.Id);
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == boxing.ProductCode);
                    if (dt_Formula == null)
                    {
                        throw new InvalidOperationException("无成品配方");
                    }
                    List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == dt_Formula.Id && x.IsScanned == 1);
                    //比较零件是否齐全
                    if (!_boxingDetailService.IsComponentCodesEqual(dt_BoxingDetails, dt_FormulaDetails))
                    {
                        throw new InvalidOperationException("零件有问题,请处理");
                    }
                    device.SetValue(W_PLCDBName.wboolLocation1ScanDone, true);
                    Dt_Boxing dt_Boxing = new Dt_Boxing();
                    dt_Boxing.PalletCode = PalletCode;
                    _boxingService.Repository.AddData(dt_Boxing);
                    //Dt_ScanStation dt_ScanStation = _scanStationService.Repository.QueryFirst(x => x.StationCode == "001");
                    //if (dt_ScanStation == null)
                    //{
                    //    throw new InvalidOperationException("无工位数据");
                    //}
                    //Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_ScanStation.StationEndProduct);
                    //if (dt_Formula == null)
                    //{
                    //    throw new InvalidOperationException("无成品配方");
                    //}
                    //List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == dt_Formula.Id && x.IsScanned == 1);
                    //if (dt_ScanStation.IsScanned == 0)
                    //{
                    //    Dt_Boxing dt_Boxing = new Dt_Boxing
                    //    {
                    //        PalletCode = PalletCode,
                    //        ProductCode = dt_Formula.ProductCode,
                    //        ProductName = dt_Formula.ProductName,
                    //        Creater = "admin",
                    //        CreateDate = new DateTime()
                    //    };
                    //    int id = _boxingService.Repository.AddData(dt_Boxing);
                    //    foreach (var item in dt_FormulaDetails)
                    //    {
                    //        Dt_BoxingDetail dt_BoxingDetail = new Dt_BoxingDetail()
                    //        {
                    //            BoxingId = id,
                    //            ComponentCode = item.ComponentCode,
                    //            ComponentName = item.ComponentName,
                    //            Creater = "admin",
                    //            CreateDate = new DateTime()
                    //        };
                    //        _boxingDetailService.Repository.AddData(dt_BoxingDetail);
                    //    }
                    //    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                    //    return;
                    //}
                    //var boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                    //if (boxing == null)
                    //{
                    //    throw new InvalidOperationException("未添加组盘信息");
                    //}
                    //List<Dt_BoxingDetail> dt_BoxingDetails = _boxingDetailService.Repository.QueryData(x => x.BoxingId == boxing.Id);
                    //if (!_boxingDetailService.CheckComponentsMatchExactly(dt_BoxingDetails.Select(x => x.ComponentCode).ToList(), dt_FormulaDetails.Select(x => x.ComponentCode).ToList()))
                    //{
                    //    throw new InvalidOperationException("零件与配方表中不同");
                    //}
                }
                catch (Exception ex)
                {
                    WriteError(device.DeviceName, "上线扫码流程执行异常", ex);
                }
            }
            else if (!Location1ScanStart && Location1ScanDone)
            else if (!Location5ScanStart && Location5ScanDone)
            {
                device.SetValue(W_PLCDBName.wboolLocation1ScanDone, false);
                device.SetValue(W_PLCDBName.wboolLocation5ScanDone, false);
            }
        }
@@ -144,6 +268,7 @@
        /// <param name="device"></param>
        private void HandlePressScan(OtherDevice device)
        {
            //DB800.1.1
            var Location2ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation2ScanStart);
            var Location2ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation2ScanDone);
            if (Location2ScanStart && !Location2ScanDone)//控制扫码枪扫描托盘码,根据托盘码查询托盘绑定成品加工所需数据,写入PLC
@@ -152,36 +277,40 @@
                try
                {
                    if (!PalletCode.IsNotEmptyOrNull())
                    if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                    {
                        throw new InvalidOperationException("托盘为空");
                        throw new InvalidOperationException("托盘号为空");
                    }
                    Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                    if (dt_Boxing == null)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation2ScanDone, true);
                        throw new InvalidOperationException("托盘为空");
                    }
                    if (dt_Boxing.ProductCode == null && dt_Boxing.BoxingNo == null)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation2ScanDone, true);
                        return;
                    }
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_Boxing.ProductCode);
                    //写入PLC
                    device.SetValue(W_PLCDBName.wrealPressPalletCode, dt_Boxing.Id % 100);
                    if(dt_Formula.PressNoTighten == 1)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation8ScanDone,true);
                    }
                    device.SetValue(W_PLCDBName.wrealProductLength, dt_Formula.ProductLength);
                    device.SetValue(W_PLCDBName.wrealProductWidth, dt_Formula.ProductWidth);
                    device.SetValue(W_PLCDBName.wrealProductHeight, dt_Formula.ProductHeight);
                    device.SetValue(W_PLCDBName.wrealScrewDownsetDistance, dt_Formula.ScrewDownsetDistance);
                    device.SetValue(W_PLCDBName.wrealScrewTorqueOutput, dt_Formula.ScrewTorqueOutput);
                    device.SetValue(W_PLCDBName.wDintAutoScrewOn, dt_Formula.DintAutoScrewOn);
                    //中心高度
                    device.SetValue(W_PLCDBName.wrealScrewTorque, dt_Formula.ScrewTorqueOutput);
                    device.SetValue(W_PLCDBName.wrealAutoScrewProgramNo, dt_Formula.DintAutoScrewOn);
                    //压装扫码完成
                    device.SetValue(W_PLCDBName.wboolLocation2ScanDone, true);
                    //接收数据
                    decimal PressHeight = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectPressHeight);
                    decimal ScrewTorque = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectScrewTorque);
                    decimal ScrewAngle = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectScrewAngle);
                    //添加到数据库
                    Dt_ProcessInfo dt_ProcessInfo = new Dt_ProcessInfo()
                    {
                        PalletCode = PalletCode,
                        ProductCode = dt_Formula.ProductCode,
                        ProductName = dt_Formula.ProductName,
                        PressHeight = PressHeight,
                        ScrewTorque = ScrewTorque,
                        ScrewAngle = ScrewAngle
                    };
                    _processInfoService.Repository.AddData(dt_ProcessInfo);
                }
                catch (Exception ex)
                {
@@ -194,50 +323,123 @@
            }
        }
        /// <summary>
        /// åŽ‹è£…ä¿¡æ¯ä¸Šä¼ 
        /// </summary>
        /// <param name="device"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void HandlePressInfoUpload(OtherDevice device)
        {
            //DB800.1.5
            var Location6ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation6ScanStart);
            var Location6ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation6ScanDone);
            if (Location6ScanStart && !Location6ScanDone)//控制扫码枪扫描托盘码,根据托盘码查询托盘绑定成品加工所需数据,写入PLC
            {
                var PalletNum = device.GetValue<R_PLCDBName, int>(R_PLCDBName.rrealPressPalletCode);
                try
                {
                    if (!PalletNum.IsNotEmptyOrNull())
                    {
                        throw new InvalidOperationException("托盘为空");
                    }
                    Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.Id % 100 == PalletNum);
                    if (dt_Boxing == null)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation6ScanDone, true);
                        throw new InvalidOperationException("未找到组盘数据");
                    }
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_Boxing.ProductCode);
                    //接收数据
                    decimal PressHeight = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectPressHeight);
                    decimal ScrewTorque = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectScrewTorque);
                    decimal ScrewAngle = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectScrewAngle);
                    decimal PressPressure = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectPressForce);
                    bool PressTightenNg = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rrealPressScrewByScrewNG);
                    bool PressTightenOk = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rrealPressScrewByScrewOK);
                    bool PressTightenUnfinished = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rrealPressScrewByProcessUnfinished);
                    //添加到数据库
                    Dt_ProcessInfo dt_ProcessInfo = new Dt_ProcessInfo()
                    {
                        PalletCode = dt_Boxing.PalletCode,
                        ProductCode = dt_Formula.ProductCode,
                        ProductName = dt_Formula.ProductName,
                        ProductSn = dt_Boxing.BoxingNo,
                        PressTightenNg = PressTightenNg?1:0,
                        PressTightenOk = PressTightenOk?1:0,
                        PressTightenUnfinished = PressTightenUnfinished?1:0,
                        PressHeight = PressHeight,
                        ScrewTorque = ScrewTorque,
                        ScrewAngle = ScrewAngle,
                        PressPressure = PressPressure,
                    };
                    _processInfoService.Repository.AddData(dt_ProcessInfo);
                    // åŽ‹è£…ä¿¡æ¯ä¸Šä¼ å®Œæˆ
                    device.SetValue(W_PLCDBName.wboolLocation6ScanDone, true);
                }
                catch (Exception ex)
                {
                    WriteError(device.DeviceName, "压装信息上传流程执行异常", ex);
                }
            }
            else if (!Location6ScanStart && Location6ScanDone)
            {
                device.SetValue(W_PLCDBName.wboolLocation6ScanDone, false);
            }
        }
        /// <summary>
        /// æ£€æµ‹æ‰«ç 
        /// </summary>
        /// <param name="device"></param>
        private void HandleDetectScan(OtherDevice device)
        {
            //DB800.1.2
            var Location3ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation3ScanStart);
            var Location3ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation3ScanDone);
            if (Location3ScanStart && !Location3ScanDone)
            {
                var PalletCode = TcpClientExample.Start("192.168.2.122", 2001);
                try
                {
                    if (!PalletCode.IsNotEmptyOrNull())
                    if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                    {
                        throw new InvalidOperationException("托盘为空");
                    }
                    Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                    if (dt_Boxing == null)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation3ScanDone, true);
                        throw new InvalidOperationException("托盘为空");
                    }
                    if (dt_Boxing.ProductCode == null && dt_Boxing.BoxingNo == null)
                    {
                        device.SetValue(W_PLCDBName.wboolLocation3ScanDone, true);
                        return;
                    }
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_Boxing.ProductCode);
                    //写入PLC
                    device.SetValue(W_PLCDBName.wrealXDirectionDistance1, dt_Formula.XDirectionDistance1);
                    device.SetValue(W_PLCDBName.wrealYDirectionHeight1, dt_Formula.YDirectionHeight1);
                    device.SetValue(W_PLCDBName.wrealXDirectionDistance2, dt_Formula.XDirectionDistance2);
                    device.SetValue(W_PLCDBName.wrealYDirectionHeight2, dt_Formula.YDirectionHeight2);
                    device.SetValue(W_PLCDBName.wrealXDirectionDistance3, dt_Formula.XDirectionDistance3);
                    device.SetValue(W_PLCDBName.wrealYDirectionHeight3, dt_Formula.YDirectionHeight3);
                    device.SetValue(W_PLCDBName.wrealCheckPalletCode, dt_Boxing.Id % 100);
                    device.SetValue(W_PLCDBName.wrealP0P1Width, dt_Formula.P0P1Width);
                    device.SetValue(W_PLCDBName.wrealP0P2Width, dt_Formula.P0P2Width);
                    device.SetValue(W_PLCDBName.wrealP0P3Width, dt_Formula.P0P3Width);
                    device.SetValue(W_PLCDBName.wrealP0P3Width, dt_Formula.P0P3Width);
                    device.SetValue(W_PLCDBName.wrealP1P3Height, dt_Formula.P1P3Height);
                    device.SetValue(W_PLCDBName.wrealP2P3Height, dt_Formula.P2P3Height);
                    //检测扫码完成
                    device.SetValue(W_PLCDBName.wboolLocation3ScanDone, true);
                    //接收数据
                    decimal Height1 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight1);
                    decimal Height2 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight2);
                    decimal Height3 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight3);
                    Dt_ProcessInfo dt_ProcessInfo = _processInfoService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                    if (dt_ProcessInfo == null)
                    {
                        throw new InvalidOperationException("成品未压装");
                    }
                    dt_ProcessInfo.Height1 = Height1;
                    dt_ProcessInfo.Height2 = Height2;
                    dt_ProcessInfo.Height3 = Height3;
                    _processInfoService.Repository.UpdateData(dt_ProcessInfo);
                }
                catch (Exception ex)
                {
@@ -252,11 +454,89 @@
        }
        /// <summary>
        /// æ£€æµ‹ä¿¡æ¯ä¸Šä¼ 
        /// </summary>
        /// <param name="device"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void HandleDetectInfoUpload(OtherDevice device)
        {
            //DB800.1.6
            var Location7ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation7ScanStart);
            var Location7ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation7ScanDone);
            if (Location7ScanStart && !Location7ScanDone)
            {
                var PalletNum = device.GetValue<R_PLCDBName, int>(R_PLCDBName.rrealCheckPalletCode);
                try
                {
                    if (!PalletNum.IsNotEmptyOrNull())
                    {
                        throw new InvalidOperationException("托盘为空");
                    }
                    Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.Id % 100 == PalletNum);
                    if (dt_Boxing == null)
                    {
                        throw new InvalidOperationException("未找到组盘数据");
                    }
                    Dt_Formula dt_Formula = _formulaService.Repository.QueryFirst(x => x.ProductCode == dt_Boxing.ProductCode);
                    //接收数据
                    decimal Height1 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight1);//113
                    decimal Height2 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight2);//92
                    decimal Height3 = (decimal)device.GetValue<R_PLCDBName, float>(R_PLCDBName.rrealDetectHeight3);//11
                    bool CheckUnfinished = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rrealDetectByInspectUnfinished);
                    Dt_ProcessInfo dt_ProcessInfo = _processInfoService.Repository.QueryFirst(x => x.PalletCode == dt_Boxing.PalletCode);
                    int id = 0;
                    if (dt_ProcessInfo == null)
                    {
                        dt_ProcessInfo = new Dt_ProcessInfo()
                        {
                            PalletCode = dt_Boxing.PalletCode,
                            ProductCode = dt_Formula.ProductCode,
                            ProductName = dt_Formula.ProductName,
                            ProductSn = dt_Boxing.BoxingNo,
                            CheckUnfinished = CheckUnfinished?1:0,
                        };
                        id = _processInfoService.Repository.AddData(dt_ProcessInfo);
                    }
                    else
                    {
                        id = dt_ProcessInfo.Id;
                    }
                    dt_ProcessInfo.Id = id;
                    dt_ProcessInfo.Height1 = Height1 = Height1 - Height3;
                    dt_ProcessInfo.Height2 = Height2 = Height2 - Height3;
                    dt_ProcessInfo.Height3 = Height3;
                    _processInfoService.Repository.UpdateData(dt_ProcessInfo);
                    //检测信息上传完成
                    device.SetValue(W_PLCDBName.wboolLocation7ScanDone, true);
                }
                catch (Exception ex)
                {
                    WriteError(device.DeviceName, "检测扫码流程执行异常", ex);
                }
            }
            else if (!Location7ScanStart && Location7ScanDone)
            {
                device.SetValue(W_PLCDBName.wboolLocation7ScanDone, false);
            }
        }
        /// <summary>
        /// ä¸‹çº¿æ‰«ç 
        /// </summary>
        /// <param name="device"></param>
        private void HandleOfflineScan(OtherDevice device)
        {
            //DB800.1.3
            var Location4ScanStart = device.GetValue<R_PLCDBName, bool>(R_PLCDBName.rboolLocation4ScanStart);
            var Location4ScanDone = device.GetValue<W_PLCDBName, bool>(W_PLCDBName.wboolLocation4ScanDone);
            if (Location4ScanStart && !Location4ScanDone)//控制扫码枪扫描托盘码,根据托盘码查询组盘数据,判断托盘绑定成品是否已绑定所有所需零件
@@ -266,30 +546,46 @@
                {
                    try
                    {
                        if (!PalletCode.IsNotEmptyOrNull())
                        if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                        {
                            throw new InvalidOperationException("托盘为空");
                        }
                        Dt_ProcessInfo dt_ProcessInfo = _processInfoService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        if (dt_ProcessInfo == null)
                        {
                            throw new InvalidOperationException("成品未压装和检测");
                        }
                        Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        _boxingService.Repository.DeleteData(dt_Boxing);
                        List<Dt_BoxingDetail> dt_BoxingDetails = _boxingDetailService.Repository.QueryData(x => x.BoxingId == dt_Boxing.Id);
                        _boxingDetailService.Repository.DeleteData(dt_BoxingDetails);
                        Dt_ProcessInfoDetail dt_ProcessInfoDetail = new Dt_ProcessInfoDetail()
                        if (dt_Boxing != null)
                        {
                            PalletCode = PalletCode,
                            ProductCode = dt_ProcessInfo.ProductCode,
                            ProductName = dt_ProcessInfo.ProductName,
                            Creater = "admin",
                            CreateDate = DateTime.Now
                        };
                        _processDetailInfoService.Repository.AddData(dt_ProcessInfoDetail);
                        _processInfoService.DeleteData(dt_ProcessInfo);
                            _boxingService.Repository.DeleteData(dt_Boxing);
                            List<Dt_BoxingDetail> dt_BoxingDetails = _boxingDetailService.Repository.QueryData(x => x.BoxingId == dt_Boxing.Id);
                            if (dt_BoxingDetails != null)
                            {
                                _boxingDetailService.Repository.DeleteData(dt_BoxingDetails);
                            }
                        }
                        Dt_ProcessInfo dt_ProcessInfo = _processInfoService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        if (dt_ProcessInfo != null)
                        {
                            Dt_ProcessInfoDetail dt_ProcessInfoDetail = new Dt_ProcessInfoDetail()
                            {
                                PalletCode = PalletCode,
                                ProductCode = dt_ProcessInfo.ProductCode?.ToString() ?? "",
                                ProductName = dt_ProcessInfo.ProductName?.ToString() ?? "",
                                ProductSn = dt_ProcessInfo.ProductSn,
                                PressTightenNg = dt_ProcessInfo.PressTightenNg,
                                PressTightenOk = dt_ProcessInfo.PressTightenOk,
                                PressTightenUnfinished = dt_ProcessInfo.PressTightenUnfinished,
                                CheckUnfinished = dt_ProcessInfo.CheckUnfinished,
                                PressHeight = dt_ProcessInfo.PressHeight,
                                ScrewTorque = dt_ProcessInfo.ScrewTorque,
                                ScrewAngle = dt_ProcessInfo.ScrewAngle,
                                PressPressure = dt_ProcessInfo.PressPressure,
                                Height1 = dt_ProcessInfo.Height1,
                                Height2 = dt_ProcessInfo.Height2,
                                Height3 = dt_ProcessInfo.Height3,
                                Creater = "admin",
                                CreateDate = DateTime.Now
                            };
                            _processDetailInfoService.Repository.AddData(dt_ProcessInfoDetail);
                            _processInfoService.DeleteData(dt_ProcessInfo);
                        }
                        uow.Commit();
                        //下线扫码完成
                        device.SetValue(W_PLCDBName.wboolLocation4ScanDone, true);
@@ -297,12 +593,13 @@
                    catch (Exception ex)
                    {
                        WriteError(device.DeviceName, "下线扫码流程执行异常", ex);
                    }
                }
            }
            else if (!Location4ScanStart && Location4ScanDone)
            {
                device.SetValue(W_PLCDBName.wboolLocation2ScanDone, false);
                device.SetValue(W_PLCDBName.wboolLocation4ScanDone, false);
            }
        }
    }