Parcourir la source

新增需求审批,修改bug

695593266@qq.com il y a 3 jours
Parent
commit
faf61a7869

+ 9 - 1
src/components/processSubmitDialog/processSubmitDialog.vue

@@ -203,6 +203,10 @@
         type: String,
         default: ''
       },
+      customSubmit: {
+        type: Function,
+        default: null
+      },
       // 关闭弹窗时是否刷新列表
       isCloseRefresh: {
         type: Boolean,
@@ -423,7 +427,11 @@
         });
       },
       async submit() {
-        await processInstanceCreateAPI(this.form);
+        if (this.customSubmit) {
+          await this.customSubmit(this.form.businessId, this.form);
+        } else {
+          await processInstanceCreateAPI(this.form);
+        }
         this.$message('提交审核成功');
         this.$emit('reload');
         this.cancel();

+ 310 - 205
src/views/demandApplication/components/DemandApplicationForm.vue

@@ -11,107 +11,117 @@
     append-to-body
   >
     <div v-loading="loading" class="application-form-layout">
-      <div class="form-overview">
-        <div class="overview-identity">
-          <div class="overview-icon">
-            <i :class="readOnly ? 'el-icon-view' : 'el-icon-edit-outline'"></i>
-          </div>
-          <div>
-            <div class="overview-label">{{
-              readOnly ? '申请单详情' : '申请单维护'
-            }}</div>
-            <div class="overview-code">
-              {{ formData.applyCode || '保存后生成申请编号' }}
+      <el-tabs
+        v-model="activeTab"
+        class="detail-tabs"
+        :class="{ 'detail-tabs--form': !readOnly }"
+      >
+        <el-tab-pane label="申请详情" name="application">
+          <div class="form-overview">
+            <div class="overview-identity">
+              <div class="overview-icon">
+                <i
+                  :class="readOnly ? 'el-icon-view' : 'el-icon-edit-outline'"
+                ></i>
+              </div>
+              <div>
+                <div class="overview-label">{{
+                  readOnly ? '申请单详情' : '申请单维护'
+                }}</div>
+                <div class="overview-code">
+                  {{ formData.applyCode || '保存后生成申请编号' }}
+                </div>
+              </div>
+            </div>
+            <div class="overview-meta">
+              <div class="meta-item meta-item--unit">
+                <span class="meta-label">申请单位</span>
+                <el-tooltip
+                  :content="formData.applyUnitName || '待填写'"
+                  placement="top"
+                  effect="dark"
+                >
+                  <span class="meta-value meta-value--unit">{{
+                    formData.applyUnitName || '待填写'
+                  }}</span>
+                </el-tooltip>
+              </div>
+              <div class="meta-item">
+                <span class="meta-label">明细行数</span>
+                <span class="meta-value meta-value--number">{{
+                  detailCount
+                }}</span>
+              </div>
+              <el-tag
+                :type="approvalStatusType(formData.approvalStatus)"
+                :class="`overview-status overview-status--${Number(
+                  formData.approvalStatus
+                )}`"
+              >
+                <i class="overview-status__dot"></i>
+                {{ approvalStatusLabel(formData.approvalStatus) }}
+              </el-tag>
             </div>
           </div>
-        </div>
-        <div class="overview-meta">
-          <div class="meta-item meta-item--unit">
-            <span class="meta-label">申请单位</span>
-            <el-tooltip
-              :content="formData.applyUnitName || '待填写'"
-              placement="top"
-              effect="dark"
-            >
-              <span class="meta-value meta-value--unit">{{
-                formData.applyUnitName || '待填写'
-              }}</span>
-            </el-tooltip>
-          </div>
-          <div class="meta-item">
-            <span class="meta-label">明细行数</span>
-            <span class="meta-value meta-value--number">{{ detailCount }}</span>
-          </div>
-          <el-tag
-            :type="approvalStatusType(formData.approvalStatus)"
-            :class="`overview-status overview-status--${Number(
-              formData.approvalStatus
-            )}`"
-          >
-            <i class="overview-status__dot"></i>
-            {{ approvalStatusLabel(formData.approvalStatus) }}
-          </el-tag>
-        </div>
-      </div>
 
-      <section class="form-section basic-section">
-        <div class="section-heading">
-          <div>
-            <div class="section-title">
-              <i class="el-icon-s-order"></i>
-              基础信息
+          <section class="form-section basic-section">
+            <div class="section-heading">
+              <div>
+                <div class="section-title">
+                  <i class="el-icon-s-order"></i>
+                  基础信息
+                </div>
+                <div class="section-description"
+                  >填写申请单位、申请人及单据基础属性</div
+                >
+              </div>
+              <span v-if="!readOnly" class="required-hint">
+                <i></i> 标记字段为必填项
+              </span>
             </div>
-            <div class="section-description"
-              >填写申请单位、申请人及单据基础属性</div
-            >
-          </div>
-          <span v-if="!readOnly" class="required-hint">
-            <i></i> 标记字段为必填项
-          </span>
-        </div>
-
-        <el-form
-          ref="form"
-          :model="formData"
-          :rules="rules"
-          :disabled="readOnly"
-          label-width="140px"
-          class="ele-body demand-form"
-        >
-          <el-row :gutter="24">
-            <el-col :lg="8" :md="12" :sm="12" :xs="24">
-              <el-form-item label="申请编号:" prop="applyCode">
-                <el-input
-                  v-model.trim="formData.applyCode"
-                  size="mini"
-                  placeholder="不填写时由后台生成"
-                />
-              </el-form-item>
-            </el-col>
-            <el-col :lg="8" :md="12" :sm="12" :xs="24">
-              <el-form-item label="申请时间:" prop="applyTime">
-                <el-date-picker
-                  v-model="formData.applyTime"
-                  type="datetime"
-                  size="mini"
-                  value-format="yyyy-MM-dd HH:mm:ss"
-                  placeholder="请选择申请时间"
-                  class="w100"
-                />
-              </el-form-item>
-            </el-col>
 
-            <el-col :lg="8" :md="12" :sm="12" :xs="24">
-              <el-form-item label="申请单位名称:" prop="applyUnitName">
-                <el-input
-                  v-model.trim="formData.applyUnitName"
-                  disabled
-                  size="mini"
-                  placeholder="当前登录人所属单位"
-                />
-              </el-form-item>
-            </el-col>
-            <!-- <el-col :lg="8" :md="12" :sm="12" :xs="24">
+            <el-form
+              ref="form"
+              :model="formData"
+              :rules="rules"
+              :disabled="readOnly"
+              label-width="140px"
+              class="ele-body demand-form"
+            >
+              <el-row :gutter="24">
+                <el-col :lg="8" :md="12" :sm="12" :xs="24">
+                  <el-form-item label="申请编号:" prop="applyCode">
+                    <el-input
+                      v-model.trim="formData.applyCode"
+                      size="mini"
+                      placeholder="不填写时由后台生成"
+                    />
+                  </el-form-item>
+                </el-col>
+                <el-col :lg="8" :md="12" :sm="12" :xs="24">
+                  <el-form-item label="申请时间:" prop="applyTime">
+                    <el-date-picker
+                      v-model="formData.applyTime"
+                      type="datetime"
+                      size="mini"
+                      value-format="yyyy-MM-dd HH:mm:ss"
+                      placeholder="请选择申请时间"
+                      class="w100"
+                    />
+                  </el-form-item>
+                </el-col>
+
+                <el-col :lg="8" :md="12" :sm="12" :xs="24">
+                  <el-form-item label="申请单位名称:" prop="applyUnitName">
+                    <el-input
+                      v-model.trim="formData.applyUnitName"
+                      disabled
+                      size="mini"
+                      placeholder="当前登录人所属单位"
+                    />
+                  </el-form-item>
+                </el-col>
+                <!-- <el-col :lg="8" :md="12" :sm="12" :xs="24">
               <el-form-item label="申请用户编码:" prop="applyUserCode">
                 <el-input
                   v-model.trim="formData.applyUserCode"
@@ -120,119 +130,132 @@
                 />
               </el-form-item>
             </el-col> -->
-          </el-row>
-
-          <el-row :gutter="24">
-            <el-col :lg="4" :md="12" :sm="12" :xs="24">
-              <el-form-item label="审批状态:">
-                <el-tag :type="approvalStatusType(formData.approvalStatus)">
-                  {{ approvalStatusLabel(formData.approvalStatus) }}
-                </el-tag>
-              </el-form-item>
-            </el-col>
-          </el-row>
+              </el-row>
+
+              <el-row :gutter="24">
+                <el-col :lg="4" :md="12" :sm="12" :xs="24">
+                  <el-form-item label="审批状态:">
+                    <el-tag :type="approvalStatusType(formData.approvalStatus)">
+                      {{ approvalStatusLabel(formData.approvalStatus) }}
+                    </el-tag>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+
+              <el-row>
+                <el-col :span="24">
+                  <el-form-item label="备注:" prop="remark">
+                    <el-input
+                      v-model.trim="formData.remark"
+                      type="textarea"
+                      :rows="2"
+                      maxlength="500"
+                      show-word-limit
+                      placeholder="请输入备注"
+                    />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+            </el-form>
+          </section>
+
+          <section class="form-section detail-section">
+            <div class="section-heading detail-heading">
+              <div>
+                <div class="section-title">
+                  <i class="el-icon-s-grid"></i>
+                  需求明细
+                  <span class="section-count">{{ detailCount }}</span>
+                </div>
+                <div class="section-description"
+                  >维护物品、数量及期望到货日期</div
+                >
+              </div>
+              <div v-if="!readOnly" class="detail-guide">
+                <i class="el-icon-info"></i>
+                请先选择物品,仅数量、要求日期和物品类型可修改
+              </div>
+            </div>
 
-          <el-row>
-            <el-col :span="24">
-              <el-form-item label="备注:" prop="remark">
+            <ele-pro-table
+              ref="detailTable"
+              :columns="detailColumns"
+              :datasource="formData.detailList"
+              :need-page="false"
+              :toolbar="!readOnly"
+              class="detail-edit-table"
+              row-key="_rowKey"
+              height="360px"
+            >
+              <template v-if="!readOnly" v-slot:toolbar>
+                <el-button
+                  type="primary"
+                  size="small"
+                  icon="el-icon-plus"
+                  class="ele-btn-icon"
+                  @click="addDetail"
+                >
+                  添加物品明细
+                </el-button>
+              </template>
+
+              <template v-slot:quantity="{ row }">
                 <el-input
-                  v-model.trim="formData.remark"
-                  type="textarea"
-                  :rows="2"
-                  maxlength="500"
-                  show-word-limit
-                  placeholder="请输入备注"
+                  v-model="row.quantity"
+                  :disabled="readOnly"
+                  size="mini"
+                  inputmode="decimal"
+                  placeholder="请输入大于 0 的数量"
+                  class="w100"
+                  @input="handleQuantityInput($event, row)"
+                  @blur="handleQuantityBlur(row)"
                 />
-              </el-form-item>
-            </el-col>
-          </el-row>
-        </el-form>
-      </section>
-
-      <section class="form-section detail-section">
-        <div class="section-heading detail-heading">
-          <div>
-            <div class="section-title">
-              <i class="el-icon-s-grid"></i>
-              需求明细
-              <span class="section-count">{{ detailCount }}</span>
-            </div>
-            <div class="section-description">维护物品、数量及期望到货日期</div>
-          </div>
-          <div v-if="!readOnly" class="detail-guide">
-            <i class="el-icon-info"></i>
-            请先选择物品,仅数量、要求日期和物品类型可修改
-          </div>
-        </div>
-
-        <ele-pro-table
-          ref="detailTable"
-          :columns="detailColumns"
-          :datasource="formData.detailList"
-          :need-page="false"
-          :toolbar="!readOnly"
-          class="detail-edit-table"
-          row-key="_rowKey"
-          height="360px"
-        >
-          <template v-if="!readOnly" v-slot:toolbar>
-            <el-button
-              type="primary"
-              size="small"
-              icon="el-icon-plus"
-              class="ele-btn-icon"
-              @click="addDetail"
-            >
-              添加物品明细
-            </el-button>
-          </template>
-
-          <template v-slot:quantity="{ row }">
-            <el-input
-              v-model="row.quantity"
-              :disabled="readOnly"
-              size="mini"
-              inputmode="decimal"
-              placeholder="请输入大于 0 的数量"
-              class="w100"
-              @input="handleQuantityInput($event, row)"
-              @blur="handleQuantityBlur(row)"
-            />
-          </template>
-          <template v-slot:requestDate="{ row }">
-            <el-date-picker
-              v-model="row.requestDate"
-              :disabled="readOnly"
-              type="date"
-              size="mini"
-              value-format="yyyy-MM-dd HH:mm:ss"
-              placeholder="必填"
-              class="w100"
+              </template>
+              <template v-slot:requestDate="{ row }">
+                <el-date-picker
+                  v-model="row.requestDate"
+                  :disabled="readOnly"
+                  type="date"
+                  size="mini"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="必填"
+                  class="w100"
+                />
+              </template>
+              <template v-slot:type="{ row }">
+                <el-select
+                  v-model="row.type"
+                  :disabled="readOnly"
+                  size="mini"
+                  class="w100"
+                >
+                  <el-option label="默认" :value="0" />
+                  <el-option label="工装" :value="1" />
+                </el-select>
+              </template>
+              <template v-slot:action="{ $index }">
+                <el-link
+                  type="danger"
+                  :underline="false"
+                  icon="el-icon-delete"
+                  @click="removeDetail($index)"
+                >
+                  删除
+                </el-link>
+              </template>
+            </ele-pro-table>
+          </section>
+        </el-tab-pane>
+        <el-tab-pane v-if="showProcessTab" label="流程详情" name="process" lazy>
+          <div class="process-detail-pane">
+            <BpmDetail
+              v-if="activeTab === 'process'"
+              :key="formData.processInstanceId"
+              :id="formData.processInstanceId"
             />
-          </template>
-          <template v-slot:type="{ row }">
-            <el-select
-              v-model="row.type"
-              :disabled="readOnly"
-              size="mini"
-              class="w100"
-            >
-              <el-option label="默认" :value="0" />
-              <el-option label="工装" :value="1" />
-            </el-select>
-          </template>
-          <template v-slot:action="{ $index }">
-            <el-link
-              type="danger"
-              :underline="false"
-              icon="el-icon-delete"
-              @click="removeDetail($index)"
-            >
-              删除
-            </el-link>
-          </template>
-        </ele-pro-table>
-      </section>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
     </div>
 
     <MaterialSelectDialog
@@ -275,11 +298,13 @@
     createDetailRow,
     normalizeDateTime
   } from '../constants';
+  import BpmDetail from '@/views/bpm/processInstance/detail.vue';
   import MaterialSelectDialog from './MaterialSelectDialog.vue';
 
   export default {
     name: 'DemandApplicationForm',
     components: {
+      BpmDetail,
       MaterialSelectDialog
     },
     data() {
@@ -288,6 +313,7 @@
         loading: false,
         submitting: false,
         mode: 'add',
+        activeTab: 'application',
         formData: createApplicationForm(),
         rules: {
           applyTime: [
@@ -309,6 +335,9 @@
       readOnly() {
         return this.mode === 'view';
       },
+      showProcessTab() {
+        return this.readOnly && Boolean(this.formData.processInstanceId);
+      },
       title() {
         if (this.mode === 'view') return '查看需求申请单';
         if (this.mode === 'edit') return '修改需求申请单';
@@ -419,6 +448,7 @@
           return;
         }
         this.mode = mode;
+        this.activeTab = 'application';
         this.formData = createApplicationForm();
         if (mode === 'add') {
           const userInfo = this.$store.getters.user.info || {};
@@ -448,6 +478,8 @@
             ...createApplicationForm(),
             ...data,
             applyTime: normalizeDateTime(data.applyTime),
+            processInstanceId:
+              data.processInstanceId || row.processInstanceId || '',
             detailList
           };
           this.setDetailData(detailList);
@@ -648,6 +680,7 @@
         this.visible = false;
         this.loading = false;
         this.submitting = false;
+        this.activeTab = 'application';
         this.formData = createApplicationForm();
       }
     }
@@ -659,6 +692,78 @@
     width: 100%;
   }
 
+  .detail-tabs {
+    min-height: 420px;
+  }
+
+  .process-detail-pane {
+    min-height: 500px;
+    padding: 2px 0 8px;
+    border-radius: 10px;
+    background: #f4f7fb;
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header {
+    margin: 0 0 14px;
+    padding: 0 14px;
+    border: 1px solid #dce7f1;
+    border-radius: 10px;
+    background: linear-gradient(180deg, #ffffff 0%, #f5f9fd 100%);
+    box-shadow: 0 4px 12px rgba(31, 45, 61, 0.04);
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header .el-tabs__nav-wrap::after {
+    height: 0;
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header .el-tabs__item {
+    height: 46px;
+    padding: 0 24px;
+    color: #60758a;
+    font-size: 14px;
+    font-weight: 600;
+    line-height: 46px;
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header .el-tabs__item:hover {
+    color: #1684df;
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header .el-tabs__item.is-active {
+    color: #1478c9;
+  }
+
+  ::v-deep .detail-tabs > .el-tabs__header .el-tabs__active-bar {
+    height: 3px;
+    border-radius: 3px 3px 0 0;
+    background: linear-gradient(90deg, #1f8ceb 0%, #16b8a6 100%);
+  }
+
+  ::v-deep .detail-tabs--form > .el-tabs__header {
+    display: none;
+  }
+
+  ::v-deep .process-detail-pane .app-container {
+    padding: 0 !important;
+    background: transparent;
+  }
+
+  ::v-deep .process-detail-pane .box-card {
+    margin-bottom: 14px;
+    overflow: hidden;
+    border: 1px solid #dfe8f1;
+    border-radius: 10px;
+    box-shadow: 0 5px 16px rgba(31, 45, 61, 0.05);
+  }
+
+  ::v-deep .process-detail-pane .box-card > .el-card__header {
+    padding: 14px 18px;
+    border-bottom: 1px solid #e5edf5;
+    background: linear-gradient(180deg, #fbfdff 0%, #f4f8fc 100%);
+    color: #263f56;
+    font-weight: 700;
+  }
+
   .demand-form {
     padding: 4px 0 0;
   }

+ 45 - 37
src/views/demandApplication/index.vue

@@ -91,10 +91,9 @@
             type="success"
             :underline="false"
             icon="el-icon-position"
-            :disabled="isSubmitting(row)"
             @click="handleSubmit(row)"
           >
-            {{ isSubmitting(row) ? '提交中' : '提交' }}
+            提交
           </el-link>
           <!-- <el-link
             class="action-link action-link--view"
@@ -131,15 +130,26 @@
     </el-card>
 
     <demand-application-form ref="formRef" @success="refreshTable" />
+    <process-submit-dialog
+      v-if="processSubmitDialogFlag"
+      ref="processSubmitDialogRef"
+      :process-submit-dialog-flag.sync="processSubmitDialogFlag"
+      :is-not-need-process="false"
+      :is-close-refresh="false"
+      :custom-submit="submitDemandApplication"
+      @reload="handleProcessReload"
+    />
   </div>
 </template>
 
 <script>
+  import { mapGetters } from 'vuex';
   import {
     deleteDemandApplications,
     getDemandApplicationPage,
     submitDemandApplication
   } from '@/api/demandApplication';
+  import ProcessSubmitDialog from '@/components/processSubmitDialog/processSubmitDialog.vue';
   import tableColumnsMixin from '@/mixins/tableColumnsMixin';
   import DemandApplicationSearch from './components/DemandApplicationSearch.vue';
   import DemandApplicationForm from './components/DemandApplicationForm.vue';
@@ -153,13 +163,18 @@
 
   export default {
     name: 'DemandApplication',
-    components: { DemandApplicationSearch, DemandApplicationForm },
+    components: {
+      DemandApplicationSearch,
+      DemandApplicationForm,
+      ProcessSubmitDialog
+    },
     mixins: [tableColumnsMixin],
     data() {
       return {
         loading: false,
         selection: [],
-        submittingIds: [],
+        processSubmitDialogFlag: false,
+        processReloadPending: false,
         currentWhere: {},
         cacheKeyUrl: 'aps-demand-application-list',
         columnsVersion: 1,
@@ -167,6 +182,7 @@
       };
     },
     computed: {
+      ...mapGetters(['user']),
       canDeleteSelection() {
         return (
           this.selection.length > 0 &&
@@ -267,14 +283,12 @@
     methods: {
       approvalStatusLabel,
       approvalStatusType,
+      submitDemandApplication,
       canModify: canModifyApplication,
       canSubmit(row) {
         const status = Number(row && row.approvalStatus);
         return status === 0 || status === 3;
       },
-      isSubmitting(row) {
-        return this.submittingIds.includes(String(row && row.id));
-      },
       datasource({ page, limit, where }) {
         return getDemandApplicationPage({
           pageNum: page,
@@ -295,6 +309,14 @@
         this.selection = [];
         this.$refs.table.reload({ where: this.currentWhere });
       },
+      handleProcessReload() {
+        if (this.processReloadPending) return;
+        this.processReloadPending = true;
+        this.$nextTick(() => {
+          this.refreshTable();
+          this.processReloadPending = false;
+        });
+      },
       handleAdd() {
         this.$refs.formRef.open('add');
       },
@@ -305,37 +327,23 @@
         if (!row) return;
         this.$refs.formRef.open('edit', row);
       },
-      async handleSubmit(row) {
-        if (!row || !row.id || !this.canSubmit(row) || this.isSubmitting(row)) {
-          return;
-        }
-        try {
-          await this.$confirm(
-            '确认提交申请单“' +
-              (row.applyCode || row.id) +
-              '”吗?提交后将进入审批流程。',
-            '提交确认',
-            {
-              type: 'warning',
-              confirmButtonText: '确认提交',
-              cancelButtonText: '取消'
+      handleSubmit(row) {
+        if (!row || !row.id || !this.canSubmit(row)) return;
+        this.processSubmitDialogFlag = true;
+        this.$nextTick(() => {
+          const currentUser = (this.user && this.user.info) || {};
+          this.$refs.processSubmitDialogRef.init({
+            businessId: row.id,
+            businessKey: 't_aps_demand_apply',
+            formCreateUserId:
+              row.createUserId || currentUser.userId || currentUser.id,
+            variables: {
+              businessCode: row.applyCode || String(row.id),
+              businessName: '需求申请',
+              businessType: '需求申请'
             }
-          );
-        } catch (error) {
-          return;
-        }
-        const id = String(row.id);
-        this.submittingIds.push(id);
-        try {
-          await submitDemandApplication(row.id);
-          this.$message.success('提交成功');
-          this.selection = [];
-          this.$refs.table.reload({ where: this.currentWhere });
-        } catch (error) {
-          this.$message.error(error.message || '提交失败');
-        } finally {
-          this.submittingIds = this.submittingIds.filter((item) => item !== id);
-        }
+          });
+        });
       },
       async handleDelete(row) {
         const rows = row ? [row] : this.selection;

+ 10 - 0
src/views/productionPlan/components/newFactoryProductionScheduling.utils.js

@@ -38,3 +38,13 @@ export function isEndAfterPlanEnd(executionEndStr, planEndStr) {
   const p = new Date(planEndStr).getTime();
   return !Number.isNaN(e) && !Number.isNaN(p) && e > p;
 }
+
+/** 计划交付时间是日期字段,比较时应以该日期当天结束为上限 */
+export function isTimeAfterDeliveryDate(timeStr, deliveryDateStr) {
+  if (!timeStr || !deliveryDateStr) return false;
+  const time = new Date(timeStr).getTime();
+  const deliveryDate = new Date(deliveryDateStr);
+  if (Number.isNaN(time) || Number.isNaN(deliveryDate.getTime())) return false;
+  deliveryDate.setHours(23, 59, 59, 999);
+  return time > deliveryDate.getTime();
+}

+ 8 - 13
src/views/productionPlan/components/newFactoryProductionScheduling.vue

@@ -267,6 +267,7 @@
     formatDotLineDateTime,
     isEndAfterPlanEnd,
     isEndBeforeStart,
+    isTimeAfterDeliveryDate,
     toSafeNumber
   } from './newFactoryProductionScheduling.utils';
 
@@ -1551,9 +1552,7 @@
           deadline &&
           row.executionStartTime
         ) {
-          const d = new Date(deadline).getTime();
-          const v = new Date(row.executionStartTime).getTime();
-          if (!Number.isNaN(d) && !Number.isNaN(v) && v > d) {
+          if (isTimeAfterDeliveryDate(row.executionStartTime, deadline)) {
             this.$message.warning('时间不能大于计划交付时间');
             this.$set(row, changeKey, '');
             return;
@@ -1562,7 +1561,8 @@
         if (changeKey === 'executionEndTime' && row.executionEndTime) {
           const planEnd = this.currentPlan?.endTime;
           const overDelivery =
-            !!deadline && isEndAfterPlanEnd(row.executionEndTime, deadline);
+            !!deadline &&
+            isTimeAfterDeliveryDate(row.executionEndTime, deadline);
           const overPlanEnd =
             !!planEnd && isEndAfterPlanEnd(row.executionEndTime, planEnd);
           if (overDelivery && overPlanEnd) {
@@ -1599,7 +1599,7 @@
         return (
           !!deadline &&
           !!row?.executionEndTime &&
-          isEndAfterPlanEnd(row.executionEndTime, deadline)
+          isTimeAfterDeliveryDate(row.executionEndTime, deadline)
         );
       },
       isExecutionEndOverPlanEnd(row) {
@@ -1914,16 +1914,11 @@
         const deadline =
           this.currentPlan?.planDeliveryTime || this.currentPlan?.deliveryTime;
         if (deadline) {
-          const d = new Date(deadline).getTime();
           const checkStart = (val, name) => {
             if (!val) return true;
-            const t = new Date(val).getTime();
-            return Number.isNaN(d) || Number.isNaN(t) || t <= d
-              ? true
-              : (this.$message.warning(
-                  `${label(item)}${name}不能大于计划交付时间`
-                ),
-                false);
+            if (!isTimeAfterDeliveryDate(val, deadline)) return true;
+            this.$message.warning(`${label(item)}${name}不能大于计划交付时间`);
+            return false;
           };
           if (!checkStart(item.executionStartTime, '执行开始时间'))
             return false;

+ 20 - 13
src/views/productionPlan/components/planDotLine.vue

@@ -281,6 +281,17 @@
     return !Number.isNaN(e) && !Number.isNaN(p) && e > p;
   }
 
+  /** 计划交付时间是日期字段,比较时应以该日期当天结束为上限 */
+  function isTimeAfterDeliveryDate(timeStr, deliveryDateStr) {
+    if (!timeStr || !deliveryDateStr) return false;
+    const time = new Date(timeStr).getTime();
+    const deliveryDate = new Date(deliveryDateStr);
+    if (Number.isNaN(time) || Number.isNaN(deliveryDate.getTime()))
+      return false;
+    deliveryDate.setHours(23, 59, 59, 999);
+    return time > deliveryDate.getTime();
+  }
+
   export default {
     data() {
       return {
@@ -736,9 +747,7 @@
           deadline &&
           row.executionStartTime
         ) {
-          const d = new Date(deadline).getTime();
-          const v = new Date(row.executionStartTime).getTime();
-          if (!Number.isNaN(d) && !Number.isNaN(v) && v > d) {
+          if (isTimeAfterDeliveryDate(row.executionStartTime, deadline)) {
             this.$message.warning('时间不能大于计划交付时间');
             this.$set(row, changeKey, '');
             return;
@@ -747,7 +756,8 @@
         if (changeKey === 'executionEndTime' && row.executionEndTime) {
           const planEnd = this.currentPlan?.endTime;
           const overDelivery =
-            !!deadline && isEndAfterPlanEnd(row.executionEndTime, deadline);
+            !!deadline &&
+            isTimeAfterDeliveryDate(row.executionEndTime, deadline);
           const overPlanEnd =
             !!planEnd && isEndAfterPlanEnd(row.executionEndTime, planEnd);
           if (overDelivery && overPlanEnd) {
@@ -786,7 +796,7 @@
         return (
           !!deadline &&
           !!row?.executionEndTime &&
-          isEndAfterPlanEnd(row.executionEndTime, deadline)
+          isTimeAfterDeliveryDate(row.executionEndTime, deadline)
         );
       },
 
@@ -871,16 +881,13 @@
 
           const deadline = this.currentPlan?.planDeliveryTime;
           if (deadline) {
-            const d = new Date(deadline).getTime();
             const checkStart = (val, name) => {
               if (!val) return true;
-              const t = new Date(val).getTime();
-              return Number.isNaN(d) || Number.isNaN(t) || t <= d
-                ? true
-                : (this.$message.warning(
-                    `${label(item)}${name}不能大于计划交付时间`
-                  ),
-                  false);
+              if (!isTimeAfterDeliveryDate(val, deadline)) return true;
+              this.$message.warning(
+                `${label(item)}${name}不能大于计划交付时间`
+              );
+              return false;
             };
             if (!checkStart(item.executionStartTime, '执行开始时间'))
               return false;