Przeglądaj źródła

新增布点派单和显示

695593266@qq.com 4 miesięcy temu
rodzic
commit
87eb5ae3a6

+ 18 - 0
src/api/produceOrder/index.js

@@ -277,3 +277,21 @@ export async function getMyPage(params) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+
+//工序布点信息
+export async function getPlanDotLine(data) {
+  const res = await request.post('/aps/planrouting/detailList', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//计划的布点信息列表
+export async function listPlanDotLine(data) {
+  const res = await request.post('/aps/planrouting/planTaskInstance', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 317 - 0
src/views/produceOrder/components/details/dotLineDetail.vue

@@ -0,0 +1,317 @@
+<template>
+  <div class="plan-dot-line">
+    <div class="top-route">
+      <div class="panel-title">工艺路线</div>
+      <el-empty
+        v-if="dotLineTaskList.length === 0"
+        description="暂无工艺路线"
+      ></el-empty>
+      <div v-else class="route-line">
+        <div
+          v-for="(item, index) in dotLineTaskList"
+          :key="`route-seg-${item._taskKey}`"
+          class="route-segment"
+        >
+          <span
+            class="route-node"
+            :class="{ 'route-node--done': isDotLineTaskDone(item) }"
+          >
+            {{ getDotLineTaskName(item, index) }}
+          </span>
+          <span
+            v-if="index < dotLineTaskList.length - 1"
+            class="route-arrow"
+            aria-hidden="true"
+            >→</span
+          >
+        </div>
+      </div>
+    </div>
+    <div class="config-panel">
+      <div class="panel-title">工艺配置</div>
+      <el-empty
+        v-if="dotLineTaskList.length === 0"
+        description="暂无工艺"
+      ></el-empty>
+      <div v-else class="task-config-table-wrap">
+        <el-table
+          :data="dotLineTaskList"
+          border
+          size="small"
+          row-key="_taskKey"
+          max-height="420"
+          class="config-table"
+        >
+          <el-table-column
+            type="index"
+            label="序号"
+            width="48"
+            align="center"
+          />
+          <el-table-column
+            label="工序名称"
+            min-width="100"
+            show-overflow-tooltip
+            class-name="task-name-cell"
+            align="center"
+          >
+            <template slot-scope="{ row, $index }">
+              <span class="task-name-text">{{
+                getDotLineTaskName(row, $index)
+              }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="执行模式" min-width="100" align="center">
+            <template slot-scope="{ row }">
+              {{ executionTypeLabel(row.executionType) }}
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="执行班组"
+            min-width="130"
+            align="center"
+            prop="executionTeamName"
+          />
+          <el-table-column
+            label="执行开始时间"
+            min-width="168"
+            align="center"
+            prop="executionStartTime"
+          />
+          <el-table-column
+            label="执行结束时间"
+            min-width="168"
+            align="center"
+            prop="executionEndTime"
+          />
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import { getPlanDotLine } from '@/api/produceOrder/index';
+  const EXEC_TYPE_MAP = { 0: '自制', 1: '请托', 2: '委外' };
+  export default {
+    props: {
+      workOrderInfo: {
+        type: Object,
+        default: () => ({})
+      }
+    },
+    data() {
+      return {
+        dotLineTaskList: [],
+        hasDotLineDetail: false
+      };
+    },
+
+    computed: {
+      executionTypeLabel() {
+        return (val) => EXEC_TYPE_MAP[val] ?? '';
+      }
+    },
+
+    watch: {
+      'workOrderInfo.productionPlanId': {
+        immediate: true,
+        handler() {
+          this.loadDotLineData();
+        }
+      }
+    },
+
+    methods: {
+      normalizeDotLineItem(item, index) {
+        return {
+          ...item,
+          _taskKey:
+            item.id ??
+            item.taskId ??
+            item.produceTaskId ??
+            item.taskSort ??
+            `${index}-${item.taskTypeName || item.taskName || ''}`
+        };
+      },
+
+      getDotLineTaskName(item, index) {
+        return (
+          item.taskTypeName ||
+          item.taskName ||
+          item.produceTaskName ||
+          item.name ||
+          `工序${index + 1}`
+        );
+      },
+
+      isDotLineTaskDone(item) {
+        const status = Number(item.status ?? item.flag ?? item.taskStatus);
+        return (
+          [3, 4, 5, 6, 9].includes(status) ||
+          !!item.executionEndTime ||
+          !!item.completeTime ||
+          Number(item.finished) === 1
+        );
+      },
+
+      async loadDotLineData() {
+        if (!this.workOrderInfo.productionPlanId) {
+          this.resetDotLineState();
+          return;
+        }
+        try {
+          const planData = await getPlanDotLine({
+            planId: this.workOrderInfo.productionPlanId
+          });
+          const details = planData?.detailList;
+          if (!Array.isArray(details) || details.length === 0) {
+            this.resetDotLineState();
+            return;
+          }
+          this.hasDotLineDetail = true;
+          console.log(details, 'details');
+          this.dotLineTaskList = details
+            .slice()
+            .sort((a, b) => (a.taskSort ?? 0) - (b.taskSort ?? 0))
+            .map((item, i) => this.normalizeDotLineItem(item, i));
+        } catch {
+          this.resetDotLineState();
+        }
+      },
+
+      resetDotLineState() {
+        this.hasDotLineDetail = false;
+        this.dotLineTaskList = [];
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .top-box {
+    display: flex;
+    margin-bottom: 10px;
+    .item-box {
+      flex: 1;
+    }
+  }
+
+  .radio-box {
+    margin: 10px 0;
+  }
+
+  .table {
+    margin-top: 20px;
+  }
+
+  ::v-deep .el-radio-button__orig-radio:checked + .el-radio-button__inner {
+    box-shadow: none;
+  }
+
+  ::v-deep .el-input.is-disabled .el-input__inner {
+    color: #ab7777;
+  }
+
+  .plan-dot-line,
+  .top-route,
+  .config-panel,
+  .route-line {
+    width: 100%;
+    max-width: 100%;
+    min-width: 0;
+    box-sizing: border-box;
+  }
+
+  .plan-dot-line {
+    min-height: 200px;
+  }
+
+  .top-route,
+  .config-panel {
+    border: 1px solid #ebeef5;
+    border-radius: 4px;
+    padding: 12px;
+    background: #fff;
+  }
+
+  .config-panel {
+    margin-top: 12px;
+  }
+
+  .panel-title {
+    font-size: 14px;
+    font-weight: 600;
+    margin-bottom: 10px;
+  }
+
+  .route-line {
+    display: flex;
+    flex-wrap: nowrap;
+    align-items: stretch;
+    color: #303133;
+  }
+
+  .route-segment {
+    flex: 1 1 0;
+    min-width: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .route-node {
+    flex: 0 1 auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    min-width: 0;
+    min-height: 22px;
+    border-radius: 4px;
+    padding: 2px 10px;
+    color: #fff;
+    background: #909399;
+    font-size: clamp(10px, 2.6vw, 12px);
+    font-weight: 600;
+    line-height: 1.2;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    text-align: center;
+  }
+
+  .route-node--done {
+    background: #56bf1d;
+  }
+
+  .route-arrow {
+    flex: 1 1 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #909399;
+    font-size: clamp(14px, 2.5vw, 18px);
+    line-height: 1;
+  }
+
+  .task-config-table-wrap {
+    width: 100%;
+  }
+
+  .config-table ::v-deep {
+    .el-table th > .cell,
+    .el-table td > .cell {
+      font-size: 14px;
+      text-align: center;
+    }
+    .el-table__body .cell {
+      padding-left: 6px;
+      padding-right: 6px;
+    }
+    td.task-name-cell .task-name-text {
+      font-size: 14px;
+      font-weight: 500;
+      line-height: 1.4;
+    }
+  }
+</style>

+ 6 - 2
src/views/produceOrder/components/details/index.vue

@@ -101,6 +101,9 @@
               :workOrderInfo="workOrderInfo"
             ></checkList>
           </el-tab-pane>
+          <el-tab-pane label="布点详情" name="dot">
+            <dotLineDetail :workOrderInfo="workOrderInfo"></dotLineDetail>
+          </el-tab-pane>
         </el-tabs>
       </div>
     </el-drawer>
@@ -117,7 +120,7 @@
   import pickDetails from '../../details.vue';
   import recordRules from '../recordRules/recordRules.vue';
   import checkList from '@/views/checklistManagement/checklist.vue';
-
+  import dotLineDetail from './dotLineDetail.vue';
   export default {
     components: {
       Info,
@@ -126,7 +129,8 @@
       productionDetails,
       pickDetails,
       recordRules,
-      checkList
+      checkList,
+      dotLineDetail
     },
     data() {
       return {

+ 1609 - 0
src/views/produceOrder/components/releaseDialog/planDotLineReleaseDialog.vue

@@ -0,0 +1,1609 @@
+<template>
+  <ele-modal
+    :before-close="cancel"
+    :close-on-click-modal="false"
+    :maxable="true"
+    title="任务派单"
+    :visible.sync="dispatchVisible"
+    :width="modelWidth"
+    append-to-body
+    custom-class="ele-dialog-form"
+  >
+    <div class="form-wrapper">
+      <el-form
+        ref="form"
+        :inline="true"
+        :model="form"
+        label-position="right"
+        label-width="100px"
+      >
+        <el-row :gutter="10" class="basic" style="flex-wrap: wrap" type="flex">
+          <el-col
+            v-for="item in fieldList"
+            :key="item.prop"
+            :lg="8"
+            :md="12"
+            :sm="12"
+            :xl="6"
+            :xs="12"
+          >
+            <el-form-item :label="item.label">
+              <!-- <div class="item_label">{{ current[item.prop] }}</div> -->
+              <el-input v-model="current[item.prop]" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :lg="8" :md="12" :sm="12" :xl="6" :xs="12">
+            <el-form-item label="所属工厂:">
+              <el-input v-model="form.factoryName" :disabled="true"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :lg="8" :md="12" :sm="12" :xl="6" :xs="12">
+            <el-form-item label="所属工作中心:">
+              <el-select
+                v-model="form.workCenterId"
+                placeholder="请选择"
+                style="width: 100%"
+                @change="changeWork"
+              >
+                <el-option
+                  v-for="item in workCenterList"
+                  :key="item.centerId"
+                  :label="item.centerName"
+                  :value="item.centerId"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :lg="8" :md="12" :sm="12" :xl="6" :xs="12">
+            <el-form-item label="所属班组:">
+              <el-input
+                v-if="form.taskAss == 0"
+                style="width: 100%"
+                v-model="form.teamName"
+                disabled
+                placeholder=" "
+              />
+              <el-select
+                v-else
+                style="width: 100%"
+                v-model="form.teamId"
+                placeholder="请选择"
+                @change="changeGroups"
+              >
+                <el-option
+                  v-for="item in teamList"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-tabs
+          v-model="processId"
+          v-loading="tabsLoading"
+          class="process_list"
+          style="margin-bottom: 20px"
+          type="border-card"
+          @tab-click="handleClick"
+        >
+          <el-tab-pane
+            v-for="(item, index) in processList"
+            :key="item.id"
+            :label="item.name"
+            :name="item.id"
+          >
+            <span style="color: green">
+              工序编码:{{ item.code }},所属班组:{{
+                item.teamName
+              }},执行模式:{{ formatExecutionType(item.executionType) }}</span
+            >
+            <ele-pro-table
+              :ref="`tableRef${index}`"
+              v-loading="tabLoading"
+              :columns="columns"
+              :datasource="item.list"
+              :pageSize="20"
+              :selection.sync="item.selection"
+              cache-key="systemRoleTable"
+              row-key="id"
+              class="table"
+            >
+              <template v-slot:toolbar>
+                <div style="display: inline-block" v-if="!item.isSpecialField">
+                  <el-button
+                    :loading="toolbarLoading"
+                    type="primary"
+                    @click="dispatch(item, 1)"
+                    :disabled="!item.isDisable"
+                  >
+                    派单
+                  </el-button>
+                  <el-button
+                    :loading="toolbarLoading"
+                    type="primary"
+                    @click="dispatch(item, 2)"
+                    :disabled="!item.isDisable"
+                  >
+                    撤回
+                  </el-button>
+                  <el-button
+                    :loading="toolbarLoading"
+                    type="primary"
+                    @click="dispatch(item, 3)"
+                    :disabled="!item.isDisable"
+                  >
+                    保存
+                  </el-button>
+
+                  <el-button
+                    type="success"
+                    @click="addStation(item, index)"
+                    :loading="toolbarLoading"
+                    :disabled="!item.isDisable || item.assignType == 3"
+                  >
+                    添加工位
+                  </el-button>
+                </div>
+                <div
+                  style="margin-left: 50px; display: inline-block"
+                  v-if="!item.isSpecialField"
+                >
+                  <span
+                    class="text"
+                    style="
+                      font-weight: bold;
+                      font-size: 14px;
+                      margin-right: 8px;
+                    "
+                    >指派:</span
+                  >
+                  <el-radio-group
+                    v-model="item.assignType"
+                    size="mini"
+                    @change="(e) => changeRadio(e, index)"
+                  >
+                    <el-radio-button
+                      :disabled="radioBun(item, 'stationDis')"
+                      :label="1"
+                      >工位
+                    </el-radio-button>
+                    <!-- <el-radio-button
+                      :disabled="radioBun(item, 'staffDis')"
+                      :label="2"
+                      >人员
+                    </el-radio-button> -->
+                    <el-radio-button
+                      :disabled="radioBun(item, 'lineDis')"
+                      :label="3"
+                      >产线
+                    </el-radio-button>
+                  </el-radio-group>
+                </div>
+                <div
+                  v-if="item.isSpecialField"
+                  class="describe"
+                  style="color: #67c23a"
+                >
+                  该工序已完成派单!
+                </div>
+
+                <div
+                  style="margin-left: 50px; display: inline-block"
+                  v-if="timeSlot(item)"
+                >
+                  时间段: {{ item.startDate }} ----- {{ item.endDate }}
+                </div>
+              </template>
+              <template v-slot:quantity="{ row }">
+                <el-input
+                  v-model="row.quantity"
+                  :disabled="row.disposalStatus == 1"
+                  placeholder="请输入数量"
+                  type="number"
+                  @input="(e) => handleQuantityInput(e, row, item)"
+                ></el-input>
+              </template>
+              <template v-slot:weight="{ row }">
+                <el-input
+                  v-model="row.weight"
+                  :disabled="row.disposalStatus == 1"
+                  placeholder="请输入重量"
+                  type="number"
+                  @input="(e) => handleWeightInput(e, row, item)"
+                ></el-input>
+              </template>
+              <template v-slot:teamTimeIds="{ row }">
+                <el-select
+                  v-model="row.teamTimeIds"
+                  multiple
+                  placeholder="班次"
+                  :disabled="row.disposalStatus == 1"
+                  @change="(e) => shiftSelection(e, row, item)"
+                >
+                  <el-option
+                    v-for="item in shiftList"
+                    :key="item.id"
+                    :label="item.dutyName"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </template>
+              <template v-slot:startTime="{ row }">
+                <el-date-picker
+                  v-model="row.startTime"
+                  :disabled="row.disposalStatus == 1"
+                  @change="handleStartTimeChange(row, item)"
+                  class="w100"
+                  placeholder="开始时间"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                ></el-date-picker>
+              </template>
+              <template v-slot:endTime="{ row }">
+                <el-date-picker
+                  v-model="row.endTime"
+                  :disabled="row.disposalStatus == 1"
+                  class="w100"
+                  placeholder="完成时间"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                ></el-date-picker>
+              </template>
+
+              <template v-slot:action="{ row }">
+                <!--  :disabled="resetBtnDis(row)" -->
+                <el-popconfirm
+                  v-if="resetBtnDis(row)"
+                  title="确定要重置该条数据吗?"
+                  @confirm="resetData(row, item)"
+                >
+                  <template v-slot:reference>
+                    <el-link :underline="false" type="primary"> 重置</el-link>
+                  </template>
+                </el-popconfirm>
+              </template>
+            </ele-pro-table>
+          </el-tab-pane>
+        </el-tabs>
+      </el-form>
+    </div>
+
+    <!--    <div slot="footer">-->
+    <!--      <el-button plain @click="cancel">取消</el-button>-->
+    <!--      <el-button :loading="toolbarLoading" type="primary" @click="confirm"-->
+    <!--      >确定-->
+    <!--      </el-button-->
+    <!--      >-->
+    <!--    </div>-->
+
+    <choose-station
+      ref="chooseStationRef"
+      @chooseStationList="chooseStationList"
+    ></choose-station>
+  </ele-modal>
+</template>
+
+<script>
+  import validDate from '@/utils/date';
+  import {
+    lineByCurrentUser,
+    listAssign,
+    listByFirstTaskId,
+    listByMesWorkOrder,
+    listUserByIds,
+    resetAssignee,
+    taskAssignment,
+    taskRevoked,
+    taskSave,
+    listByFactoryId
+  } from '@/api/mainData/index.js';
+  import { getUserInfo, listPlanDotLine } from '@/api/produceOrder/index.js';
+  import chooseStation from '../chooseStation.vue';
+
+  export default {
+    components: { chooseStation },
+    props: {
+      current: {
+        type: Object,
+        default: () => {}
+      },
+      dispatchVisible: {
+        type: Boolean,
+        default: false
+      }
+    },
+    data() {
+      return {
+        processId: '',
+        tabLoading: false,
+        dynamicName: '工位名称',
+        form: {
+          assignType: 1,
+          crewIds: '',
+          workstationIds: '',
+          teamId: '',
+          singleReport: '',
+          workCenterId: '',
+          taskAss: 1,
+          factoryName: ''
+        },
+        toolbarLoading: false,
+        processList: [],
+        workCenterList: [],
+        teamList: [],
+        tabsLoading: false,
+        stationList: [], // 工位的数据
+        productionList: [], // 产线的数据
+        crewList: [], // 人员的数据
+        // procTaskDis: false, // 工序任务派单选择
+        // firstTaskindex: '', // 首工序id 对应的工序列表数据下标
+        fieldList: [
+          { label: '生产订单号:', prop: 'code' },
+          { label: '计划编号:', prop: 'productionPlanCode' },
+          { label: '工艺路线:', prop: 'produceRoutingName' },
+          // { label: '编码', prop: 'productCode' },
+          { label: '名称:', prop: 'productName' },
+          { label: '生产编号:', prop: 'productionCodes' },
+          { label: '牌号:', prop: 'brandNo' },
+          { label: '批次号:', prop: 'batchNo' },
+          { label: '型号:', prop: 'model' },
+          { label: '要求生产数量:', prop: 'formingNum' },
+          { label: '要求生产重量:', prop: 'initialWeight' },
+          { label: '计划开始时间:', prop: 'planStartTime' },
+          { label: '计划结束时间:', prop: 'planCompleteTime' }
+        ],
+        shiftList: [],
+        dateValue: '',
+        factoriesId: '', // 工厂id
+        dispatchType: 1,
+        time_calc_code: '0', // 是否进行时间赋值 0 否 1 是
+        validDate,
+        userTeamList: [],
+        cachedUserData: null
+      };
+    },
+    computed: {
+      clientEnvironmentId() {
+        return this.$store.state.user.info.clientEnvironmentId;
+      },
+      userInfo() {
+        return this.$store.state.user.info;
+      },
+      modelWidth() {
+        // if(this.form.taskAss == 1){
+        //   return '1000px'
+        // }
+        return '75vw';
+      },
+      // 重置按钮 的置灰权限 没有进行操作跟派单的数据 置灰
+      resetBtnDis() {
+        return (row) => {
+          if (!row.status) return false;
+          let flag = row.status.code != 1;
+          return flag;
+        };
+      },
+      // 指派单选框操作 已派单的 其它两个按钮不能操作
+      radioBun() {
+        return (row, type) => {
+          if (!row.radioBun) return false;
+          let flag = row.radioBun[type];
+          return flag;
+        };
+      },
+      // 列表输入框操作 已派单的不能操作
+      permissions() {
+        return (row, item) => {
+          if (item.isSpecialField) return true;
+          if (!row.status) return false;
+          if (row.status.code == 1) return true;
+        };
+      },
+      // 时间段显示
+      timeSlot() {
+        return (item) => {
+          if (!item.startDate || !item.endDate) {
+            return false;
+          }
+          return true;
+        };
+      },
+      columns() {
+        return [
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            fixed: 'left',
+            selectable: (row, index) => {
+              return row.disposalStatus != 1;
+            }
+          },
+          {
+            prop: 'name',
+            label: this.dynamicName,
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 200
+          },
+          {
+            prop: 'code',
+            label: '编码',
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 200
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 150,
+            formatter: (row) => {
+              if (!row.status) return '';
+              return row.status.desc || '';
+            }
+          },
+          {
+            prop: 'disposalStatus',
+            label: '接收状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            width: 150,
+            formatter: (row) => {
+              return row.disposalStatus == 1
+                ? '已接收'
+                : row.disposalStatus == 2
+                ? '已拒绝'
+                : '未接收';
+            }
+          },
+
+          {
+            slot: 'quantity',
+            prop: 'quantity',
+            label: '数量',
+            align: 'center',
+            width: 140
+          },
+          {
+            slot: 'weight',
+            prop: 'weight',
+            label: `重量(${this.current.weightUnit})`,
+            align: 'center',
+            width: 140
+          },
+          {
+            slot: 'teamTimeIds',
+            prop: 'teamTimeIds',
+            label: '班次',
+            align: 'center',
+            minWidth: 220
+          },
+          {
+            slot: 'startTime',
+            prop: 'startTime',
+            label: '计划开始时间',
+            align: 'center',
+            minWidth: 240
+          },
+          {
+            slot: 'endTime',
+            prop: 'endTime',
+            label: '计划完成时间',
+            align: 'center',
+            minWidth: 240
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 120,
+            align: 'center',
+            resizable: false,
+            fixed: 'right',
+            slot: 'action'
+          }
+        ];
+      }
+    },
+    watch: {},
+    created() {
+      this.dispatchType = this.current.singleReport || 0;
+      this.workCenterData();
+      this.form.singleReport = this.clientEnvironmentId == 2 ? 0 : 1;
+      this.dateValue = this.getFormattedDate();
+    },
+    methods: {
+      getClassesData() {
+        if (!this.factoriesId) return;
+        listByFactoryId(this.factoriesId).then((res) => {
+          if (!res) return;
+          this.shiftList = res;
+        });
+      },
+      // 获取当前年月日
+      getFormattedDate() {
+        const now = new Date();
+        const year = now.getFullYear();
+        const month = String(now.getMonth() + 1).padStart(2, '0');
+        const date = String(now.getDate()).padStart(2, '0');
+        return `${year}-${month}-${date}`;
+      },
+      async workCenterData() {
+        const userData = await getUserInfo(this.$store.state.user.info.userId);
+        this.cachedUserData = userData;
+        this.factoriesId = userData.factoryId || '';
+        this.form.factoryName = userData.factoryName || '';
+
+        if (!userData.centerList || userData.centerList.length === 0) return;
+
+        const firstCenter = userData.centerList[0];
+        this.form.workCenterId = firstCenter.centerId;
+        this.form.workCenterName = firstCenter.centerName;
+
+        const map = new Map();
+        userData.centerList.forEach((item) => {
+          const { teamId, ...rest } = item;
+          if (!map.has(rest.centerId)) {
+            map.set(rest.centerId, rest);
+          }
+        });
+        this.workCenterList = [...map.values()];
+        this.userTeamList = userData.teamList;
+
+        const teamData = this.userTeamList.filter((item) =>
+          item.workCenterIds.includes(firstCenter.centerId)
+        );
+        this.teamList = teamData || [];
+        if (this.teamList.length !== 0) {
+          this.form.teamId = this.teamList[0].teamId;
+          const td = this.teamList.find(
+            (item) => item.teamId === this.teamList[0].teamId
+          );
+          this.form.teamName = td ? td.teamName : '';
+          try {
+            const res = await listUserByIds([this.teamList[0].teamId]);
+            this.crewList = res || [];
+          } catch {
+            this.crewList = [];
+          }
+        }
+
+        await Promise.all([
+          this.getProductionData(),
+          this.FirstTaskIdFn(),
+          this.getClassesData()
+        ]);
+
+        await this.changeDispatch();
+      },
+
+      async changeDispatch() {
+        if (this.tabsLoading) return;
+        this.tabsLoading = true;
+        try {
+          let allRes = await listPlanDotLine({
+            planId: this.current.productionPlanId,
+            routingId: this.current.produceRoutingId
+          });
+          const userData = this.cachedUserData;
+          if (!userData) return;
+          const teamIdSet = new Set(
+            (userData?.teamList || []).map((it) => it.teamId)
+          );
+          let params = {
+            apsWorkOrderId: this.current.apsWorkOrderId,
+            categoryId: this.current.categoryId,
+            mesWorkOrderId: this.current.id,
+            produceRoutingId: this.current.produceRoutingId
+          };
+          let existRes = await listByMesWorkOrder(params);
+          let res = [];
+          if (!existRes || existRes.length === 0) {
+            res = allRes;
+          } else {
+            // 先将 存在的工序数据 数组的 id 存入 Set
+            const existIds = new Map(
+              existRes.map((item) => [
+                item.assignees.length ? item.taskId : null,
+                true
+              ])
+            );
+            // 过滤 全部工序数据 数组
+            // res = allRes.map((aItem) => !existIds.has(aItem.sourceTaskId));
+            res = allRes.map((aItem) => {
+              return {
+                ...aItem,
+                isSpecialField: existIds.has(aItem.sourceTaskId)
+              };
+            });
+          }
+          // 如果没有首工序的数据 就不能选择工序任务派单
+          if (!res || res.length === 0) {
+            this.processList = [];
+            // this.form.taskAss = 1;
+            // this.procTaskDis = true;
+            this.$message.warning('当前工单没有工序数据');
+            return;
+          }
+          // this.procTaskDis = false;
+          let list = [];
+          res.forEach((item, index) => {
+            let obj = {
+              id: item.taskId, //工序 id
+              name: item.taskName, //工序 名称
+              executionTeamName: item.executionTeamName || '', // 工序执行班组
+              assignType: 1, // 默认的指派数据
+              assignName: '工位', // 默认指派数据名称
+              list: [], // 当前工序下面的指派 绑定的表格
+              selection: [], // 当前工序下面的指派 选中的数据
+              code: item.taskCode, // 工序 编码
+              executionStartTime: item.executionStartTime || '', // 工序执行开始时间
+              executionEndTime: item.executionEndTime || '', // 工序执行结束时间
+              index: index, // 当前工序数据的下标
+              // isSpecialField: item.isSpecialField,
+              isSpecialField: false, //需求不清晰 为了满足江南需求 先默认false
+              radioBun: {
+                // 指派按钮的操作状态 绑定 默认false(可操作)
+                stationDis: false, // 工位按钮
+                staffDis: false, // 人员按钮
+                lineDis: false // 产线按钮
+              },
+              isDisable: teamIdSet.has(item.executionTeamId),
+              startDate: '', // 开始日期 (当前工序中最早的计划开始时间)
+              endDate: '', // 结束日期 (当前工序中最晚的计划结束时间)
+              workCenterId: item.workCenterId,
+              workCenterName: item.workCenterName,
+              teamName: item.executionTeamName,
+              executionType: item.executionType
+            };
+            list.push(obj);
+          });
+          this.processList = list;
+          this.processId = list[0].id;
+          // this.handleClick({ name: res[0].sourceTaskId });
+          this.initializeQuery();
+        } catch (err) {
+          this.processList = [];
+          this.$message.error(err.message);
+        } finally {
+          this.tabsLoading = false;
+        }
+      },
+
+      // 初始化查询 查询全部工序操作过的数据
+      async initializeQuery() {
+        try {
+          // 不存在 班组数据的话 就不调用这个方法
+          if (!this.form.teamId) {
+            return;
+          }
+          let params = {
+            workOrderId: this.current.id,
+            workCenterId: this.form.workCenterId,
+            teamId: this.form.teamId
+          };
+          let processMap = {};
+          this.processList.map((el, index) => (processMap[el.id] = index));
+          const res = await listAssign(params);
+          let isFirstData = false; // 判断默认第一道工序是否操作过
+          if (res && res.length > 0) {
+            res.map((el) => {
+              let index = processMap[el.taskId];
+              if (index === 0 && el.assignees && el.assignees.length > 0) {
+                isFirstData = true; // 操作过
+              }
+              // 这里第三个参数传空数组就好了 会自动计算的
+              setTimeout(() => {
+                this.operationalData(index, [el], []);
+              });
+            });
+            // 没有操作过 默认获取一下表格数据
+            if (!isFirstData) {
+              this.handleClick({ name: this.processId });
+            }
+          } else {
+            this.handleClick({ name: this.processId });
+          }
+        } catch (err) {}
+      },
+
+      //添加工位
+      addStation(item, index) {
+        this.$refs.chooseStationRef.open(
+          this.form.workCenterId,
+          item.list,
+          index
+        );
+      },
+
+      chooseStationList(list, index) {
+        const process = this.processList[index];
+        if (!process) return;
+
+        const oldList = process.list || [];
+
+        const existingIds = new Set(oldList.map((i) => i.id || i.__tempKey));
+
+        const newList = list
+          .filter((item) => !existingIds.has(item.id || item.__tempKey))
+          .map((item) => ({
+            ...item,
+            isNew: 1,
+            __tempKey: item.id || `temp_${Date.now()}_${Math.random()}`,
+            disposalStatus: 0,
+            assetCode: item.extInfo?.assetCode,
+            assetId: item.extInfo?.assetId,
+            assetName: item.extInfo?.assetName
+            // status: { code: 0, desc: '未派单' }
+          }));
+
+        this.$set(process, 'list', [...oldList, ...newList]);
+
+        const newIds = newList.map((i) => i.id || i.__tempKey);
+        if (!process.selection) process.selection = [];
+        process.selection.push(...newIds);
+
+        this.$nextTick(() => {
+          const tab = `tableRef${process.index}`;
+          this.$refs[tab]?.[0]?.setSelectedRowKeys(process.selection);
+        });
+      },
+
+      async changeWork(e) {
+        this.form.workCenterId = e;
+        const item = this.workCenterList.find((it) => it.centerId == e);
+        this.form.workCenterName = item ? item.centerName : '';
+
+        const filteredTeams = this.userTeamList.filter((item) =>
+          item.workCenterIds.includes(e)
+        );
+        this.teamList = filteredTeams || [];
+
+        if (this.teamList.length !== 0) {
+          this.form.teamId = this.teamList[0].teamId;
+          const td = this.teamList.find(
+            (item) => item.teamId === this.teamList[0].teamId
+          );
+          this.form.teamName = td ? td.teamName : '';
+          try {
+            const res = await listUserByIds([this.form.teamId]);
+            this.crewList = res || [];
+          } catch {
+            this.crewList = [];
+          }
+        } else {
+          this.crewList = [];
+          this.form.teamId = '';
+        }
+
+        await Promise.all([this.getProductionData(), this.FirstTaskIdFn()]);
+
+        await this.changeDispatch();
+
+        if (this.teamList.length === 0) {
+          const pData = this.processList.find(
+            (item) => item.id == this.processId
+          );
+          if (pData && pData.assignType == 2) {
+            this.$set(pData, 'list', []);
+          }
+        }
+      },
+      // 选择班组 查询人员的数据
+      async changeGroups(e) {
+        let data = this.teamList.find((item) => item.teamId == e);
+        this.form.teamName = data.teamName;
+        try {
+          const res = await listUserByIds([e]);
+          this.crewList = res || [];
+          if (!this.processId || this.processId == 0) {
+            return;
+          }
+          this.handleClick({ name: this.processId });
+          this.btnInit();
+        } catch {
+          this.crewList = [];
+        }
+      },
+      // 工序按钮初始化
+      btnInit() {
+        let data = this.processList.find((item) => item.id == this.processId);
+        this.$set(data.radioBun, 'lineDis', false);
+        this.$set(data.radioBun, 'staffDis', false);
+        this.$set(data.radioBun, 'stationDis', false);
+        this.$set(data, 'assignName', '工位');
+        this.$set(data, 'assignType', 1);
+      },
+      // 获取产线数据
+      async getProductionData() {
+        const res = await lineByCurrentUser(this.form.workCenterId);
+        this.productionList = res || [];
+      },
+      async FirstTaskIdFn(id) {
+        try {
+          const res = await listByFirstTaskId(
+            id || this.current.taskInstanceId
+          );
+          this.stationList = res || [];
+        } catch (err) {
+          this.stationList = [];
+          this.$message.error(err.message);
+        }
+      },
+      resetData(row, item) {
+        if (this.toolbarLoading) return;
+        if (!row.changeId) {
+          return this.$message.warning('只能对已撤回跟已保存的数据进行重置');
+        }
+        this.toolbarLoading = true;
+        resetAssignee(row.changeId)
+          .then((res) => {
+            this.toolbarLoading = false;
+            if (res) {
+              this.$message.success('操作成功');
+              // 更改当前表格数据
+              this.setCurrentTab(item);
+            }
+          })
+          .catch((err) => {
+            this.toolbarLoading = false;
+            this.$message.warning(err.message);
+          });
+      },
+      // 派单/撤回 判断
+      getWithdrawT(row, type) {
+        // if (type != 2) {
+        //   return true;
+        // }
+        let isWithdraw = [];
+        row.selection.forEach((item) => {
+          //撤回逻辑
+          if (type == 2) {
+            if (!item.status || !item.status.code) {
+              isWithdraw.push(item.name);
+            }
+          }
+          if (type == 1) {
+            if (item?.status?.code == 1) {
+              isWithdraw.push(item.name);
+            }
+          }
+          // if (!item.status.code) {
+          //   isFlag = false;
+          // }
+        });
+        return isWithdraw;
+      },
+      dispatch(row, type) {
+        if (this.toolbarLoading) return;
+        if (!row.selection || row.selection.length === 0) {
+          return this.$message.warning('请最少选择一条数据');
+        }
+
+        let assignees = [];
+        let changeIds = [];
+        let flag = true;
+
+        row.selection.forEach((item) => {
+          if (!item.quantity || !item.startTime || !item.endTime) {
+            flag = false;
+            return;
+          }
+
+          let Aobj = {
+            assigneeId: item.id,
+            quantity: item.quantity,
+            weight: item.weight,
+            startTime: item.startTime,
+            endTime: item.endTime,
+            assigneeType: row.assignType,
+            assigneeName: item.name,
+            measuringUnit: this.current.measuringUnit,
+            isNew: item.isNew ? item.isNew : '',
+            deviceId: item.extInfo?.assetId || '',
+            deviceName: item.extInfo?.assetName || '',
+            workStationId: item.id,
+            workStationName: item.name
+          };
+
+          if (item.teamTimeIds) {
+            Aobj.teamTimeIds = item.teamTimeIds;
+          }
+
+          assignees.push(Aobj);
+          changeIds.push(item.changeId);
+        });
+
+        if (!flag) {
+          return this.$message.warning(
+            '请将所选数据的数量、开始时间、完成时间填写完毕'
+          );
+        }
+
+        let data = null;
+        this.toolbarLoading = true;
+
+        if (type === 2) {
+          data = changeIds; // 撤回
+        } else {
+          data = {
+            dispatchMethod: 0,
+            dispatchType: this.dispatchType,
+            taskId: this.processId,
+            taskName: row.name,
+            taskCode: row.code,
+            teamName: this.form.teamName,
+            teamId: this.form.teamId,
+            workCenterId: this.form.workCenterId,
+            workCenterName: this.form.workCenterName,
+            workOrderId: this.current.apsWorkOrderId,
+            sourceType: 2,
+            mesWorkOrderId: this.current.id,
+            mesWorkOrderCode: this.current.code,
+            assignees
+          };
+        }
+
+        const api =
+          type === 1 ? taskAssignment : type === 2 ? taskRevoked : taskSave;
+
+        api(data)
+          .then((res) => {
+            this.toolbarLoading = false;
+            if (res) {
+              this.$message.success('操作成功');
+
+              // 更新表格数据,包括新增工位状态
+              this.setCurrentTab(row);
+
+              row.list.forEach((item) => {
+                if (item.isNew === 1) {
+                  // item.disposalStatus =
+                  //   type === 1 ? 1 : item.disposalStatus || 0;
+                  item.status = {
+                    code: type === 1 ? 1 : 0,
+                    desc: type === 1 ? '已派单' : '已保存'
+                  };
+                }
+              });
+            }
+          })
+          .catch((err) => {
+            this.toolbarLoading = false;
+            this.$message.warning(err.message);
+          });
+      },
+
+      cancel() {
+        this.$emit('update:dispatchVisible', false);
+      },
+      // 按钮操作成功后 更改当前的表格数据
+      setCurrentTab(row) {
+        let arr = [];
+        if (row.assignType == 1) {
+          arr = this.stationList;
+        } else if (row.assignType == 2) {
+          arr = this.crewList;
+        } else {
+          arr = this.productionList;
+        }
+        this.getAssignData(row.index, arr);
+      },
+      async handleClick(tab) {
+        if (this.tabLoading) return;
+        let id = tab.name;
+        this.processId = id;
+        await this.FirstTaskIdFn(id);
+        let data = this.processList.find((item) => item.id == this.processId);
+        if (data) {
+          // 点击工序后,班组显示以工序返回的 executionTeamName 为准
+          this.form.taskAss = 0;
+          this.form.teamName = data.executionTeamName || '';
+          await this.changeRadio(data.assignType, data.index);
+        }
+      },
+      // 指派选择
+      changeRadio(e, index) {
+        let data = this.processList[index];
+        if (e == 1) {
+          this.dynamicName = '工位名称';
+          data.assignName = '工位';
+          this.getAssignData(index, this.stationList);
+        } else if (e == 2) {
+          this.dynamicName = '人员名称';
+          data.assignName = '人员';
+          this.getAssignData(index, this.crewList);
+        } else {
+          this.dynamicName = '产线名称';
+          data.assignName = '产线';
+          this.getAssignData(index, this.productionList);
+        }
+      },
+      async getAssignData(index, arr, type = 0) {
+        const dataRow = this.processList[index];
+
+        const localNewList = (dataRow.list || []).filter((i) => i.isNew === 1);
+
+        let list = JSON.parse(JSON.stringify(arr || []));
+        list = this.applyExecutionTimeToList(list, dataRow);
+
+        if (!this.form.teamId) return;
+
+        const params = {
+          workOrderId: this.current.apsWorkOrderId,
+          workCenterId: this.form.workCenterId,
+          teamId: this.form.teamId,
+          taskId: this.processId
+        };
+
+        this.tabLoading = true;
+        try {
+          const res = await listAssign(params);
+          this.tabLoading = false;
+
+          if (!res || res.length === 0) {
+            // 没有后台数据,合并新增工位
+            const merged = [...list, ...localNewList];
+            this.$set(dataRow, 'list', merged);
+            return;
+          }
+
+          // 已操作过数据处理
+          this.operationalData(index, res, list);
+
+          // 合并新增工位并去重
+          const existingIds = new Set(
+            (dataRow.list || []).map((i) => i.id || i.__tempKey)
+          );
+          const mergedList = [
+            ...dataRow.list,
+            ...localNewList.filter((i) => !existingIds.has(i.id || i.__tempKey))
+          ];
+
+          // 更新新增工位状态
+          mergedList.forEach((item) => {
+            if (item.isNew === 1) {
+              item.disposalStatus = type === 1 ? 1 : item.disposalStatus || 0;
+              item.status = item.status || {
+                code: type === 1 ? 1 : 0,
+                desc: type === 1 ? '已派单' : '已保存'
+              };
+            }
+          });
+
+          this.$set(dataRow, 'list', mergedList);
+        } catch (err) {
+          this.tabLoading = false;
+          this.$message.warning(err.message);
+        }
+      },
+
+      // 操作过的数据 赋值
+      operationalData(index, res, list) {
+        const dataRow = this.processList[index];
+        // 键值对存储 当前工序 操作的数据  指派的code(键) 数据(list:值)
+        let arrMap = {};
+        // 要先判断有没有操作的数据 如果有的话 其它的指派操作置灰
+        let codeT = null; // 表示有已操作的数据(对应的 code)
+        res[0].assignees.map((el) => {
+          let code = el.assigneeType.code;
+          if (arrMap[code]) {
+            arrMap[code].arr.push(el);
+            arrMap[code].bunDis = arrMap[code].bunDis
+              ? arrMap[code].bunDis
+              : el.status.desc
+              ? true
+              : false;
+          } else {
+            arrMap[code] = {
+              arr: [el],
+              bunDis: el.status.desc ? true : false
+            };
+          }
+          codeT = codeT ? codeT : el.status.desc ? code : '';
+        });
+        let radioBun = {
+          lineDis: false, // 产线 3
+          staffDis: false, // 人员 2
+          stationDis: false // 工位 1
+        };
+        // 默认是传递下来的 list 数据 但是如果 codeT有值 说明 工位 人员 产线 有派单数据
+        // 需要自动切换过去
+        let listArr = list;
+        if (codeT) {
+          if (codeT == 1) {
+            radioBun.staffDis = true;
+            radioBun.lineDis = true;
+            radioBun.stationDis = false;
+            listArr = JSON.parse(JSON.stringify(this.stationList));
+            dataRow.assignType = 1;
+            dataRow.assignName = '工位';
+          } else if (codeT == 2) {
+            radioBun.stationDis = true;
+            radioBun.lineDis = true;
+            radioBun.staffDis = false;
+            listArr = JSON.parse(JSON.stringify(this.crewList));
+            dataRow.assignType = 2;
+            dataRow.assignName = '人员';
+          } else {
+            radioBun.stationDis = true;
+            radioBun.staffDis = true;
+            radioBun.lineDis = false;
+            listArr = JSON.parse(JSON.stringify(this.productionList));
+            dataRow.assignType = 3;
+            dataRow.assignName = '产线';
+          }
+        }
+        listArr = this.applyExecutionTimeToList(listArr, dataRow);
+        // 切换完后 对 指派的数组数据进行赋值
+        let listMap = {};
+        listArr.map((el, index) => (listMap[el.id] = index));
+        let arrList = codeT ? arrMap[codeT].arr : res[0].assignees;
+
+        if (listArr.length == 0) return;
+
+        // listArr.forEach((it) => {
+        //   if (it.disposalStatus || it.disposalStatus == 0) {
+        arrList.map((item) => {
+          if (item.assigneeType.code == dataRow.assignType) {
+            let idx = listMap[item.assigneeId];
+            if (idx === undefined || !listArr[idx]) {
+              console.warn('未找到对应指派对象', item.assigneeId, listArr);
+              return;
+            }
+            listArr[idx].disposalStatus = item.disposalStatus;
+            listArr[idx].status = item.status;
+            listArr[idx].startTime = item.startTime;
+            listArr[idx].endTime = item.endTime;
+            listArr[idx].quantity = item.quantity;
+            listArr[idx].weight = item.weight;
+            listArr[idx].changeId = item.id;
+            listArr[idx].teamTimeIds = item.teamTimeIds;
+            this.compareAndSetTime(listArr[idx], dataRow);
+            this.compareEndSetTime(listArr[idx], dataRow);
+          }
+        });
+        //   }
+        // });
+
+        // console.log(listArr,'listArr')
+        this.$set(dataRow, 'list', listArr);
+        this.$set(dataRow, 'radioBun', radioBun);
+      },
+
+      applyExecutionTimeToList(list, dataRow) {
+        if (!Array.isArray(list) || !dataRow) return list;
+        if (!dataRow.executionStartTime || !dataRow.executionEndTime)
+          return list;
+        return list.map((item) => ({
+          ...item,
+          startTime: item.startTime || dataRow.executionStartTime,
+          endTime: item.endTime || dataRow.executionEndTime
+        }));
+      },
+      // 时间比较与赋值方法 开始时间
+      compareAndSetTime(data, dataRow) {
+        // 如果startDate为空,直接赋值为startTime
+        if (!dataRow.startDate) {
+          dataRow.startDate = data['startTime'];
+          return;
+        }
+
+        // 转换为Date对象进行比较
+        const startTimeDate = new Date(data['startTime']);
+        const startDateDate = new Date(dataRow.startDate);
+
+        // 比较时间(getTime()获取时间戳)
+        if (startTimeDate.getTime() < startDateDate.getTime()) {
+          dataRow.startDate = data['startTime'];
+        }
+      },
+      // 时间比较与赋值方法 结束时间时间
+      compareEndSetTime(data, dataRow) {
+        // 如果startDate为空,直接赋值为endTime
+        if (!dataRow.endDate) {
+          dataRow.endDate = data['endTime'];
+          return;
+        }
+        // 转换为Date对象进行比较
+        const endTimeDate = new Date(data['endTime']);
+        const endDateDate = new Date(dataRow.endDate);
+        // 比较时间(getTime()获取时间戳)
+        if (endTimeDate.getTime() > endDateDate.getTime()) {
+          dataRow.endDate = data['endTime'];
+        }
+      },
+      // 数量正则 quantity
+      handleQuantityInput(e, row, item) {
+        // 过滤非数字字符(包括负号)
+        let value = e.replace(/[^\d]/g, '');
+        // 限制不能以 0 开头(除非是 0 本身)
+        if (value.startsWith('0') && value.length > 1) {
+          value = value.slice(1);
+        }
+        // 更新绑定值
+        row.quantity = value;
+        this.calculateQuantity(row, item);
+        this.bringWeight(row.quantity, row);
+        this.selectedListData(row, item);
+      },
+      // 自动算重量
+      bringWeight(value, row) {
+        if (!this.current.formingWeight) {
+          this.$set(row, 'weight', 0);
+          return;
+        }
+        let weight =
+          (this.current.formingWeight / this.current.formingNum) * value;
+        if (weight > 0) {
+          weight = weight.toFixed(4) - 0;
+        }
+        this.$set(row, 'weight', weight);
+      },
+      calculateQuantity(row, item) {
+        // 如果没有该字段 就不做判断
+        if (!this.current.formingNum) {
+          return;
+        }
+        let total = 0;
+        item.list.forEach((el) => {
+          if (el.quantity) {
+            total = total + (el.quantity - 0);
+          }
+        });
+        if (total > this.current.formingNum - 0) {
+          this.$message.warning('列表数量相加不能大于目标要求生产数量');
+          row.quantity = 0;
+        }
+      },
+      // 计算重量
+      calculateWeight(row, item) {
+        // 如果没有该字段 就不做判断
+        if (!this.current.formingWeight) {
+          return;
+        }
+        let total = 0;
+        item.list.forEach((el) => {
+          if (el.weight) {
+            total = total + (el.weight - 0);
+          }
+        });
+        if (total > this.current.formingWeight - 0) {
+          this.$message.warning('列表数量相加不能大于目标要求生产数量');
+          row.weight = 0;
+        }
+      },
+      // 重量正则 weight
+      handleWeightInput(e, row, item) {
+        // 过滤非数字和非小数点字符(包括负号)
+        let value = e.replace(/[^\d.]/g, '');
+        // 限制只能有一个小数点
+        const dotCount = (value.match(/\./g) || []).length;
+        if (dotCount > 1) {
+          value = value.slice(0, value.lastIndexOf('.'));
+        }
+
+        // 限制不能以小数点开头
+        if (value.startsWith('.')) {
+          value = '0' + value;
+        }
+        // 更新绑定值
+        row.weight = value;
+        this.calculateWeight(row, item);
+        this.selectedListData(row, item);
+      },
+      // 选中班次
+      shiftSelection(e, row, item) {
+        // this.selectedListData(row, item);
+        let data = this.shifTimeData(e, row);
+        // let data = this.shiftList.find((item) => item.id == e);
+        // let startTime = `${this.dateValue} ${data.startTime}`;
+        // let endTime = `${this.dateValue} ${data.endTime}`;
+        let startTime = `${this.dateValue} ${data.startTime}` + `:00`;
+        let endTime = `${this.dateValue} ${data.endTime}` + `:00`;
+        this.$set(row, 'startTime', startTime);
+        this.$set(row, 'endTime', endTime);
+        this.handleStartTimeChange(row, item);
+        this.handleEndTimeChange(row, item);
+      },
+      // 默认选中当前更改数据
+      selectedListData(row, item) {
+        this.$nextTick(() => {
+          let data = item.selection.find((el) => el.id == row.id);
+          if (!data) {
+            let ids = item.selection.map((el) => el.id);
+            ids.push(row.id);
+            let tab = `tableRef${[item.index]}`;
+            this.$refs[tab][0].setSelectedRowKeys(ids);
+          }
+        });
+      },
+      // 多选班次时间数据
+      shifTimeData(e, row) {
+        if (!e || e.length == 0) {
+          return {
+            startTime: row.startTime,
+            endTime: row.endTime
+          };
+        }
+        let startTime = '';
+        let endTime = '';
+        e.map((el) => {
+          let obj = this.shiftList.find((item) => item.id == el);
+          if (!startTime) {
+            startTime = obj.startTime;
+          }
+          if (!endTime) {
+            endTime = obj.endTime;
+          }
+          // 获取更小的
+          startTime =
+            this.compareTime(startTime, obj.startTime) !== -1
+              ? obj.startTime
+              : startTime;
+          // 获取更大的
+          endTime =
+            this.compareTime(endTime, obj.endTime) !== 1
+              ? obj.endTime
+              : endTime;
+        });
+
+        return {
+          startTime,
+          endTime
+        };
+      },
+      // 将HH:mm:ss格式的时间转换为总秒数
+      timeToSeconds(timeStr) {
+        const [hours, minutes, seconds] = timeStr.split(':').map(Number);
+        return hours * 3600 + minutes * 60 + seconds;
+      },
+      // this.$refs.table.setSelectedRowKeys(ids);
+      // 比较两个时间的大小
+      compareTime(time1, time2) {
+        const sec1 = this.timeToSeconds(time1);
+        const sec2 = this.timeToSeconds(time2);
+
+        if (sec1 > sec2) {
+          return 1; // time1 更大
+        } else if (sec1 < sec2) {
+          return -1; // time2 更大
+        } else {
+          return 0; // 两个时间相等
+        }
+      },
+      // 【开始时间变化时】触发
+      handleStartTimeChange(row, item) {
+        if (!row.startTime) {
+          return;
+        }
+        this.selectedListData(row, item);
+        // 这一道工序的开始时间 不能小于前一道工序的结束时间
+        const startTime = new Date(row.startTime); // 开始时间
+        if (item.index !== 0) {
+          // let frontIdx = item.index - 1;
+          let frontIdx = this.calculateIndex(item.index).startIdx;
+          if (frontIdx !== 'none') {
+            let frontName = this.processList[frontIdx].name;
+            let time = this.processList[frontIdx].endDate;
+            const frontTime = new Date(time); // 前面工序的结束时间
+            if (time && startTime < frontTime) {
+              this.$message.closeAll();
+              this.$message.info(
+                `开始时间不能小于前面工序${frontName}的结束时间${time}`
+              );
+              // 判断是否 配置时间更改规则
+              if (this.time_calc_code == '1') {
+                row.startTime = time;
+              }
+              return;
+            }
+          }
+        }
+        // 这一道工序的开始时间更不能大于后一道工序的开始时间
+        if (item.index !== this.processList.length - 1) {
+          // let latterIdx = item.index + 1;
+          let latterIdx = this.calculateIndex(item.index).endIdx;
+          if (latterIdx !== 'none') {
+            let time = this.processList[latterIdx].startDate;
+            let latterName = this.processList[latterIdx].name;
+            const latterTime = new Date(time); // 下一道工序的结束时间
+            if (time && startTime > latterTime) {
+              this.$message.closeAll();
+              this.$message.info(
+                `开始时间不能大于后面工序${latterName}的开始时间${time}`
+              );
+              // 判断是否 配置时间更改规则
+              if (this.time_calc_code == '1') {
+                row.startTime = '';
+              }
+              return;
+            }
+          }
+        }
+        // 校验 是否 大于结束时间  wda
+        this.checkEndTimeValid(row);
+      },
+      // 当更改一个工序开始时间 结束时间的时候
+      // 开始时间 不能小于之前工序的结束时间 ( 要先去上一道工序找 是否存在结束时间 不存在就再往前找 直到 第一道工序 )
+      // 结束时间 不能大于后面工序的开始时间 ( 要先去后一道工序找 是否存在开始时间 不存在就再往后找 直到 最后一道工序 )
+      // 计算出当前下标数据 的前后 有 开始时间 结束时间的数据下标
+      calculateIndex(index) {
+        let startIdx = 'none';
+        let endIdx = 'none';
+        // 前面工序下标
+        for (let i = index - 1; i >= 0; i--) {
+          let row = this.processList[i];
+          if (row && row.endDate) {
+            startIdx = i;
+            break;
+          }
+        }
+        // 后面工序的下标
+        for (let i = index + 1; i <= this.processList.length; i++) {
+          let row = this.processList[i];
+          if (row && row.startDate) {
+            endIdx = i;
+            break;
+          }
+        }
+        return {
+          startIdx,
+          endIdx
+        };
+      },
+      // 【结束时间变化时】触发
+      handleEndTimeChange(row, item) {
+        if (!row.endTime) {
+          return;
+        }
+        this.selectedListData(row, item);
+        const endTime = new Date(row.endTime); // 结束时间
+        // 当前工序的结束时间 不能大于后一道工序的开始时间
+        if (item.index !== this.processList.length - 1) {
+          let latterIdx = this.calculateIndex(item.index).endIdx;
+          if (latterIdx !== 'none') {
+            let latterName = this.processList[latterIdx].name;
+            let time = this.processList[latterIdx].startDate;
+            const latterTime = new Date(time); // 后面工序的开始时间
+            if (time && endTime > latterTime) {
+              this.$message.closeAll();
+              this.$message.info(
+                `结束时间不能大于后面工序${latterName}的开始时间${time}`
+              );
+              // 判断是否 配置时间更改规则
+              if (this.time_calc_code == '1') {
+                row.endTime = time;
+              }
+              return;
+            }
+          }
+        }
+        // 这一道工序的开始时间更不能小于于前一道工序的结束时间
+        if (item.index !== 0) {
+          // let frontIdx = item.index - 1;
+          let frontIdx = this.calculateIndex(item.index).startIdx;
+          if (frontIdx !== 'none') {
+            let frontName = this.processList[frontIdx].name;
+            let time = this.processList[frontIdx].endDate;
+            const frontTime = new Date(time); // 上一道工序的结束时间
+            if (time && endTime < frontTime) {
+              this.$message.closeAll();
+              this.$message.info(
+                `结束时间不能小于前面工序${frontName}的结束时间${time}`
+              );
+              // 判断是否 配置时间更改规则
+              if (this.time_calc_code == '1') {
+                row.endTime = '';
+              }
+              return;
+            }
+          }
+        }
+        this.checkEndTimeValid(row, item);
+      },
+      // 时间校验
+      checkEndTimeValid(row) {
+        const { startTime: start, endTime: end } = row;
+        // if (!start || !end) return; // 开始/结束时间未填,跳过
+        const startTime = new Date(start); // 开始时间
+        const endTime = new Date(end); // 结束时间
+        if (endTime < startTime) {
+          row.endTime = new Date(startTime); // 修正为开始时间
+          this.$message.info('结束时间不能早于开始时间,已自动设为开始时间');
+        }
+      },
+      formatExecutionType(type) {
+        const map = {
+          0: '自制',
+          1: '请托',
+          2: '委外'
+        };
+        return map[type] || '';
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .top-box {
+    display: flex;
+    margin-bottom: 10px;
+
+    .item-box {
+      flex: 1;
+    }
+  }
+
+  .radio-box {
+    margin: 10px 0;
+  }
+
+  .table {
+    margin-top: 20px;
+  }
+
+  ::v-deep .el-radio-button__orig-radio:checked + .el-radio-button__inner {
+    background-color: #10d070;
+    border-color: #10d070;
+  }
+
+  ::v-deep .el-radio-button__orig-radio:checked + .el-radio-button__inner {
+    box-shadow: none;
+  }
+
+  // ::v-deep .ele-block{
+  //   width: 240px;
+  // }
+
+  // ::v-deep .basic {
+  //   .el-form-item {
+  //     width: 100%;
+  //   }
+
+  //   .form80 {
+  //     .el-form-item__content {
+  //       width: calc(100% - 80px);
+  //     }
+  //   }
+
+  //   .form65 {
+  //     .el-form-item__content {
+  //       width: calc(100% - 65px);
+  //     }
+  //   }
+
+  //   .el-form-item__label {
+  //     padding: 0 4px 0 0;
+  //   }
+
+  //   .item_label {
+  //     white-space: nowrap;
+  //     overflow: hidden;
+  //     text-overflow: ellipsis;
+  //     width: 100%;
+  //   }
+  // }
+
+  .describe {
+    display: inline-block;
+  }
+</style>

+ 30 - 4
src/views/produceOrder/index.vue

@@ -277,6 +277,14 @@
       v-if="dispatchVisible"
     />
 
+    <planDotLineReleaseDialog
+      ref="planDotLineReleaseDialogRef"
+      :current="dispatchRow"
+      :dispatchVisible.sync="planDotLineReleaseDialogVisible"
+      @createSuccess="createSuccess"
+      v-if="planDotLineReleaseDialogVisible"
+    />
+
     <originCode ref="originCodeRef" />
 
     <checkAdd
@@ -313,13 +321,14 @@
   import printCard from './print.vue';
   import EquipmentDialog from './components/EquipmentDialog.vue';
   import detailsPop from './components/details/index.vue';
-
+  import { parameterGetByCode } from '@/api/system/dictionary-data';
   import { debounce } from 'lodash';
   import tableColumnsMixin from '@/mixins/tableColumnsMixin';
   import originCode from './originCode.vue';
   import checkAdd from '@/views/checklistManagement/components/checkAdd.vue';
   import checkDetails from '@/views/checklistManagement/components/checkDetails.vue';
   import { getTaskInstanceList } from '@/api/produce/job';
+  import planDotLineReleaseDialog from './components/releaseDialog/planDotLineReleaseDialog.vue';
 
   export default {
     mixins: [tableColumnsMixin],
@@ -339,7 +348,8 @@
       workReport,
       originCode,
       checkAdd,
-      checkDetails
+      checkDetails,
+      planDotLineReleaseDialog
     },
 
     data() {
@@ -376,7 +386,9 @@
         dispatchRow: {},
         tableHeight: 'calc(100vh - 375px)',
         workDataList: [],
-        taskNameMap: {}
+        taskNameMap: {},
+        planDotLine: false,
+        planDotLineReleaseDialogVisible: false
       };
     },
     computed: {
@@ -889,12 +901,22 @@
     },
     created() {
       this.getFieldModel();
+      this.getPlanDotLine();
     },
     mounted() {
       this.reload();
     },
 
     methods: {
+      getPlanDotLine() {
+        parameterGetByCode({
+          code: 'plan_dot_line'
+        }).then((res) => {
+          if (res) {
+            this.planDotLine = res.value == '1' ? true : false;
+          }
+        });
+      },
       //派单
       toReleaseOpen(row) {
         getTaskIdByInstanceId(row.taskId)
@@ -905,7 +927,11 @@
                 ? row.formingWeight + row.weightUnit
                 : '';
               this.dispatchRow.taskInstanceId = res;
-              this.dispatchVisible = true;
+              if (this.planDotLine) {
+                this.planDotLineReleaseDialogVisible = true;
+              } else {
+                this.dispatchVisible = true;
+              }
             }
           })
           .catch((err) => {