Browse Source

生产订单

lxf 1 year ago
parent
commit
06052d178b
2 changed files with 474 additions and 0 deletions
  1. 14 0
      src/directive/preReClick.js
  2. 460 0
      src/views/production/schedule/production-order/index.vue

+ 14 - 0
src/directive/preReClick.js

@@ -0,0 +1,14 @@
+export default (app) => {
+  app.directive("preReClick", {
+    mounted(el, binding) {
+      el.addEventListener("click", () => {
+        if (!el.disabled) {
+          el.disabled = true;
+          setTimeout(() => {
+            el.disabled = false;
+          }, binding.value || 2000);
+        }
+      });
+    },
+  });
+};

+ 460 - 0
src/views/production/schedule/production-order/index.vue

@@ -0,0 +1,460 @@
+<template>
+  <div>
+    <el-card class="box-card">
+      <byTable
+        :source="sourceList.data"
+        :pagination="sourceList.pagination"
+        :config="config"
+        :loading="loading"
+        :searchConfig="searchConfig"
+        highlight-current-row
+        :table-events="{
+          select: selectRow,
+          'select-all': selectRow,
+        }"
+        :action-list="[
+          {
+            text: '标签',
+            action: () => clickTag(),
+            type: ' ',
+          },
+        ]"
+        @get-list="getList"
+        @clickReset="clickReset">
+        <template #code="{ item }">
+          <div>
+            <el-tag :type="tagList[item.tag]" size="small" style="margin-right: 4px" v-if="item.tag">
+              {{ dictKeyValue(item.tag, useUserStore().allDict["order_tag"]) }}
+            </el-tag>
+            <a style="color: #409eff; cursor: pointer; word-break: break-all" @click="clickCode(item)">{{ item.code }}</a>
+          </div>
+        </template>
+        <template #schedule="{ item }">
+          <div>生产进度</div>
+        </template>
+      </byTable>
+    </el-card>
+
+    <el-dialog title="编辑标签" v-if="openTag" v-model="openTag" width="800">
+      <el-form :model="formTagData.data" :rules="rulesTag" label-width="80px" style="margin-top: 18px" ref="tagForm">
+        <el-form-item label="标签: " prop="tag">
+          <el-radio-group v-model="formTagData.data.tag">
+            <el-radio label="0">无</el-radio>
+            <el-radio v-for="(item, index) in useUserStore().allDict['order_tag']" :key="index" :label="item.dictKey">{{ item.dictValue }}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="openTag = false" size="large">取 消</el-button>
+        <el-button type="primary" @click="submitTagForm()" size="large" v-preReClick>确 定</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="一键包装" v-if="openPacking" v-model="openPacking" width="90%">
+      <el-row :gutter="10">
+        <el-col :span="5">
+          <el-card style="height: calc(100vh - 114px); overflow-y: auto; overflow-x: hidden">
+            <div
+              style="
+                font-size: 14px;
+                font-weight: bold;
+                color: #6c88f1;
+                width: 120px;
+                border-bottom: 1px solid #6c88f1;
+                line-height: 32px;
+                margin-bottom: 18px;
+              ">
+              订单产品清单
+            </div>
+            <div v-if="formData.data.skuSpecList && formData.data.skuSpecList.length">
+              <div style="border: 1px solid #edf0f5; margin-bottom: 20px" v-for="(item, index) in formData.data.skuSpecList" :key="index">
+                <div style="background-color: #edf0f5; height: 35px; line-height: 35px; padding: 0 10px">产品</div>
+                <div style="padding: 10px 20px">
+                  <div style="padding: 5px 0">品号: {{ item.skuSpecCode }}</div>
+                  <div style="padding: 5px 0; word-break: break-all">品名: {{ item.skuSpecName }}</div>
+                  <div style="padding: 5px 0">数量: {{ item.quantity }}</div>
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="19" style="height: calc(100vh - 114px); overflow-y: auto; overflow-x: hidden">
+          <el-form :model="formData.data" :rules="rules" label-width="0" style="margin-top: 18px" ref="packingForm">
+            <div style="margin-bottom: 10px">
+              <el-button type="primary" @click="clickExpressPacking()">选择快递物流包材</el-button>
+            </div>
+            <el-table :data="formData.data.packageList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+              <el-table-column label="品号" prop="bomSpecCode" width="160" />
+              <el-table-column label="品名" prop="bomSpecName" min-width="220" />
+              <el-table-column label="成本单价" prop="costPrice" align="right" width="100" />
+              <el-table-column label="销售单价" prop="internalSellingPrice" align="right" width="100" />
+              <el-table-column label="数量" width="120">
+                <template #default="{ row, $index }">
+                  <el-form-item :prop="'packageList.' + $index + '.quantity'" :rules="rules.quantity" :inline-message="true" style="width: 100%">
+                    <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="数量" style="width: 100%" :controls="false" :min="0" />
+                  </el-form-item>
+                </template>
+              </el-table-column>
+              <el-table-column label="成本单价" align="right" width="100">
+                <template #default="{ row }">
+                  <span>{{ calculatedAmount(row, "costPrice") }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="销售单价" align="right" width="100">
+                <template #default="{ row }">
+                  <span>{{ calculatedAmount(row, "internalSellingPrice") }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" align="center" fixed="right" width="60">
+                <template #default="{ $index }">
+                  <el-button type="danger" @click="clickDeleteExpressPacking($index)" text>删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+            <div style="padding: 8px; text-align: center">
+              <el-button @click="openPacking = false" size="large">取 消</el-button>
+              <el-button type="primary" @click="submitForm()" size="large" v-preReClick>确 定</el-button>
+            </div>
+          </el-form>
+        </el-col>
+      </el-row>
+    </el-dialog>
+
+    <el-dialog title="选择快递物流包材" v-if="openExpressPacking" v-model="openExpressPacking" width="84%">
+      <SelectBOM :selectStatus="true" :expressStatus="true" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import { ElMessage } from "element-plus";
+import SelectBOM from "@/views/group/BOM/management/index";
+
+const { proxy } = getCurrentInstance();
+const departmentList = ref([{ dictKey: "0", dictValue: "胜德体育" }]);
+const tagList = ref({
+  10: "warning",
+  30: "danger",
+  40: "info",
+  50: "success",
+});
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 0,
+    pageNum: 1,
+    pageSize: 10,
+    code: "",
+    wlnCode: "",
+    departmentId: "",
+    tagList: [],
+    beginTime: "",
+    endTime: "",
+  },
+});
+const loading = ref(false);
+const searchConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "code",
+      label: "订单号",
+    },
+    {
+      type: "input",
+      prop: "wlnCode",
+      label: "万里牛单号",
+    },
+    {
+      type: "select",
+      prop: "departmentId",
+      label: "事业部",
+      data: departmentList.value,
+    },
+    {
+      type: "select",
+      prop: "tagList",
+      dictKey: "order_tag",
+      label: "标签",
+      multiple: true,
+    },
+    {
+      type: "date",
+      propList: ["beginTime", "endTime"],
+      label: "交期",
+    },
+  ];
+});
+const config = computed(() => {
+  return [
+    {
+      type: "selection",
+      attrs: {
+        checkAtt: "isCheck",
+      },
+    },
+    {
+      attrs: {
+        label: "事业部",
+        prop: "departmentName",
+        width: 160,
+      },
+    },
+    {
+      attrs: {
+        label: "订单号",
+        slot: "code",
+        width: 220,
+      },
+    },
+    {
+      attrs: {
+        label: "万里牛单号",
+        prop: "wlnCode",
+        width: 200,
+      },
+    },
+    {
+      attrs: {
+        label: "快递单号",
+        prop: "expressDeliveryCode",
+        width: 180,
+      },
+    },
+    {
+      attrs: {
+        label: "交期",
+        prop: "deliveryTime",
+        width: 160,
+        align: "center",
+      },
+    },
+    {
+      attrs: {
+        label: "各款SKU生产进度",
+        slot: "schedule",
+        "min-width": 220,
+      },
+    },
+    {
+      attrs: {
+        label: "操作",
+        width: 100,
+        align: "center",
+        fixed: "right",
+      },
+      renderHTML(row) {
+        return [
+          {
+            attrs: {
+              label: "一键包装",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              clickPacking(row);
+            },
+          },
+        ];
+      },
+    },
+  ];
+});
+const getDemandData = () => {
+  proxy.post("/department/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    if (res.rows && res.rows.length > 0) {
+      departmentList.value = departmentList.value.concat(
+        res.rows.map((item) => {
+          return {
+            dictKey: item.id,
+            dictValue: item.name,
+          };
+        })
+      );
+    }
+  });
+};
+getDemandData();
+const getList = async (req, status) => {
+  if (status) {
+    sourceList.value.pagination = {
+      pageNum: sourceList.value.pagination.pageNum,
+      pageSize: sourceList.value.pagination.pageSize,
+    };
+  } else {
+    sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  }
+  loading.value = true;
+  proxy.post("/productionOrder/page", sourceList.value.pagination).then((res) => {
+    if (res.rows && res.rows.length > 0) {
+      sourceList.value.data = res.rows.map((item) => {
+        return {
+          ...item,
+          isCheck: true,
+        };
+      });
+    } else {
+      sourceList.value.data = res.rows;
+    }
+    sourceList.value.pagination.total = res.total;
+    setTimeout(() => {
+      loading.value = false;
+    }, 200);
+  });
+};
+getList();
+const clickReset = () => {
+  getList("", true);
+};
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
+const clickCode = (row) => {
+  proxy.$router.replace({
+    path: "/addOrder",
+    query: {
+      detailId: row.id,
+      text: "订单详情",
+      random: proxy.random(),
+      orderInquiry: true,
+    },
+  });
+};
+const openTag = ref(false);
+const formTagData = reactive({
+  data: {
+    tag: "",
+  },
+});
+const rulesTag = ref({
+  tag: [{ required: true, message: "请选择标签", trigger: "change" }],
+});
+const clickTag = () => {
+  if (selectData.value && selectData.value.length > 0) {
+    formTagData.data = {
+      orderIdList: selectData.value.map((item) => item.orderId),
+      tag: "",
+    };
+    openTag.value = true;
+  } else {
+    return ElMessage("请选择需添加标签的数据");
+  }
+};
+const submitTagForm = () => {
+  proxy.$refs["tagForm"].validate((valid) => {
+    if (valid) {
+      proxy.post("/productionOrder/setTag", formTagData.data).then(() => {
+        ElMessage({ message: "提交完成", type: "success" });
+        openTag.value = false;
+        getList();
+      });
+    }
+  });
+};
+const openPacking = ref(false);
+const packingLoading = ref(false);
+const formData = reactive({
+  data: {
+    orderId: "",
+    skuSpecList: [],
+    packageList: [],
+  },
+});
+const rules = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const clickPacking = (row) => {
+  packingLoading.value = true;
+  openPacking.value = true;
+  proxy.post("/productionOrder/detail", { id: row.orderId }).then(
+    (res) => {
+      formData.data = {
+        orderId: row.orderId,
+        skuSpecList: res.skuSpecList,
+        packageList: res.packageList,
+      };
+      packingLoading.value = false;
+    },
+    (err) => {
+      console.log(err);
+      packingLoading.value = false;
+    }
+  );
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = () => {
+  openExpressPacking.value = true;
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.packageList && formData.data.packageList.length > 0) {
+    let list = formData.data.packageList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递包材已添加");
+    }
+    formData.data.packageList.push({
+      bomSpecId: data.id,
+      bomSpecCode: data.code,
+      bomSpecName: data.name,
+      quantity: undefined,
+      costPrice: data.costPrice,
+      internalSellingPrice: data.internalSellingPrice,
+    });
+  } else {
+    formData.data.packageList = [
+      {
+        bomSpecId: data.id,
+        bomSpecCode: data.code,
+        bomSpecName: data.name,
+        quantity: undefined,
+        costPrice: data.costPrice,
+        internalSellingPrice: data.internalSellingPrice,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
+const calculatedAmount = (item, label) => {
+  let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
+const clickDeleteExpressPacking = (index) => {
+  formData.data.packageList.splice(index, 1);
+};
+const submitForm = () => {
+  proxy.$refs["packingForm"].validate((valid) => {
+    if (valid) {
+      if (formData.data.packageList && formData.data.packageList.length > 0) {
+        proxy.post("/productionOrder/rapidPackaging".formData.data).then(() => {
+          ElMessage({ message: "提交成功", type: "success" });
+          openPacking.value = false;
+          getList();
+        });
+      } else {
+        return ElMessage("请先添加快递物流包材");
+      }
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-input-number .el-input__inner) {
+  text-align: left;
+}
+:deep(.el-dialog) {
+  margin-top: 10px !important;
+  margin-bottom: 10px !important;
+}
+:deep(.el-form-item--default) {
+  margin-bottom: 0px;
+}
+</style>