zouyu
2023-11-30 272dcaff7a22312fe261945621682ceeca8ed02f
	new file:   src/api/plan/productionschedul.js
modified: src/views/common/ztt-table.vue
modified: src/views/plan/customerorder/index.vue
modified: src/views/plan/manufacturingorder/index.vue
new file: src/views/plan/productionschedul/index.vue
new file: src/views/plan/productionschedul/template-form.vue
已修改3个文件
已添加3个文件
627 ■■■■■ 文件已修改
src/api/plan/productionschedul.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/common/ztt-table.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/plan/customerorder/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/plan/manufacturingorder/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/plan/productionschedul/index.vue 424 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/plan/productionschedul/template-form.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/plan/productionschedul.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
import request from '@/router/axios'
export function fetchScheduleList(query) {
  return request({
    url: '/mes/productionSchedul/page',
    method: 'get',
    params: query
  })
}
export function fetchScheduleById(id) {
  return request({
    url: '/mes//productionSchedul/'+id,
    method: 'get',
  })
}
src/views/common/ztt-table.vue
@@ -149,11 +149,7 @@
        v-bind="$attrs"
        v-on="$listeners"
        :highlight-current-row="true"
        :row-key="
          (row) => {
            return row.id
          }
        "
        :row-key="rowKey"
        @row-dblclick="dbClickRow"
        @row-contextmenu="contextMenu"
        @header-click="headClick"
@@ -563,6 +559,12 @@
  name: 'TTable',
  components: { exSlot, advancedSearchDialog, zttdraggable },
  props: {
    rowKey: {
      type: String,
      default: ()=>{
        return 'id'
      }
    },
    // è¡¨æ ¼åž‹å·ï¼šmini,medium,small
    tableSize: { type: String, default: 'small' },
    // æ•°æ®è¯·æ±‚方法
src/views/plan/customerorder/index.vue
@@ -93,7 +93,6 @@
          > -->
        </template>
      </ttable>
      <!-- å¼¹çª—, æ—¥æœŸé€‰æ‹© -->
      <ConfirmPullCustomerorder
        v-if="showPullCustomerOrderVisible"
src/views/plan/manufacturingorder/index.vue
@@ -1123,6 +1123,7 @@
                getByMoIds([this.orderPlan.id]).then((repsonse) => {
                  const resData = repsonse.data.data
                  const resCode = repsonse.data.code
                  console.log("resData-----",repsonse);
                  if (resCode === 0) {
                    const _that = this
                    for (const key in resData) {
src/views/plan/productionschedul/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,424 @@
<template>
  <div class="mod-config">
    <basic-container>
      <el-row>
        <el-col :span="12">
          <div style="height:80vh;">
            <avue-crud :data="tableData" ref="crud" :option="option" :span-method="spanMethod"
            @refresh-change="getData"
            :page="page"
            @selection-change="selectionRow"
            :table-loading="loading">
            <template #menu="{ row, index }">
              <el-button type="text" icon="el-icon-delete" size="small" @click="deleteHandle(row, index)">删除</el-button>
            </template>
          </avue-crud>
          </div>
        </el-col>
        <el-col :span="12" style="padding-left: 10px">
          <div style="">
            <el-card>
              <div slot="header" class="clearfix">
                <span>调度时间线</span>
                <el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>
              </div>
              <div style="height:70vh;overflow-y: scroll;">
                <el-timeline reverse>
                    <el-timeline-item
                      placement="top"
                      v-for="(item, index) in scheduleList"
                      :key="index"
                      :timestamp="item.planTime">
                        <el-card style="width:95%;margin: 0;padding: 0px 0px;">
                          <p style="font-weight: bold;">{{item.title}}</p>
                          <p>实际时间: {{ item.actualTime }}</p>
                        </el-card>
                    </el-timeline-item>
                </el-timeline>
            </div>
            </el-card>
          </div>
        </el-col>
      </el-row>
    </basic-container>
  </div>
</template>
<script>
import {
  fetchScheduleList,
  fetchScheduleById,
} from '@/api//plan/productionschedul'
import TableForm from './template-form'
import ttable from '@/views/common/ztt-table.vue'
import { mapGetters } from 'vuex'
export default {
    data() {
    return {
      scheduleList: [],
      typeOptions: [],
      multipleSelection: [],
      loading: true,
      tableData: [],
      page: {
        total: 10,
        currentPage: 1,
        pageSize: 10
      },
      option: {
        height: 'auto',
        selection: true,
        columnBtn: false,
        index: true,
        rowKey: 'product',
        indexLabel: '序号',
        menuAlign: 'center',
        menuWidth: 100,
        editBtn: false,
        delBtn: false,
        addBtn: false,
        border: true,
        align: 'center',
        column: [
          {
            minWidth: 120,
            prop: 'projectName',
            label: '项目名称',
            overHidden: true,
          },
          {
            minWidth: 100,
            prop: 'contractNo',
            label: '合同号',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'orderTime',
            label: '接单日期',
            overHidden: true,
            formatter: (row,columnValue)=> this.formatDate(row,columnValue)
          },
          {
            minWidth: 120,
            prop: 'customerName',
            label: '客户名称',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'deliveryDate',
            label: '交货日期',
            overHidden: true,
            formatter: (row,columnValue)=> this.formatDate(row,columnValue)
          },
          {
            minWidth: 120,
            prop: 'productType',
            label: '产品类型',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'product',
            label: '产品名',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'specs',
            label: '规格型号',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'unit',
            label: '单位',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'number',
            label: '数量',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'productionStatus',
            label: '生产情况',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'productionRoutine',
            label: '生产程度',
            overHidden: true,
          },
          {
            minWidth: 120,
            prop: 'projectLeader',
            label: '项目负责人',
            overHidden: true,
          },
          {
            minWidth: 150,
            prop: 'remark',
            label: '备注',
            overHidden: true,
          }
        ],
      },
      spanArr: [{
        prop: 'projectName',
        span: []
      }, {
        prop: 'contractNo',
        span: []
      },
      {
        prop: 'orderTime',
        span: []
      },
      {
        prop: 'customerName',
        span: []
      },
      {
        prop: 'deliveryDate',
        span: []
      },
      {
        prop: 'productType',
        span: []
      },
    ],
    }
  },
  components: {
    ttable,
    TableForm,
  },
  computed: {
    ...mapGetters(['permissions'])
  },
  created(){
    this.loading = true
    this.getData()
    this.getParamType()
    this.rowSort()
    this.rowCalc()
  },
  beforeUpdate() {
    this.rowSort()
    this.rowCalc()
  },
  watch:{
  },
  mounted() {
  },
  beforeDestroy() {
  },
  methods: {
    initTimeLine(data){
      this.scheduleList = []
      if(data){
        let arr = [
          {
            title: '文件签发',
            actualTime: data.documentActualTime,
            planTime: data.documentPlanTime,
          },
          {
            title: '下达物料需求',
            actualTime: data.bomActualTime,
            planTime: data.bomPlanTime,
          },
          {
            title: '采购询价+合同签订',
            actualTime: data.contractActualTime,
            planTime: data.contractPlanTime,
          },
          {
            title: '物料采购到货',
            actualTime: data.arrivalActualTime,
            planTime: data.arrivalPlanTime,
          },
          {
            title: '物料到货检验',
            actualTime: data.checkActualTime,
            planTime: data.checkPlanTime,
          },
          {
            title: '领料、装箱入库',
            actualTime: data.productActualTime,
            planTime: data.productPlanTime,
          },
        ]
        this.scheduleList = arr
      }
    },
    getScheduleById(id){
      if(id){
        fetchScheduleById(id).then(res=>{
          this.initTimeLine(res.data.data)
        }).catch(error=>{
          console.log(error);
        })
      }
    },
    selectionRow(val){
      if (val.length > 1) {
         const preVal = val.shift();
         this.$refs.crud.toggleRowSelection(preVal, false);
       }
       this.getScheduleById(val[0].id)
    },
    formatDate(row, cellValue){
      if (cellValue) {
        const dutyDateList = /\d{4}-\d{1,2}-\d{1,2}/g.exec(cellValue)
        if (dutyDateList && dutyDateList.length > 0) {
          return dutyDateList[0]
        }
      }
      return ''
    },
    // èŽ·å–æ•°æ®åˆ—è¡¨
    getData() {
      this.loading = true
      let param = {
        size: 20,
        current: 1,
      }
      fetchScheduleList(param).then((res) => {
        this.tableData = res.data.data.records
        this.page.total = res.data.data.total
        this.page.currentPage = res.data.data.records.pages
      })
      this.loading = false
    },
    handleCurrentChange(val) {
      this.multipleSelection = val
    },
    // åˆ é™¤
    deleteHandle(row,index) {
      this.$confirm('是否确认删除', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(function() {
      })
    },
    //动态合并方法
    rowCalc() {
      this.spanArr.forEach((ele, index) => {
        let parent
        if (index !== 0) parent = this.spanArr[ele.parent || index - 1].span
        ele.span = this.rowSpan(ele.prop, parent)
      })
    },
    rowSort(list) {
      let propList = this.spanArr.map(ele => ele.prop)
      this.spanArr.forEach((ele, index) => {
        let key = ele.prop
        this.tableData = this.tableData.sort((a, b) => {
          let flag = true;
          for (let i = 0; i < index; i++) {
            let prop = this.spanArr[i].prop
            flag = flag && a[prop] == b[prop]
          }
          if (flag) {
            if (a[key] < b[key]) { return 1; }
            else if (a[key] > b[key]) { return -1; }
            return 0;
          }
          return 0;
        })
      })
    },
    rowSpan(key, parent) {
      let list = [];
      let position = 0;
      this.tableData.forEach((item, index) => {
        if (index === 0) {
          list.push(1)
          let position = 0;
        } else {
          if (this.tableData[index][key] === this.tableData[index - 1][key]) {
            if (parent && parent[index] !== 0) {
              list.push(1)
              position = index
            } else {
              list[position] += 1;
              list.push(0)
            }
          } else {
            list.push(1)
            position = index
          }
        }
      })
      return list
    },
    spanMethod({ row, column, rowIndex, columnIndex }) {
      for (let i = 0; i < this.spanArr.length; i++) {
        const ele = this.spanArr[i]
        if (column.property == ele.prop) {
          const _row = ele.span[rowIndex];
          const _col = _row > 0 ? 1 : 0;
          return {
            rowspan: _row,
            colspan: _col
          }
        }
      }
    }
  }
}
</script>
<style scoped>
.basic-template-table .el-table__body .el-table__row td:first-child .cell {
  padding-left: 0px;
  padding-right: 0px;
}
.basic-template-table .el-table__body .el-table__row:hover {
  cursor: move;
}
.basic-template-table .el-table__body .el-table__row:hover .icon {
  display: inline-block;
}
.basic-template-table .el-table__body .el-table__row .icon {
  color: rgba(0, 0, 0, 0.45);
  font-size: 12px;
  line-height: 18px;
  display: none;
}
.aufontAll {
  font-family: aufontAll !important;
  font-size: 14px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.h-icon-all-drag {
  background: url('/img/tz.png') center center no-repeat;
  background-size: cover;
  font-size: 14px;
}
.h-icon-all-drag:before {
  content: '\E63E';
  font-size: 14px;
  visibility: hidden;
}
.avue-main .el-card__body{
  padding: 0px 20px;
}
</style>
src/views/plan/productionschedul/template-form.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,173 @@
<template>
  <el-dialog
    v-diadrag
    :title="!dataForm.id ? '新增' : '修改'"
    :close-on-click-modal="false"
    :visible.sync="visible"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      label-width="100px"
      class="l-mes"
    >
      <el-form-item label="模板编号" prop="templateNo">
        <el-input
          v-model="dataForm.templateNo"
          placeholder="模板编号"
        ></el-input>
      </el-form-item>
      <el-form-item label="模板名称" prop="templateName">
        <el-input
          v-model="dataForm.templateName"
          placeholder="模板名称"
        ></el-input>
      </el-form-item>
      <el-form-item label="模板类型" prop="templateType">
        <el-select
          v-model="dataForm.templateType"
          placeholder="模板类型"
          filterable
          style="width: 100%"
          clearable
          @change="templateTypeChange"
        >
          <el-option
            v-for="item in templateTypeList"
            :key="item.id"
            :label="item.templateTypeName"
            :value="item.templateTypeName"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="备注" prop="remark">
        <el-input v-model="dataForm.remark" placeholder="备注"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">取消</el-button>
      <el-button
        type="primary"
        :disabled="isSubmit"
        v-thinclick="`dataFormSubmit`"
        >确定</el-button
      >
    </span>
  </el-dialog>
</template>
<script>
import { getObj, addObj, putObj, getTemplateTypes } from '@/api/basic/template'
export default {
  data() {
    return {
      templateTypeList: [],
      visible: false,
      dataForm: {
        id: 0,
        templateName: '',
        templateNo: '',
        templateType: '',
        dataType: '',
        remark: ''
      },
      dataRule: {
        templateName: [
          { required: true, message: '模板名称不能为空', trigger: 'blur' }
        ],
        templateType: [
          { required: true, message: '模板类型不能为空', trigger: 'blur' }
        ]
      },
      isSubmit: false
    }
  },
  methods: {
    init(id) {
      this.dataForm.id = id || 0
      this.visible = true
      this.$nextTick(() => {
        this.$refs.dataForm.resetFields()
        Promise.all([this.getDict(), this.getDataForm(this.dataForm.id)]).then(
          (res) => {}
        )
      })
    },
    getDataForm(id) {
      return new Promise((resolve, reject) => {
        if (id) {
          getObj(id)
            .then((response) => {
              if (response.data.code === 0) {
                this.dataForm = response.data.data
                resolve()
              } else {
                this.dataForm = {}
                reject()
              }
            })
            .catch((error) => {
              reject(error)
            })
        }
      })
    },
    getDict() {
      return new Promise((resolve, reject) => {
        getTemplateTypes()
          .then((response) => {
            if (response.data.code === 0) {
              this.templateTypeList = response.data.data
              resolve()
            } else {
              this.templateTypeList = []
              reject()
            }
          })
          .catch((error) => {
            reject(error)
          })
      })
    },
    templateTypeChange() {
      const currOperationTemplateType = this.dataForm.templateType
      const templateType = this.templateTypeList.find(
        (item) => item.templateTypeName === currOperationTemplateType
      )
      console.log(templateType)
      if (templateType != undefined) {
        this.dataForm.dataType = templateType.dataType
      } else {
        this.dataForm.dataType = ''
      }
    },
    // è¡¨å•提交
    dataFormSubmit() {
      this.isSubmit = true
      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          if (this.dataForm.id) {
            putObj(this.dataForm).then((data) => {
              this.$message.success('修改成功')
              this.visible = false
              this.isSubmit = false
              this.$emit('refreshDataList')
            })
          } else {
            addObj(this.dataForm).then((data) => {
              this.$message.success('添加成功')
              this.visible = false
              this.isSubmit = false
              this.$emit('refreshDataList')
            })
          }
        } else {
          this.isSubmit = false
        }
      })
    }
  }
}
</script>