src/views/mes/MesProductionWorkOrderList.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/mes/modules/MesProductionWeekCalendar.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/mes/modules/MesProductionWorkOrderForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/mes/modules/MesProductionWorkOrderListModal.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/mes/modules/MesProductionWorkOrderModal.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/mes/modules/MesProductionWorkOrderRepublishModal.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/views/mes/MesProductionWorkOrderList.vue
@@ -1,33 +1,34 @@ <template> <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 :xl="6" :lg="7" :md="8" :sm="24"> <a-form-item label="å·¥åå·(ä»»å¡å·)"> <j-input placeholder="请è¾å ¥å·¥åå·(ä»»å¡å·)" v-model="queryParam.workOrderCode"></j-input> <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 :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-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> @@ -37,14 +38,20 @@ <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-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-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>项 <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> @@ -67,7 +74,8 @@ </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;"/> <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> @@ -83,10 +91,18 @@ </template> <span slot="action" slot-scope="text, record"> <a @click="handleEdit(record)">ç¼è¾</a> <span v-if="record.workOrderStatus === 'NEW'"> <a-popconfirm title="ç¡®å®åå¸å?" @confirm="() => handlePublish(record.id)"> <a>åå¸</a> </a-popconfirm> <a-divider type="vertical" /> <a-dropdown> </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> @@ -100,12 +116,46 @@ </a-menu> </a-dropdown> </span> <span v-if="record.workOrderStatus !== 'NEW'"> <a @click="handleDetail(record)">详æ </a> </span> </span> </a-table> </div> <mes-production-work-order-modal ref="modalForm" @ok="modalFormOk"></mes-production-work-order-modal> <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> @@ -114,13 +164,21 @@ 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 MesProductionWorkOrderModal, MesProductionWeekCalendar, MesProductionWorkOrderListModal, MesProductionWorkOrderRepublishModal }, data () { return { @@ -132,115 +190,220 @@ dataIndex: '', key:'rowIndex', width:60, align:"center", align: 'center', customRender:function (t,r,index) { return parseInt(index)+1; return parseInt(index) + 1 } }, { title:'å·¥åå·(ä»»å¡å·)', align:"center", align: 'center', dataIndex: 'workOrderCode' }, { title:'ç©æç¼ç ', align:"center", align: 'center', dataIndex: 'materialNumber' }, { title:'ç©æåç§°', align:"center", align: 'center', dataIndex: 'materialName' }, { title:'计åç产æ°é', align:"center", align: 'center', dataIndex: 'planQuantity' }, { title:'产线(åä½)', align:"center", title: '产线', align: 'center', dataIndex: 'factoryId_dictText' }, { title:'çç»', align:"center", align: 'center', dataIndex: 'groupId_dictText' }, { title:'çæ¬¡(åä½)', align:"center", title: 'çæ¬¡', align: 'center', dataIndex: 'shiftId_dictText' }, { title:'æäº§æ¥æ', align:"center", align: 'center', dataIndex: 'workOrderDate' }, { title:'å·¥åç¶æ', align:"center", align: 'center', dataIndex: 'workOrderStatus_dictText' }, { title:'å®é æ¥å·¥æ°é', align:"center", align: 'center', dataIndex: 'actualQuantity' }, { title:'åå¸äºº', align:"center", align: 'center', dataIndex: 'publisher' }, { title:'å叿¶é´', align:"center", align: 'center', dataIndex: 'publishTime' }, { title:'éåå¸äºº', align:"center", align: 'center', dataIndex: 'republisher' }, { title:'éå叿¶é´', align:"center", align: 'center', dataIndex: 'republishTime' }, { title: 'æä½', dataIndex: 'action', align:"center", fixed:"right", 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", 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.getSuperFieldList() this.initDictConfig() }, computed: { importExcelUrl: function(){ return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`; }, 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("请设置url.list屿§!") reject(new Error("请设置url.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=[]; 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:''}) @@ -257,10 +420,147 @@ 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 } }, 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'; .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> 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å¹´MæDæ¥')} - ${end.format('Dæ¥')}` } else { return `${start.format('YYYYå¹´MæDæ¥')} - ${end.format('MæDæ¥')}` } } }, 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> 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="请è¾å ¥äº§çº¿ID(åä½)" ></a-input> <a-form-model-item label="产线" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="factoryId"> <a-input v-model="model.factoryId_dictText" placeholder="请è¾å ¥äº§çº¿ID(åä½)" ></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="请è¾å ¥çç»ID" ></a-input> <a-form-model-item label="çç»" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="groupId"> <a-input v-model="model.groupId_dictText" placeholder="请è¾å ¥çç»ID" ></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="请è¾å ¥ç次ID(åä½)" ></a-input> <a-form-model-item label="çæ¬¡" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="shiftId"> <a-input v-model="model.shiftId_dictText" placeholder="请è¾å ¥ç次ID(åä½)" ></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 }, 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> src/views/mes/modules/MesProductionWorkOrderModal.vue
@@ -23,7 +23,7 @@ data () { return { title:'', width:896, width:900, visible: false, disableSubmit: false } 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>