From dacf37deb3d53345024402016e9c4d19ac82e3aa Mon Sep 17 00:00:00 2001
From: cuilei <ray_tsu1@163.com>
Date: 星期四, 07 八月 2025 10:29:19 +0800
Subject: [PATCH] 生产管控 排产工单页面

---
 src/views/mes/MesProductionWorkOrderList.vue                   |  780 ++++++++++++++++++++---------
 src/views/mes/modules/MesProductionWorkOrderRepublishModal.vue |  132 +++++
 src/views/mes/modules/MesProductionWeekCalendar.vue            |  241 +++++++++
 src/views/mes/modules/MesProductionWorkOrderForm.vue           |   18 
 src/views/mes/modules/MesProductionWorkOrderListModal.vue      |  375 ++++++++++++++
 src/views/mes/modules/MesProductionWorkOrderModal.vue          |    2 
 6 files changed, 1,298 insertions(+), 250 deletions(-)

diff --git a/src/views/mes/MesProductionWorkOrderList.vue b/src/views/mes/MesProductionWorkOrderList.vue
index d81fb4d..8d1fe7d 100644
--- a/src/views/mes/MesProductionWorkOrderList.vue
+++ b/src/views/mes/MesProductionWorkOrderList.vue
@@ -1,266 +1,566 @@
 <template>
-  <a-card :bordered="false">
-    <!-- 鏌ヨ鍖哄煙 -->
-    <div class="table-page-search-wrapper">
-      <a-form layout="inline" @keyup.enter.native="searchQuery">
-        <a-row :gutter="24">
-          <a-col :xl="6" :lg="7" :md="8" :sm="24">
-            <a-form-item label="宸ュ崟鍙�(浠诲姟鍙�)">
-              <j-input placeholder="璇疯緭鍏ュ伐鍗曞彿(浠诲姟鍙�)" v-model="queryParam.workOrderCode"></j-input>
-            </a-form-item>
-          </a-col>
-          <a-col :xl="6" :lg="7" :md="8" :sm="24">
-            <a-form-item label="鐗╂枡缂栧彿">
-              <j-input placeholder="璇疯緭鍏ョ墿鏂欑紪鍙�" v-model="queryParam.materialNumber"></j-input>
-            </a-form-item>
-          </a-col>
-          <a-col :xl="6" :lg="7" :md="8" :sm="24">
-            <a-form-item label="宸ュ崟鐘舵��">
-              <j-dict-select-tag dictCode="work_order_status" placeholder="璇疯緭鍏ュ伐鍗曠姸鎬�" v-model="queryParam.workOrderStatus"></j-dict-select-tag>
-            </a-form-item>
-          </a-col>
-          <a-col :xl="6" :lg="7" :md="8" :sm="24">
-            <a-form-item label="閲嶅彂甯冧汉">
-              <j-select-user-by-dep placeholder="璇疯緭鍏ラ噸鍙戝竷浜�" v-model="queryParam.republisher"></j-select-user-by-dep>
-            </a-form-item>
-          </a-col>
-          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+  <a-row :gutter="{ xs: 4, sm: 8, md: 16}">
+    <a-col :span="12">
+      <a-card :bordered="false">
+        <!-- 鏌ヨ鍖哄煙 -->
+        <div class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="searchQuery">
+            <a-row :gutter="24">
+              <a-col :span="12">
+                <a-form-item label="浜х嚎">
+                  <j-tree-select dict="base_factory,factory_name,id" pid-field="parent_id"
+                                 v-model="queryParam.factoryId"></j-tree-select>
+                </a-form-item>
+              </a-col>
+              <a-col :span="12">
+                <a-form-item label="璧锋鏃ユ湡">
+                  <a-range-picker
+                    style="width: 100%"
+                    @change="dateRangeChange"
+                    :value="dateRange"
+                    :disabledDate="disabledDate"
+                    @openChange="onOpenChange"
+                  />
+                </a-form-item>
+              </a-col>
+              <a-col :xl="6" :lg="7" :md="8" :sm="24">
             <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
               <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button>
-              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">閲嶇疆</a-button>
+              <a-button type="info" @click="searchReset" icon="reload" style="margin-left: 8px">閲嶇疆</a-button>
+              <a-button type="primary" @click="productionSchedule" icon="retweet"
+                        style="margin-left: 8px">鎺掍骇</a-button>
             </span>
-          </a-col>
-        </a-row>
-      </a-form>
-    </div>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
 
-    <div class="table-operator">
-      <a-dropdown v-if="selectedRowKeys.length > 0">
-        <a-menu slot="overlay">
-          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>鍒犻櫎</a-menu-item>
-        </a-menu>
-        <a-button style="margin-left: 8px"> 鎵归噺鎿嶄綔 <a-icon type="down" /></a-button>
-      </a-dropdown>
-    </div>
-    <div>
-      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
-        <i class="anticon anticon-info-circle ant-alert-icon"></i> 宸查�夋嫨 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>椤�
-        <a style="margin-left: 24px" @click="onClearSelected">娓呯┖</a>
-      </div>
-
-      <a-table
-        ref="table"
-        size="middle"
-        :scroll="{x:true}"
-        bordered
-        rowKey="id"
-        :columns="columns"
-        :dataSource="dataSource"
-        :pagination="ipagination"
-        :loading="loading"
-        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
-        class="j-table-force-nowrap"
-        @change="handleTableChange">
-
-        <template slot="htmlSlot" slot-scope="text">
-          <div v-html="text"></div>
-        </template>
-        <template slot="imgSlot" slot-scope="text,record">
-          <span v-if="!text" style="font-size: 12px;font-style: italic;">鏃犲浘鐗�</span>
-          <img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
-        </template>
-        <template slot="fileSlot" slot-scope="text">
-          <span v-if="!text" style="font-size: 12px;font-style: italic;">鏃犳枃浠�</span>
-          <a-button
-            v-else
-            :ghost="true"
-            type="primary"
-            icon="download"
-            size="small"
-            @click="downloadFile(text)">
-            涓嬭浇
-          </a-button>
-        </template>
-
-        <span slot="action" slot-scope="text, record">
-          <a @click="handleEdit(record)">缂栬緫</a>
-
-          <a-divider type="vertical" />
-          <a-dropdown>
-            <a class="ant-dropdown-link">鏇村 <a-icon type="down" /></a>
+        <div class="table-operator">
+          <a-dropdown v-if="selectedRowKeys.length > 0">
             <a-menu slot="overlay">
-              <a-menu-item>
-                <a @click="handleDetail(record)">璇︽儏</a>
-              </a-menu-item>
-              <a-menu-item>
-                <a-popconfirm title="纭畾鍒犻櫎鍚�?" @confirm="() => handleDelete(record.id)">
-                  <a>鍒犻櫎</a>
-                </a-popconfirm>
+              <a-menu-item key="1" @click="batchDel">
+                <a-icon type="delete" />
+                鍒犻櫎
               </a-menu-item>
             </a-menu>
+            <a-button style="margin-left: 8px"> 鎵归噺鎿嶄綔
+              <a-icon type="down" />
+            </a-button>
           </a-dropdown>
+        </div>
+        <div>
+          <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+            <i class="anticon anticon-info-circle ant-alert-icon"></i> 宸查�夋嫨 <a
+            style="font-weight: 600">{{ selectedRowKeys.length }}</a>椤�
+            <a style="margin-left: 24px" @click="onClearSelected">娓呯┖</a>
+          </div>
+
+          <a-table
+            ref="table"
+            size="middle"
+            :scroll="{x:true}"
+            bordered
+            rowKey="id"
+            :columns="columns"
+            :dataSource="dataSource"
+            :pagination="ipagination"
+            :loading="loading"
+            :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+            class="j-table-force-nowrap"
+            @change="handleTableChange">
+
+            <template slot="htmlSlot" slot-scope="text">
+              <div v-html="text"></div>
+            </template>
+            <template slot="imgSlot" slot-scope="text,record">
+              <span v-if="!text" style="font-size: 12px;font-style: italic;">鏃犲浘鐗�</span>
+              <img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt=""
+                   style="max-width:80px;font-size: 12px;font-style: italic;" />
+            </template>
+            <template slot="fileSlot" slot-scope="text">
+              <span v-if="!text" style="font-size: 12px;font-style: italic;">鏃犳枃浠�</span>
+              <a-button
+                v-else
+                :ghost="true"
+                type="primary"
+                icon="download"
+                size="small"
+                @click="downloadFile(text)">
+                涓嬭浇
+              </a-button>
+            </template>
+
+            <span slot="action" slot-scope="text, record">
+              <span v-if="record.workOrderStatus === 'NEW'">
+                <a-popconfirm title="纭畾鍙戝竷鍚�?" @confirm="() => handlePublish(record.id)">
+                  <a>鍙戝竷</a>
+                </a-popconfirm>
+                <a-divider type="vertical" />
+              </span>
+              <span v-if="record.workOrderStatus === 'PUBLISHED'">
+                <a @click="handleRePublish(record)">閲嶅彂甯�</a>
+                <a-divider type="vertical" />
+              </span>
+              <span>
+                <a-dropdown v-if="record.workOrderStatus === 'NEW'">
+                  <a class="ant-dropdown-link">鏇村 <a-icon type="down" /></a>
+                    <a-menu slot="overlay">
+                    <a-menu-item>
+                      <a @click="handleDetail(record)">璇︽儏</a>
+                    </a-menu-item>
+                    <a-menu-item>
+                      <a-popconfirm title="纭畾鍒犻櫎鍚�?" @confirm="() => handleDelete(record.id)">
+                        <a>鍒犻櫎</a>
+                      </a-popconfirm>
+                    </a-menu-item>
+                    </a-menu>
+                </a-dropdown>
+              </span>
+              <span v-if="record.workOrderStatus !== 'NEW'">
+                <a @click="handleDetail(record)">璇︽儏</a>
+              </span>
         </span>
+          </a-table>
+        </div>
 
-      </a-table>
-    </div>
-
-    <mes-production-work-order-modal ref="modalForm" @ok="modalFormOk"></mes-production-work-order-modal>
-  </a-card>
+        <mes-production-work-order-list-modal ref="modal" @ok="modalFormOk"></mes-production-work-order-list-modal>
+        <mes-production-work-order-modal ref="modalForm"></mes-production-work-order-modal>
+        <mes-production-work-order-republish-modal ref="republishModal" @ok="modalFormOk"></mes-production-work-order-republish-modal>
+      </a-card>
+    </a-col>
+    <a-col :span="12">
+      <a-card>
+        <MesProductionWeekCalendar
+          ref="weekCalendar"
+          :start-date="calendarStartDate"
+          @select="onDateSelect"
+          @change="onCalendarChange"
+        >
+          <!-- 浣跨敤鎻掓Ы鑷畾涔夋棩鏈熷崟鍏冩牸鍐呭 -->
+          <template #dateCell="{ date, isSelected, isToday }">
+            <div class="custom-date-content">
+              <!-- 绀轰緥锛氬湪鏃ユ湡鍗曞厓鏍间腑鏄剧ず宸ュ崟淇℃伅 -->
+              <div
+                v-for="workOrder in getWorkOrdersForDate(date)"
+                :key="workOrder.id"
+                class="work-order-item"
+                :class="{ 'urgent': isUrgent(workOrder) }"
+              >
+                <span class="work-order-shift">{{ workOrder.groupName }}</span>
+                <span class="work-order-material">{{ workOrder.materialName }}</span>
+                <span class="work-order-quantity">{{ workOrder.planQuantity }}</span>
+              </div>
+            </div>
+          </template>
+        </MesProductionWeekCalendar>
+      </a-card>
+    </a-col>
+  </a-row>
 </template>
 
 <script>
 
-  import '@/assets/less/TableExpand.less'
-  import { mixinDevice } from '@/utils/mixin'
-  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
-  import MesProductionWorkOrderModal from './modules/MesProductionWorkOrderModal'
-  import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
+import '@/assets/less/TableExpand.less'
+import { mixinDevice } from '@/utils/mixin'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import MesProductionWorkOrderModal from './modules/MesProductionWorkOrderModal'
+import MesProductionWeekCalendar from '@views/mes/modules/MesProductionWeekCalendar.vue'
+import MesProductionWorkOrderListModal from '@views/mes/modules/MesProductionWorkOrderListModal.vue'
+import MesProductionWorkOrderRepublishModal from '@views/mes/modules/MesProductionWorkOrderRepublishModal.vue'
+import { filterMultiDictText } from '@/components/dict/JDictSelectUtil'
+import moment from 'moment'
+import { getAction, postAction, requestPut } from '@api/manage'
 
-  export default {
-    name: 'MesProductionWorkOrderList',
-    mixins:[JeecgListMixin, mixinDevice],
-    components: {
-      MesProductionWorkOrderModal
-    },
-    data () {
-      return {
-        description: '鎺掍骇宸ュ崟绠$悊椤甸潰',
-        // 琛ㄥご
-        columns: [
-          {
-            title: '#',
-            dataIndex: '',
-            key:'rowIndex',
-            width:60,
-            align:"center",
-            customRender:function (t,r,index) {
-              return parseInt(index)+1;
-            }
-          },
-          {
-            title:'宸ュ崟鍙�(浠诲姟鍙�)',
-            align:"center",
-            dataIndex: 'workOrderCode'
-          },
-          {
-            title:'鐗╂枡缂栫爜',
-            align:"center",
-            dataIndex: 'materialNumber'
-          },
-          {
-            title:'鐗╂枡鍚嶇О',
-            align:"center",
-            dataIndex: 'materialName'
-          },
-          {
-            title:'璁″垝鐢熶骇鏁伴噺',
-            align:"center",
-            dataIndex: 'planQuantity'
-          },
-          {
-            title:'浜х嚎(鍐椾綑)',
-            align:"center",
-            dataIndex: 'factoryId_dictText'
-          },
-          {
-            title:'鐝粍',
-            align:"center",
-            dataIndex: 'groupId_dictText'
-          },
-          {
-            title:'鐝(鍐椾綑)',
-            align:"center",
-            dataIndex: 'shiftId_dictText'
-          },
-          {
-            title:'鎺掍骇鏃ユ湡',
-            align:"center",
-            dataIndex: 'workOrderDate'
-          },
-          {
-            title:'宸ュ崟鐘舵��',
-            align:"center",
-            dataIndex: 'workOrderStatus_dictText'
-          },
-          {
-            title:'瀹為檯鎶ュ伐鏁伴噺',
-            align:"center",
-            dataIndex: 'actualQuantity'
-          },
-          {
-            title:'鍙戝竷浜�',
-            align:"center",
-            dataIndex: 'publisher'
-          },
-          {
-            title:'鍙戝竷鏃堕棿',
-            align:"center",
-            dataIndex: 'publishTime'
-          },
-          {
-            title:'閲嶅彂甯冧汉',
-            align:"center",
-            dataIndex: 'republisher'
-          },
-          {
-            title:'閲嶅彂甯冩椂闂�',
-            align:"center",
-            dataIndex: 'republishTime'
-          },
-          {
-            title: '鎿嶄綔',
-            dataIndex: 'action',
-            align:"center",
-            fixed:"right",
-            width:147,
-            scopedSlots: { customRender: 'action' }
+export default {
+  name: 'MesProductionWorkOrderList',
+  mixins: [JeecgListMixin, mixinDevice],
+  components: {
+    MesProductionWorkOrderModal,
+    MesProductionWeekCalendar,
+    MesProductionWorkOrderListModal,
+    MesProductionWorkOrderRepublishModal
+  },
+  data() {
+    return {
+      description: '鎺掍骇宸ュ崟绠$悊椤甸潰',
+      // 琛ㄥご
+      columns: [
+        {
+          title: '#',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
           }
-        ],
-        url: {
-          list: "/mesproductionworkorder/mesProductionWorkOrder/list",
-          delete: "/mesproductionworkorder/mesProductionWorkOrder/delete",
-          deleteBatch: "/mesproductionworkorder/mesProductionWorkOrder/deleteBatch",
-          exportXlsUrl: "/mesproductionworkorder/mesProductionWorkOrder/exportXls",
-          importExcelUrl: "mesproductionworkorder/mesProductionWorkOrder/importExcel",
-
         },
-        dictOptions:{},
-        superFieldList:[],
+        {
+          title: '宸ュ崟鍙�(浠诲姟鍙�)',
+          align: 'center',
+          dataIndex: 'workOrderCode'
+        },
+        {
+          title: '鐗╂枡缂栫爜',
+          align: 'center',
+          dataIndex: 'materialNumber'
+        },
+        {
+          title: '鐗╂枡鍚嶇О',
+          align: 'center',
+          dataIndex: 'materialName'
+        },
+        {
+          title: '璁″垝鐢熶骇鏁伴噺',
+          align: 'center',
+          dataIndex: 'planQuantity'
+        },
+        {
+          title: '浜х嚎',
+          align: 'center',
+          dataIndex: 'factoryId_dictText'
+        },
+        {
+          title: '鐝粍',
+          align: 'center',
+          dataIndex: 'groupId_dictText'
+        },
+        {
+          title: '鐝',
+          align: 'center',
+          dataIndex: 'shiftId_dictText'
+        },
+        {
+          title: '鎺掍骇鏃ユ湡',
+          align: 'center',
+          dataIndex: 'workOrderDate'
+        },
+        {
+          title: '宸ュ崟鐘舵��',
+          align: 'center',
+          dataIndex: 'workOrderStatus_dictText'
+        },
+        {
+          title: '瀹為檯鎶ュ伐鏁伴噺',
+          align: 'center',
+          dataIndex: 'actualQuantity'
+        },
+        {
+          title: '鍙戝竷浜�',
+          align: 'center',
+          dataIndex: 'publisher'
+        },
+        {
+          title: '鍙戝竷鏃堕棿',
+          align: 'center',
+          dataIndex: 'publishTime'
+        },
+        {
+          title: '閲嶅彂甯冧汉',
+          align: 'center',
+          dataIndex: 'republisher'
+        },
+        {
+          title: '閲嶅彂甯冩椂闂�',
+          align: 'center',
+          dataIndex: 'republishTime'
+        },
+        {
+          title: '鎿嶄綔',
+          dataIndex: 'action',
+          align: 'center',
+          fixed: 'right',
+          width: 147,
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      url: {
+        list: '/mesproductionworkorder/mesProductionWorkOrder/list',
+        delete: '/mesproductionworkorder/mesProductionWorkOrder/delete',
+        deleteBatch: '/mesproductionworkorder/mesProductionWorkOrder/deleteBatch',
+        exportXlsUrl: '/mesproductionworkorder/mesProductionWorkOrder/exportXls',
+        importExcelUrl: 'mesproductionworkorder/mesProductionWorkOrder/importExcel',
+        listProductionLinesOption: '/base/factory/queryIdTree',
+        schedule: '/mesproductionworkorder/mesProductionWorkOrder/schedule',
+        publish: '/mesproductionworkorder/mesProductionWorkOrder/publish'
+      },
+      dictOptions: {},
+      superFieldList: [],
+      // 鐢ㄤ簬婕旂ず鐨勫伐鍗曟暟鎹�
+      workOrdersByDate: {},
+      // 鏃ュ巻璧峰鏃ユ湡
+      calendarStartDate: moment(),
+      productionLineData: [],
+      dateRange: [],
+      tempStartDate: null, // 涓存椂瀛樺偍寮�濮嬫棩鏈�
+      hoveredDate: null,    // 瀛樺偍榧犳爣鎮仠鐨勬棩鏈�
+    }
+  },
+  created() {
+    this.getSuperFieldList()
+    this.initDictConfig()
+  },
+  computed: {
+    importExcelUrl: function() {
+      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
+    }
+  },
+  methods: {
+    modalFormOk() {
+      this.onClearSelected()
+      this.loadData(1).then(() => {
+        if (this.queryParam.factoryId) {
+          // 鍚屾椂鏇存柊鏃ュ巻涓殑宸ュ崟鏁版嵁
+          this.updateCalendarWorkOrders()
+        }
+      }).catch(error => {
+        console.error('鏁版嵁鍔犺浇澶辫触:', error)
+      })
+    },
+    loadData(arg) {
+      return new Promise((resolve, reject) => {
+        if (!this.url.list) {
+          this.$message.error("璇疯缃畊rl.list灞炴��!")
+          reject(new Error("璇疯缃畊rl.list灞炴��!"))
+          return
+        }
+        //鍔犺浇鏁版嵁 鑻ヤ紶鍏ュ弬鏁�1鍒欏姞杞界涓�椤电殑鍐呭
+        if (arg === 1) {
+          this.ipagination.current = 1;
+        }
+        var params = this.getQueryParams();//鏌ヨ鏉′欢
+        console.log('params', params)
+        if (!params) {
+          reject(new Error("鏌ヨ鍙傛暟鏃犳晥"))
+          return false;
+        }
+        this.loading = true;
+        getAction(this.url.list, params).then((res) => {
+          if (res.success) {
+            // console.log(res)
+            //update-begin---author:zhangyafei    Date:20201118  for锛氶�傞厤涓嶅垎椤电殑鏁版嵁鍒楄〃------------
+            this.dataSource = res.result.records || res.result;
+            if (res.result.total) {
+              this.ipagination.total = res.result.total;
+            } else {
+              this.ipagination.total = 0;
+            }
+            //update-end---author:zhangyafei    Date:20201118  for锛氶�傞厤涓嶅垎椤电殑鏁版嵁鍒楄〃------------
+            resolve(res)
+          } else {
+            this.$message.warning(res.message)
+            reject(new Error(res.message))
+          }
+        }).catch(error => {
+          reject(error)
+        }).finally(() => {
+          this.loading = false
+        })
+      })
+    },
+    searchQuery() {
+      this.queryParam = Object.assign(this.queryParam, this.dateRange)
+      this.loadData(1).then(() => {
+        if (this.queryParam.factoryId) {
+          // 鍚屾椂鏇存柊鏃ュ巻涓殑宸ュ崟鏁版嵁
+          this.updateCalendarWorkOrders()
+        }
+      }).catch(error => {
+        console.error('鏁版嵁鍔犺浇澶辫触:', error)
+      })
+    },
+    searchReset() {
+      this.queryParam = {}
+      this.dateRange = []
+      this.workOrdersByDate = {}
+      this.loadData(1);
+    },
+    handlePublish(id) {
+      requestPut(this.url.publish, null, { ids: id }).then(res => {
+        if (res.success) {
+          this.$message.success(res.message)
+          this.loadData(1).then(() => {
+            if (this.queryParam.factoryId) {
+              // 鍚屾椂鏇存柊鏃ュ巻涓殑宸ュ崟鏁版嵁
+              this.updateCalendarWorkOrders()
+            }
+          }).catch(error => {
+            console.error('鏁版嵁鍔犺浇澶辫触:', error)
+          })
+        } else {
+          this.$message.warning(res.message)
+        }
+      })
+    },
+    handleRePublish(record) {
+      this.$refs.republishModal.add(record)
+    },
+    initDictConfig() {
+      getAction(this.url.listProductionLinesOption, null).then(res => {
+        if (res.success) {
+          this.productionLineData = res.result
+        }
+      })
+    },
+    getSuperFieldList() {
+      let fieldList = []
+      fieldList.push({ type: 'int', value: 'delFlag', text: '鍒犻櫎鏍囪', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'workOrderCode', text: '宸ュ崟鍙�(浠诲姟鍙�)', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'materialNumber', text: '鐗╂枡缂栫爜', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'materialName', text: '鐗╂枡鍚嶇О', dictCode: '' })
+      fieldList.push({ type: 'double', value: 'planQuantity', text: '璁″垝鐢熶骇鏁伴噺', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'factoryId', text: '浜х嚎ID(鍐椾綑)', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'groupId', text: '鐝粍ID', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'shiftId', text: '鐝ID(鍐椾綑)', dictCode: '' })
+      fieldList.push({ type: 'datetime', value: 'workOrderDate', text: '鎺掍骇鏃ユ湡' })
+      fieldList.push({ type: 'string', value: 'workOrderStatus', text: '宸ュ崟鐘舵��', dictCode: 'work_order_status' })
+      fieldList.push({ type: 'double', value: 'actualQuantity', text: '瀹為檯鎶ュ伐鏁伴噺', dictCode: '' })
+      fieldList.push({ type: 'string', value: 'publisher', text: '鍙戝竷浜�', dictCode: '' })
+      fieldList.push({ type: 'datetime', value: 'publishTime', text: '鍙戝竷鏃堕棿' })
+      fieldList.push({ type: 'string', value: 'republisher', text: '閲嶅彂甯冧汉', dictCode: '' })
+      fieldList.push({ type: 'datetime', value: 'republishTime', text: '閲嶅彂甯冩椂闂�' })
+      this.superFieldList = fieldList
+    },
+    productionSchedule() {
+      if (!this.queryParam.factoryId || this.dateRange.length === 0) {
+        this.$message.warning('璇烽�夋嫨浜х嚎鍙婃帓浜ф棩鏈熻寖鍥达紒')
+        return
+      }
+      getAction(this.url.schedule, {
+        factoryId: this.queryParam.factoryId,
+        startDate: this.dateRange[0].format('YYYY-MM-DD'),
+        endDate: this.dateRange[1].format('YYYY-MM-DD')
+      }).then(res => {
+        if (res.success) {
+          this.$refs.modal.edit(res.result, this.dateRange)
+        }
+      })
+    },
+    onOpenChange(open) {
+      if (!open) {
+        // 鍏抽棴閫夋嫨鍣ㄦ椂閲嶇疆鐘舵��
+        this.tempStartDate = null
+        this.hoveredDate = null
       }
     },
-    created() {
-    this.getSuperFieldList();
-    },
-    computed: {
-      importExcelUrl: function(){
-        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
-      },
-    },
-    methods: {
-      initDictConfig(){
-      },
-      getSuperFieldList(){
-        let fieldList=[];
-        fieldList.push({type:'int',value:'delFlag',text:'鍒犻櫎鏍囪',dictCode:''})
-        fieldList.push({type:'string',value:'workOrderCode',text:'宸ュ崟鍙�(浠诲姟鍙�)',dictCode:''})
-        fieldList.push({type:'string',value:'materialNumber',text:'鐗╂枡缂栫爜',dictCode:''})
-        fieldList.push({type:'string',value:'materialName',text:'鐗╂枡鍚嶇О',dictCode:''})
-        fieldList.push({type:'double',value:'planQuantity',text:'璁″垝鐢熶骇鏁伴噺',dictCode:''})
-        fieldList.push({type:'string',value:'factoryId',text:'浜х嚎ID(鍐椾綑)',dictCode:''})
-        fieldList.push({type:'string',value:'groupId',text:'鐝粍ID',dictCode:''})
-        fieldList.push({type:'string',value:'shiftId',text:'鐝ID(鍐椾綑)',dictCode:''})
-        fieldList.push({type:'datetime',value:'workOrderDate',text:'鎺掍骇鏃ユ湡'})
-        fieldList.push({type:'string',value:'workOrderStatus',text:'宸ュ崟鐘舵��',dictCode:'work_order_status'})
-        fieldList.push({type:'double',value:'actualQuantity',text:'瀹為檯鎶ュ伐鏁伴噺',dictCode:''})
-        fieldList.push({type:'string',value:'publisher',text:'鍙戝竷浜�',dictCode:''})
-        fieldList.push({type:'datetime',value:'publishTime',text:'鍙戝竷鏃堕棿'})
-        fieldList.push({type:'string',value:'republisher',text:'閲嶅彂甯冧汉',dictCode:''})
-        fieldList.push({type:'datetime',value:'republishTime',text:'閲嶅彂甯冩椂闂�'})
-        this.superFieldList = fieldList
+    disabledDate(current) {
+      // 濡傛灉鏈変复鏃跺紑濮嬫棩鏈燂紝鍒欓檺鍒剁粨鏉熸棩鏈熻寖鍥�
+      if (this.tempStartDate) {
+        const startDate = this.tempStartDate.clone().startOf('day')
+        const maxDate = startDate.clone().add(6, 'days').endOf('day') // 7澶╁寘鎷捣濮嬫棩
+        const minDate = startDate.clone().subtract(6, 'days').startOf('day') // 涔熷彲浠ュ悜鍓嶉��6澶�
+        // 绂佺敤瓒呭嚭7澶╄寖鍥寸殑鏃ユ湡
+        return current && (current < minDate || current > maxDate)
       }
+      // 榛樿涓嶇鐢�
+      return false
+    },
+    dateRangeChange(dates, dateStrings) {
+      this.dateRange = dates
+      if (dates && dates.length > 0) {
+        if (dates.length === 1) {
+          // 閫夋嫨浜嗗紑濮嬫棩鏈燂紝淇濆瓨鍒颁复鏃跺彉閲�
+          this.tempStartDate = dates[0]
+          this.hoveredDate = dates[0]
+        } else if (dates.length === 2) {
+          // 閫夋嫨浜嗙粨鏉熸棩鏈燂紝楠岃瘉鑼冨洿
+          const startDate = dates[0]
+          const endDate = dates[1]
+          const diffDays = endDate.diff(startDate, 'days') + 1
+
+          if (diffDays > 7) {
+            this.$message.warning('鏃ユ湡鑼冨洿涓嶈兘瓒呰繃7澶�')
+            // 鑷姩璋冩暣涓�7澶╄寖鍥�
+            const adjustedEndDate = startDate.clone().add(6, 'days')
+            this.dateRange = [startDate, adjustedEndDate]
+            this.queryParam.startDate = startDate.format('YYYY-MM-DD')
+            this.queryParam.endDate = adjustedEndDate.format('YYYY-MM-DD')
+          } else {
+            this.queryParam.startDate = dateStrings[0]
+            this.queryParam.endDate = dateStrings[1]
+          }
+          // 閲嶇疆涓存椂鐘舵��
+          this.tempStartDate = null
+          this.hoveredDate = null
+        }
+      } else {
+        // 娓呴櫎浜嗛�夋嫨
+        this.queryParam.startDate = null
+        this.queryParam.endDate = null
+        this.tempStartDate = null
+        this.hoveredDate = null
+      }
+    },
+    // 澶勭悊鏃ユ湡閫夋嫨浜嬩欢
+    onDateSelect(date) {
+      console.log('Selected date:', date.format('YYYY-MM-DD'))
+    },
+    // 澶勭悊鏃ュ巻鍛ㄥ彉鍖栦簨浠�
+    onCalendarChange(date) {
+      console.log('Calendar week changed:', date.format('YYYY-MM-DD'))
+    },
+    // 鏇存柊鏃ュ巻涓殑宸ュ崟鏁版嵁
+    updateCalendarWorkOrders() {
+      // 灏嗗綋鍓嶈〃鏍兼暟鎹寜鏃ユ湡鍒嗙粍鏄剧ず鍦ㄦ棩鍘嗕腑
+      const workOrdersByDate = {}
+      this.dataSource.filter(workOrder => workOrder.workOrderStatus !== 'NEW').forEach(workOrder => {
+        const workOrderDate = workOrder.workOrderDate
+        if (workOrderDate) {
+          if (!workOrdersByDate[workOrderDate]) {
+            workOrdersByDate[workOrderDate] = []
+          }
+          workOrdersByDate[workOrderDate].push({
+            id: workOrder.id,
+            groupName: workOrder.groupId_dictText || '',
+            materialName: workOrder.materialName || '',
+            planQuantity: workOrder.planQuantity || 0
+          })
+        }
+      })
+      this.workOrdersByDate = workOrdersByDate
+    },
+    // 鑾峰彇鎸囧畾鏃ユ湡鐨勫伐鍗�
+    getWorkOrdersForDate(date) {
+      const dateStr = date.format('YYYY-MM-DD')
+      console.log(dateStr)
+      return this.workOrdersByDate[dateStr] || []
+    },
+    // 鍒ゆ柇宸ュ崟鏄惁绱ф��
+    isUrgent(workOrder) {
+      return workOrder.status === 'urgent'
     }
   }
+}
 </script>
 <style scoped>
-  @import '~@assets/less/common.less';
+@import '~@assets/less/common.less';
+
+.work-order-item {
+  font-size: 12px;
+  padding: 2px 4px;
+  margin-bottom: 2px;
+  background-color: #f0f0f0;
+  border-radius: 2px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.work-order-item.urgent {
+  background-color: #ffccc7;
+  border-left: 2px solid #ff4d4f;
+}
+
+.work-order-shift {
+  font-weight: bold;
+  margin-right: 4px;
+}
+
+.work-order-material {
+  margin-right: 4px;
+}
+
+.work-order-quantity {
+  float: right;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/mes/modules/MesProductionWeekCalendar.vue b/src/views/mes/modules/MesProductionWeekCalendar.vue
new file mode 100644
index 0000000..46c0716
--- /dev/null
+++ b/src/views/mes/modules/MesProductionWeekCalendar.vue
@@ -0,0 +1,241 @@
+<!-- src/views/mes/modules/MesProductionWeekCalendar.vue -->
+<template>
+  <div class="week-calendar">
+    <div class="calendar-header">
+      <a-button icon="left" @click="prevWeek" size="small" />
+      <span class="current-week-range">{{ weekRangeText }}</span>
+      <a-button icon="right" @click="nextWeek" size="small" />
+      <a-button @click="goToToday" size="small" style="margin-left: 8px">浠婂ぉ</a-button>
+    </div>
+
+    <div class="calendar-grid">
+      <div class="week-header">
+        <div
+          v-for="(day, index) in weekDays"
+          :key="index"
+          class="header-cell"
+        >
+          <div class="day-name">{{ day.format('ddd') }}</div>
+          <div
+            class="day-number"
+            :class="{ today: isToday(day), selected: isSelected(day) }"
+            @click="selectDay(day)"
+          >
+            {{ day.date() }}
+          </div>
+        </div>
+      </div>
+
+      <div class="calendar-body">
+        <div
+          v-for="(day, index) in weekDays"
+          :key="index"
+          class="day-cell"
+          :class="{ today: isToday(day), selected: isSelected(day) }"
+          @click="selectDay(day)"
+        >
+          <div class="cell-content">
+            <!-- 鎻掓Ы鐢ㄤ簬娓叉煋鏃ユ湡鍐呭 -->
+            <slot
+              name="dateCell"
+              :date="day"
+              :isSelected="isSelected(day)"
+              :isToday="isToday(day)"
+            >
+              <!-- 榛樿鍐呭 -->
+              <div class="default-content">
+                <!-- 鍙互鍦ㄨ繖閲屾坊鍔犻粯璁ょ殑鏃ユ湡鍐呭娓叉煋閫昏緫 -->
+              </div>
+            </slot>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+
+export default {
+  name: 'MesProductionWeekCalendar',
+  props: {
+    // 璧峰鏃ユ湡锛岄粯璁や负浠婂ぉ
+    startDate: {
+      type: [Object, String, Date],
+      default: null
+    }
+  },
+  data() {
+    return {
+      // 褰撳墠鏄剧ず鐨勮捣濮嬫棩鏈�
+      currentStartDate: this.startDate ? moment(this.startDate) : moment(),
+      // 閫変腑鐨勬棩鏈�
+      selectedDate: this.startDate ? moment(this.startDate) : moment()
+    }
+  },
+  computed: {
+    // 璁$畻杩炵画7澶╃殑鏃ユ湡
+    weekDays() {
+      const days = []
+      for (let i = 0; i < 7; i++) {
+        days.push(this.currentStartDate.clone().add(i, 'days'))
+      }
+      return days
+    },
+    // 褰撳墠鏄剧ず鐨勬棩鏈熻寖鍥存枃鏈�
+    weekRangeText() {
+      const start = this.currentStartDate
+      const end = this.currentStartDate.clone().add(6, 'days')
+
+      if (start.month() === end.month()) {
+        return `${start.format('YYYY骞碝鏈圖鏃�')} - ${end.format('D鏃�')}`
+      } else {
+        return `${start.format('YYYY骞碝鏈圖鏃�')} - ${end.format('M鏈圖鏃�')}`
+      }
+    }
+  },
+  watch: {
+    startDate(newVal) {
+      if (newVal) {
+        this.currentStartDate = moment(newVal)
+        this.selectedDate = moment(newVal)
+      }
+    }
+  },
+  methods: {
+    // 鍒囨崲鍒颁笂7澶�
+    prevWeek() {
+      this.currentStartDate = this.currentStartDate.clone().subtract(7, 'days')
+      this.$emit('change', this.currentStartDate)
+    },
+    // 鍒囨崲鍒颁笅7澶�
+    nextWeek() {
+      this.currentStartDate = this.currentStartDate.clone().add(7, 'days')
+      this.$emit('change', this.currentStartDate)
+    },
+    // 璺宠浆鍒颁粖澶�
+    goToToday() {
+      this.currentStartDate = moment()
+      this.selectedDate = moment()
+      this.$emit('change', this.currentStartDate)
+      this.$emit('select', this.selectedDate)
+    },
+    // 閫夋嫨鏃ユ湡
+    selectDay(day) {
+      this.selectedDate = day.clone()
+      this.$emit('select', day)
+    },
+    // 鍒ゆ柇鏄惁鏄粖澶�
+    isToday(day) {
+      return day.isSame(moment(), 'day')
+    },
+    // 鍒ゆ柇鏄惁鏄�変腑鐨勬棩鏈�
+    isSelected(day) {
+      return day.isSame(this.selectedDate, 'day')
+    }
+  }
+}
+</script>
+
+<style scoped>
+.week-calendar {
+  padding: 16px;
+}
+
+.calendar-header {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-bottom: 16px;
+}
+
+.current-week-range {
+  margin: 0 16px;
+  font-weight: bold;
+  font-size: 14px;
+}
+
+.calendar-grid {
+  border: 1px solid #e8e8e8;
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.week-header {
+  display: flex;
+  background-color: #fafafa;
+  border-bottom: 1px solid #e8e8e8;
+}
+
+.header-cell {
+  flex: 1;
+  text-align: center;
+  padding: 8px 0;
+  border-right: 1px solid #e8e8e8;
+}
+
+.header-cell:last-child {
+  border-right: none;
+}
+
+.day-name {
+  font-size: 12px;
+  color: #666;
+  margin-bottom: 4px;
+}
+
+.day-number {
+  font-size: 16px;
+  font-weight: bold;
+  cursor: pointer;
+  width: 30px;
+  height: 30px;
+  line-height: 30px;
+  margin: 0 auto;
+  border-radius: 50%;
+}
+
+.day-number.today {
+  background-color: #1890ff;
+  color: white;
+}
+
+.day-number.selected {
+  background-color: #bae7ff;
+  color: #1890ff;
+}
+
+.calendar-body {
+  display: flex;
+  height: 300px;
+}
+
+.day-cell {
+  flex: 1;
+  border-right: 1px solid #e8e8e8;
+  cursor: pointer;
+  padding: 4px;
+}
+
+.day-cell:last-child {
+  border-right: none;
+}
+
+.day-cell.today {
+  background-color: #e6f7ff;
+}
+
+.day-cell.selected {
+  background-color: #bae7ff;
+}
+
+.cell-content {
+  height: 100%;
+  overflow: hidden;
+}
+
+.default-content {
+  height: 100%;
+}
+</style>
diff --git a/src/views/mes/modules/MesProductionWorkOrderForm.vue b/src/views/mes/modules/MesProductionWorkOrderForm.vue
index 76de965..ce6941f 100644
--- a/src/views/mes/modules/MesProductionWorkOrderForm.vue
+++ b/src/views/mes/modules/MesProductionWorkOrderForm.vue
@@ -24,28 +24,28 @@
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
-            <a-form-model-item label="浜х嚎ID(鍐椾綑)" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="factoryId">
-              <a-input v-model="model.factoryId" placeholder="璇疯緭鍏ヤ骇绾縄D(鍐椾綑)"  ></a-input>
+            <a-form-model-item label="浜х嚎" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="factoryId">
+              <a-input v-model="model.factoryId_dictText" placeholder="璇疯緭鍏ヤ骇绾縄D(鍐椾綑)"  ></a-input>
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
-            <a-form-model-item label="鐝粍ID" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="groupId">
-              <a-input v-model="model.groupId" placeholder="璇疯緭鍏ョ彮缁処D"  ></a-input>
+            <a-form-model-item label="鐝粍" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="groupId">
+              <a-input v-model="model.groupId_dictText" placeholder="璇疯緭鍏ョ彮缁処D"  ></a-input>
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
-            <a-form-model-item label="鐝ID(鍐椾綑)" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="shiftId">
-              <a-input v-model="model.shiftId" placeholder="璇疯緭鍏ョ彮娆D(鍐椾綑)"  ></a-input>
+            <a-form-model-item label="鐝" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="shiftId">
+              <a-input v-model="model.shiftId_dictText" placeholder="璇疯緭鍏ョ彮娆D(鍐椾綑)"  ></a-input>
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
             <a-form-model-item label="鎺掍骇鏃ユ湡" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="workOrderDate">
-              <j-date placeholder="璇烽�夋嫨鎺掍骇鏃ユ湡"  v-model="model.workOrderDate" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
+              <j-date placeholder="璇烽�夋嫨鎺掍骇鏃ユ湡"  v-model="model.workOrderDate" :show-time="true" date-format="YYYY-MM-DD" style="width: 100%" />
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
             <a-form-model-item label="宸ュ崟鐘舵��" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="workOrderStatus">
-              <j-dict-select-tag type="list" v-model="model.workOrderStatus" dictCode="work_order_status" placeholder="璇烽�夋嫨宸ュ崟鐘舵��" />
+              <j-dict-select-tag type="list" v-model="model.workOrderStatus_dictText" dictCode="work_order_status" placeholder="璇烽�夋嫨宸ュ崟鐘舵��" />
             </a-form-model-item>
           </a-col>
           <a-col :span="12">
@@ -102,7 +102,7 @@
          },
         labelCol: {
           xs: { span: 24 },
-          sm: { span: 5 },
+          sm: { span: 6 },
         },
         wrapperCol: {
           xs: { span: 24 },
diff --git a/src/views/mes/modules/MesProductionWorkOrderListModal.vue b/src/views/mes/modules/MesProductionWorkOrderListModal.vue
new file mode 100644
index 0000000..6075145
--- /dev/null
+++ b/src/views/mes/modules/MesProductionWorkOrderListModal.vue
@@ -0,0 +1,375 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    @ok="handleOk"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    @cancel="handleCancel"
+    cancelText="鍏抽棴">
+
+    <a-button :style="{ marginBottom: '10px' }" type="primary" @click="handleAdd">鏂板</a-button>
+    <vxe-table
+      ref="table"
+      border
+      :data="dataSource"
+      :edit-config="{trigger: 'click', mode: 'cell'}"
+      :edit-rules="editRules"
+    >
+      <vxe-table-column type="seq" width="40"/>
+      <vxe-table-column width="200" title="宸ュ崟鍙�" field="workOrderCode">
+        <template #default="{ row }">
+          <span v-if="row.workOrderCode">{{ row.workOrderCode }}</span>
+          <span v-else class="placeholder-text">绯荤粺鑷姩鐢熸垚</span>
+        </template>
+      </vxe-table-column>
+      <vxe-table-column
+        title="鐗╂枡缂栧彿"
+        field="materialNumber"
+        :edit-render="{name: '$select', options: materialOptions, events: {change: handleMaterialChange}}">
+        <template #default="{ row }">
+          <span v-if="row.materialNumber">{{ row.materialNumber }}</span>
+          <span v-else class="placeholder-text">璇烽�夋嫨鐗╂枡缂栧彿</span>
+        </template>
+      </vxe-table-column>
+      <vxe-table-column title="鐗╂枡鍚嶇О" field="materialName">
+        <template #default="{ row }">
+          <span v-if="row.materialName">{{ row.materialName }}</span>
+          <span v-else class="placeholder-text">鐗╂枡鍚嶇О鑷姩濉厖</span>
+        </template>
+      </vxe-table-column>
+      <vxe-table-column title="浜х嚎" field="factoryName"></vxe-table-column>
+      <vxe-table-column
+        title="鐝粍"
+        field="groupId"
+        :edit-render="{name: '$select', options: groupOptions, events: {change: handleGroupChange}}">
+      </vxe-table-column>
+      <vxe-table-column title="鐝id" :visible="false" field="shiftName"></vxe-table-column>
+      <vxe-table-column title="鐝" field="shiftName"></vxe-table-column>
+      <vxe-table-column
+        title="鎺掍骇鏃ユ湡"
+        field="workOrderDate"
+        :edit-render="{name: '$select', options: workOrderDateOptions, events: {change: handleWorkOrderDateChange}}">
+      </vxe-table-column>
+      <vxe-table-column
+        title="璁″垝鐢熶骇鏁伴噺"
+        field="planQuantity"
+        width="150"
+        :edit-render="{name: '$input'}">
+        <template #default="{ row }">
+          <span v-if="row.planQuantity">{{ row.planQuantity }}</span>
+          <span v-else class="placeholder-text">璇峰~鍐欒鍒掔敓浜ф暟閲�</span>
+        </template>
+      </vxe-table-column>
+      <vxe-table-column title="鎿嶄綔">
+        <template #default="{ row }">
+          <vxe-button size="small" class="error-button" @click="handleRemove(row)">鍒犻櫎</vxe-button>
+        </template>
+      </vxe-table-column>
+    </vxe-table>
+  </j-modal>
+</template>
+
+<script>
+
+import MesProductionWorkOrderForm from './MesProductionWorkOrderForm'
+import { ajaxGetDictItems } from '@api/api'
+import { getAction, postAction } from '@api/manage'
+
+export default {
+    name: 'MesProductionWorkOrderModal',
+    components: {
+      MesProductionWorkOrderForm
+    },
+    data () {
+      return {
+        title: '鎺掍骇鏄庣粏',
+        width: 1300,
+        visible: false,
+        disableSubmit: false,
+        loading: false,
+        dataSource: [],
+        groupOptions: [],
+        groupShiftMap: {},
+        materialOptions: [],
+        materNumberNameMap: {},
+        workOrderDateOptions: [],
+        url: {
+          queryShiftGroupByFactoryId: '/base/shiftGroup/queryShiftGroupByFactoryId',
+          addSchedulePlan: '/mesproductionworkorder/mesProductionWorkOrder/addSchedulePlan'
+        },
+        editRules: {
+          materialNumber: [
+            { required: true, message: '鐗╂枡缂栧彿蹇呴』閫夋嫨' }
+          ],
+          groupId: [
+            { required: true, message: '鐝粍蹇呴』閫夋嫨' }
+          ],
+          workOrderDate: [
+            { required: true, message: '鎺掍骇鏃ユ湡蹇呴』閫夋嫨' }
+          ],
+          planQuantity: [
+            { required: true, message: '璁″垝鐢熶骇鏁伴噺涓哄繀濉�' }
+          ]
+        }
+      }
+    },
+    methods: {
+      // 鐢熸垚鏃ユ湡鑼冨洿鏁扮粍
+      generateDateRangeOptions(startDate, endDate) {
+        const dateOptions = [];
+        const start = new Date(startDate);
+        const end = new Date(endDate);
+
+        // 璁剧疆鏃堕棿涓烘瘡澶╃殑0鐐�
+        start.setHours(0, 0, 0, 0);
+        end.setHours(0, 0, 0, 0);
+
+        // 鐢熸垚鏃ユ湡鑼冨洿鍐呯殑鎵�鏈夋棩鏈�
+        for (let date = new Date(start); date <= end; date.setDate(date.getDate() + 1)) {
+          const formattedDate = this.formatDate(date);
+          dateOptions.push({
+            value: formattedDate,
+            label: formattedDate
+          });
+        }
+        return dateOptions;
+      },
+      // 鏍煎紡鍖栨棩鏈熶负 YYYY-MM-DD
+      formatDate(date) {
+        const year = date.getFullYear();
+        const month = String(date.getMonth() + 1).padStart(2, '0');
+        const day = String(date.getDate()).padStart(2, '0');
+        return `${year}-${month}-${day}`;
+      },
+      // 鐢熸垚宸ュ崟鍙风殑鏂规硶
+      generateWorkOrderCode(row) {
+        console.log('row:', row)
+        // 鑾峰彇鍚勪釜瀛楁鐨勫��
+        const factoryCode = row.factoryCode || '';      // 浜х嚎缂栧彿
+        const materialNumber = row.materialNumber || ''; // 鐗╂枡缂栧彿
+        const workDate = row.workOrderDate || '';       // 鎺掍骇鏃ユ湡
+        const shiftCode = row.shiftCode || '';            // 鐝缂栧彿
+
+        // 鏍煎紡鍖栨帓浜ф棩鏈燂紙濡傛灉闇�瑕佺壒瀹氭牸寮忥紝姣斿鍙彇骞存湀鏃ワ級
+        let formattedDate = workDate;
+        if (workDate && workDate.length >= 10) {
+          // 濡傛灉鏄畬鏁存棩鏈熸牸寮忥紝鎻愬彇 YYYY-MM-DD 閮ㄥ垎
+          formattedDate = workDate.substring(0, 10).replace(/-/g, '');
+        }
+        // 鎷兼帴宸ュ崟鍙�
+        return `${factoryCode}${materialNumber}${formattedDate}${shiftCode}`;
+      },
+      // 鍦ㄩ�傚綋鏃舵満鏇存柊宸ュ崟鍙�
+      updateWorkOrderCode(row) {
+        row.workOrderCode = this.generateWorkOrderCode(row);
+      },
+      handleWorkOrderDateChange($event, value) {
+        $event.row.workOrderDate = value.value;
+        this.updateWorkOrderCode($event.row)
+      },
+      handleMaterialChange($event, value) {
+        const key = value.value
+        if (key && this.materNumberNameMap[key]) {
+          $event.row.materialName = this.materNumberNameMap[key]
+        } else {
+          $event.row.materialName = '';
+        }
+        // 鏇存柊鐗╂枡缂栧彿
+        $event.row.materialNumber = key;
+        // 閲嶆柊鐢熸垚宸ュ崟鍙�
+        this.updateWorkOrderCode($event.row);
+      },
+      handleGroupChange($event, value) {
+        const key = value.value
+        // 浠� groupShiftMap 涓幏鍙栧搴旂殑鐝淇℃伅
+        if (key && this.groupShiftMap[key]) {
+          // 鏇存柊褰撳墠琛岀殑鐝瀛楁
+          $event.row.shiftId = this.groupShiftMap[key].shiftId;
+          $event.row.shiftCode = this.groupShiftMap[key].shiftCode;
+          $event.row.shiftName = this.groupShiftMap[key].shiftName;
+        } else {
+          // 濡傛灉娌℃湁鍖归厤鐨勭彮娆′俊鎭紝鍒欐竻绌虹彮娆″瓧娈�
+          $event.row.shiftId = '';
+          $event.row.shiftCode = '';
+          $event.row.shiftName = '';
+        }
+        // 閲嶆柊鐢熸垚宸ュ崟鍙�
+        this.updateWorkOrderCode($event.row);
+      },
+      initDictSelectOptions(record) {
+        return new Promise((resolve) => {
+          // 骞惰鎵ц澶氫釜寮傛璇锋眰
+          const promises = [];
+
+          // 鑾峰彇鐝粍鍜岀彮娆′俊鎭�
+          if (record && record.length > 0) {
+            const factoryId = record[0].factoryId
+            const shiftGroupPromise = getAction(this.url.queryShiftGroupByFactoryId, { factoryId: factoryId }).then(res => {
+              if (res.success) {
+                // 淇鏄犲皠閫昏緫
+                this.groupOptions = res.result.map(item => {
+                  return {
+                    value: item.id,
+                    label: item.groupName
+                  }
+                })
+                // 淇濆瓨鐝粍鍜岀彮娆$殑鏄犲皠鍏崇郴
+                this.groupShiftMap = res.result.reduce((map, item) => {
+                  map[item.id] = {
+                    shiftId: item.shiftId,
+                    shiftCode: item.shiftCode_dictText,
+                    shiftName: item.shiftId_dictText
+                  }
+                  return map
+                }, {})
+              }
+            }).catch(() => {
+              // 鍗充娇璇锋眰澶辫触涔熶笉闃诲
+            });
+            promises.push(shiftGroupPromise);
+          }
+
+          //鑾峰彇鐗╂枡缂栧彿涓嬫媺閫夐」
+          const materialNumberPromise = ajaxGetDictItems("lsw_material,material_name,material_number,del_flag!='1' order by material_number asc", null).then(res => {
+            if (res.success) {
+              // 鍋囪鐗╂枡缂栧彿瀛楁涓� materialNumber锛岄渶瑕佹牴鎹疄闄呭瓧娈佃皟鏁�
+              // 灏嗙墿鏂欓�夐」瀛樺偍鍒扮粍浠舵暟鎹腑锛屼緵琛ㄦ牸浣跨敤
+              this.materialOptions = res.result.map(item => {
+                return {
+                  value: item.value,
+                  label: item.value
+                }
+              });
+              this.materNumberNameMap = res.result.reduce((map, item) => {
+                map[item.value] = item.text
+                return map
+              }, {})
+            }
+          }).catch(() => {
+            // 鍗充娇璇锋眰澶辫触涔熶笉闃诲
+          });
+          promises.push(materialNumberPromise);
+
+          // 绛夊緟鎵�鏈夎姹傚畬鎴�
+          Promise.all(promises).then(() => {
+            resolve();
+          });
+        })
+      },
+      edit (record, dateRange) {
+        // 鍏堝姞杞藉瓧鍏告暟鎹紝鍐嶅垵濮嬪寲琛ㄥ崟
+        this.initDictSelectOptions(record).then(() => {
+          this.$nextTick(() => {
+            // 鏍规嵁鏃ユ湡鑼冨洿鐢熸垚鎺掍骇鏃ユ湡閫夐」
+            if (dateRange && dateRange.length === 2) {
+              this.workOrderDateOptions = this.generateDateRangeOptions(dateRange[0], dateRange[1]);
+            }
+
+            // 涓烘瘡鏉¤褰曠敓鎴愬伐鍗曞彿
+            if (record && record.length > 0) {
+              record.forEach(row => {
+                if (!row.workOrderCode) {
+                  this.updateWorkOrderCode(row);
+                }
+              });
+            }
+            this.dataSource = record
+            this.visible = true
+            // 鏁版嵁鍔犺浇瀹屾垚鍚庢縺娲绘墍鏈夎鐨勭紪杈戠姸鎬�
+            this.$nextTick(() => {
+              if (this.$refs.table && this.dataSource.length > 0) {
+                // 婵�娲荤涓�琛岃繘鍏ョ紪杈戠姸鎬�
+                this.$refs.table.setActiveRow(this.dataSource[0])
+              }
+            })
+          });
+        })
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleAdd() {
+        // 鍒涘缓鏂拌鏁版嵁
+        const newRow = {
+          workOrderCode: this.dataSource.length > 0 ? this.dataSource[0].factoryCode : '',
+          materialNumber: '',       // 鐗╂枡缂栧彿锛堥渶閫夋嫨锛�
+          materialName: '',         // 鐗╂枡鍚嶇О锛堣嚜鍔ㄥ~鍏咃級
+          factoryId: this.dataSource.length > 0 ? this.dataSource[0].factoryId : '',
+          factoryCode: this.dataSource.length > 0 ? this.dataSource[0].factoryCode : '',
+          factoryName: this.dataSource.length > 0 ? this.dataSource[0].factoryName : '',
+          groupId: '',              // 鐝粍锛堥渶閫夋嫨锛�
+          shiftId: '',              // 鐝ID
+          shiftCode: '',            // 鐝缂栧彿
+          shiftName: '',            // 鐝鍚嶇О
+          workOrderDate: '',        // 鎺掍骇鏃ユ湡锛堥渶閫夋嫨锛�
+          planQuantity: ''          // 璁″垝鐢熶骇鏁伴噺锛堥渶濉啓锛�
+        }
+        // 灏嗘柊琛屾坊鍔犲埌鏁版嵁婧愪腑
+        this.dataSource.push(newRow);
+        // 婵�娲绘柊澧炵殑琛岃繘鍏ョ紪杈戠姸鎬�
+        this.$nextTick(() => {
+          if (this.$refs.table) {
+            this.$refs.table.setActiveRow(newRow);
+          }
+        });
+      },
+      handleRemove(row) {
+        let table = this.$refs.table
+        this.$confirm({
+          title: '鎻愮ず',
+          content: '纭瑕佸垹闄ゅ悧锛�',
+          okText: '纭畾',
+          cancelText: '鍙栨秷',
+          onOk: () => {
+            // 鍒犻櫎琛�
+            table.remove(row)
+          }
+        })
+      },
+      handleOk () {
+        // 琛ㄦ牸鍏ㄨ〃鏍¢獙
+        this.$refs.table.validate((valid) => {
+          if (valid) {
+            this.$message.error("璇峰畬鎴愭墍鏈夊繀濉俊鎭悗鍐嶆彁浜わ紒")
+          } else {
+            let tableData = this.$refs.table.getTableData().fullData
+            console.log(tableData)
+            postAction(this.url.addSchedulePlan, tableData).then(res=> {
+              if (res.success) {
+                this.$message.success(res.message)
+                this.submitCallback()
+              } else {
+                this.$message.warning(res.message)
+              }
+            })
+          }
+        })
+      },
+      submitCallback(){
+        this.$emit('ok');
+        this.visible = false;
+      },
+      handleCancel () {
+        this.close()
+      }
+    }
+  }
+</script>
+
+<style scoped>
+
+.placeholder-text {
+  color: #999;
+  font-style: italic;
+}
+
+.error-button {
+  background-color: #ff4d4f !important;
+  border-color: #ff4d4f !important;
+  color: #fff !important;
+}
+
+</style>
\ No newline at end of file
diff --git a/src/views/mes/modules/MesProductionWorkOrderModal.vue b/src/views/mes/modules/MesProductionWorkOrderModal.vue
index 33c60fc..012dcdf 100644
--- a/src/views/mes/modules/MesProductionWorkOrderModal.vue
+++ b/src/views/mes/modules/MesProductionWorkOrderModal.vue
@@ -23,7 +23,7 @@
     data () {
       return {
         title:'',
-        width:896,
+        width:900,
         visible: false,
         disableSubmit: false
       }
diff --git a/src/views/mes/modules/MesProductionWorkOrderRepublishModal.vue b/src/views/mes/modules/MesProductionWorkOrderRepublishModal.vue
new file mode 100644
index 0000000..bf3160d
--- /dev/null
+++ b/src/views/mes/modules/MesProductionWorkOrderRepublishModal.vue
@@ -0,0 +1,132 @@
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    @ok="handleOk"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    @cancel="handleCancel"
+    cancelText="鍏抽棴">
+
+    <a-spin :spinning="confirmLoading">
+      <j-form-container :disabled="formDisabled">
+        <a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
+          <a-row>
+            <a-col :span="24">
+              <a-form-model-item label="璁″垝鐢熶骇鏁伴噺" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="planQuantity">
+                <a-input-number
+                  v-model="model.planQuantity"
+                  placeholder="璇疯緭鍏ヨ鍒掔敓浜ф暟閲�"
+                  style="width: 100%"
+                  :min="0">
+                </a-input-number>
+              </a-form-model-item>
+            </a-col>
+            <a-col :span="24">
+              <a-form-model-item label="閲嶅彂甯冨師鍥�" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="republishReason">
+                <a-textarea
+                  v-model="model.republishReason"
+                  placeholder="璇峰~鍐欓噸鍙戝竷鍘熷洜"
+                  :rows="4">
+                </a-textarea>
+              </a-form-model-item>
+            </a-col>
+          </a-row>
+        </a-form-model>
+      </j-form-container>
+    </a-spin>
+  </j-modal>
+</template>
+
+<script>
+import { postAction } from '@api/manage'
+
+export default {
+  name: 'MesProductionWorkOrderRepublishModal',
+  data () {
+    return {
+      title: '閲嶅彂甯冨伐鍗�',
+      width: 600,
+      visible: false,
+      disableSubmit: false,
+      confirmLoading: false,
+      model: {
+        id: '',
+        planQuantity: null,
+        republishReason: ''
+      },
+      validatorRules: {
+        planQuantity: [
+          { required: true, message: '璇疯緭鍏ヨ鍒掔敓浜ф暟閲�!' }
+        ],
+        republishReason: [
+          { required: true, message: '璇峰~鍐欓噸鍙戝竷鍘熷洜!' }
+        ]
+      },
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 },
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 },
+      },
+      url: {
+        republish: '/mesproductionworkorder/mesProductionWorkOrder/republish'
+      }
+    }
+  },
+  computed: {
+    formDisabled(){
+      return this.disabled
+    },
+  },
+  methods: {
+    add (record) {
+      // 閲嶇疆琛ㄥ崟
+      this.$refs.form && this.$refs.form.resetFields()
+      // 璁剧疆鍒濆鍊�
+      if (record) {
+        this.model.id = record.id
+        this.model.planQuantity = record.planQuantity
+        this.model.republishReason = ''
+      }
+      this.visible = true
+    },
+    close () {
+      this.$emit('close');
+      this.visible = false;
+    },
+    handleOk () {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.confirmLoading = true
+          let formData = {
+            id: this.model.id,
+            planQuantity: this.model.planQuantity,
+            republishReason: this.model.republishReason
+          }
+          postAction(this.url.republish, formData).then(res => {
+            if (res.success) {
+              this.$message.success(res.message)
+              this.submitCallback()
+            } else {
+              this.$message.warning(res.message)
+            }
+          }).finally(() => {
+            this.confirmLoading = false
+          })
+        }
+      })
+    },
+    submitCallback(){
+      this.$emit('ok');
+      this.visible = false;
+    },
+    handleCancel () {
+      this.close()
+    }
+  }
+}
+</script>

--
Gitblit v1.9.3