|
@@ -0,0 +1,569 @@
|
|
|
+<template>
|
|
|
+ <div class="pageIndexClass" style="height:calc(100vh - 100px)">
|
|
|
+ <div class="main">
|
|
|
+ <div class="left">
|
|
|
+ <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
|
|
|
+ </byForm>
|
|
|
+ <div style="text-align:center">
|
|
|
+ <el-button type="primary" @click="submitForm()" size="defualt" v-debounce :loading="submitLoading">
|
|
|
+ 保 存
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="right">
|
|
|
+ <div style="padding-left:20px" v-if="printList && printList.length>0">
|
|
|
+ <div v-if="prodFileList && prodFileList.length>0" style="font-size:18px">
|
|
|
+ plt文件:<span class="el-click" @click="openImg(prodFileList[0].fileUrl)"> {{prodFileList[0].fileName}} </span>
|
|
|
+ </div>
|
|
|
+ <el-button type="primary" v-print="printObj" size="defualt">打印任务单</el-button>
|
|
|
+ </div>
|
|
|
+ <div id="pdfDom" style="width:100%">
|
|
|
+ <div v-for="item in printList" :key="item.id" style="margin-bottom:20px">
|
|
|
+ <div style="font-size:32px;font-weight:700;color:#000;text-align:center">
|
|
|
+ 生产任务单
|
|
|
+ </div>
|
|
|
+ <div style="float:right;margin: 20px 0px 5px 0;">
|
|
|
+ {{printTime}}
|
|
|
+ </div>
|
|
|
+ <table class="table" border>
|
|
|
+ <tr>
|
|
|
+ <td style="width:25%">
|
|
|
+ <div :ref="item.id">
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ <td style="width:75%">
|
|
|
+ <div style="display:flex;margin-bottom:10px">
|
|
|
+ <div style="width:50%">
|
|
|
+ <div class="top-title">
|
|
|
+ 订单号
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.orderCode}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="width:50%">
|
|
|
+ <div class="top-title">
|
|
|
+ 交期
|
|
|
+ </div>
|
|
|
+ <div v-if="item.deliveryPeriod">
|
|
|
+ {{item.deliveryPeriod.substr(0,10)}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="display:flex;margin-bottom:10px">
|
|
|
+ <div style="width:50%">
|
|
|
+ <div class="top-title">
|
|
|
+ 产品编码
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.productCode}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="width:50%">
|
|
|
+ <div class="top-title">
|
|
|
+ 生产数量
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.quantity}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="margin-bottom:10px">
|
|
|
+ <div class="top-title">
|
|
|
+ 产品名称
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.productName}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="margin-bottom:10px">
|
|
|
+ <div class="top-title">
|
|
|
+ 产品尺寸(cm)
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.productLength}} * {{item.productWidth}} * {{item.productHeight}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="text-align:center" rowspan="4">
|
|
|
+ <div>
|
|
|
+ <div style="font-weight:700">产品图</div>
|
|
|
+ <img v-if="item.fileList &&item.fileList.length > 0" class="bigImg" :src="item.fileList[0].fileUrl" alt="">
|
|
|
+ </div>
|
|
|
+ <!-- <div style="margin-top:20px">
|
|
|
+ <div style="font-weight:700">设计图</div>
|
|
|
+ <img v-if="item.fileListOne &&item.fileListOne.length > 0" class="bigImg" :src="item.fileListOne[0].fileUrl" alt="">
|
|
|
+ </div> -->
|
|
|
+ </td>
|
|
|
+ <td style="height:60px;vertical-align:top">
|
|
|
+ <div>
|
|
|
+ <div class="top-title">
|
|
|
+ 产品备注
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.productRemark}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="height:60px;vertical-align:top">
|
|
|
+ <div class="top-title">
|
|
|
+ 生产工序
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <!-- <el-checkbox v-for="proess in item.productionTaskProgressList" :key="proess.processesId" :label="proess.progressName"
|
|
|
+ size="small" /> -->
|
|
|
+ <span v-for="(proess,index) in item.productionTaskProgressList" :key="proess.processesId">{{proess.progressName}} <span
|
|
|
+ v-if="index<item.productionTaskProgressList.length-1"> > </span> </span>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="height:107px">
|
|
|
+ <div style="margin-bottom:10px">
|
|
|
+ <div class="top-title">
|
|
|
+ 原材料编码
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.rawMaterialCode}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="top-title">
|
|
|
+ 原材料名称
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{item.rawMaterialName}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td style="vertical-align:top">
|
|
|
+ <div class="top-title">BOM</div>
|
|
|
+ <div>
|
|
|
+ <table border class="table son">
|
|
|
+ <tr>
|
|
|
+ <td style="width:85%">名称</td>
|
|
|
+ <!-- <td style="width:15%">单价</td> -->
|
|
|
+ <td style="width:15%">数量</td>
|
|
|
+ </tr>
|
|
|
+ <tr v-for="son in item.contractProductBomList" :key="son.id">
|
|
|
+ <td>
|
|
|
+ <div>
|
|
|
+ {{son.productCode}}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {{son.productName}}
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ <!-- <td>{{son.price}}</td> -->
|
|
|
+ <td>{{son.quantity}}</td>
|
|
|
+ </tr>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+
|
|
|
+ </table>
|
|
|
+ <div style="page-break-after: always"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import byTable from "@/components/byTable/index";
|
|
|
+import byForm from "@/components/byForm/index";
|
|
|
+import QRCode from "qrcodejs2-fix";
|
|
|
+import moment from "moment";
|
|
|
+import { onMounted } from "vue";
|
|
|
+import { v4 as uuidv4 } from "uuid";
|
|
|
+import { async } from "@antv/x6/lib/registry/marker/main";
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+const loading = ref(false);
|
|
|
+const submitLoading = ref(false);
|
|
|
+const sourceList = ref({
|
|
|
+ data: [],
|
|
|
+ pagination: {
|
|
|
+ total: 3,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ keyword: "",
|
|
|
+ },
|
|
|
+});
|
|
|
+const treeData = ref([]);
|
|
|
+const taskData = ref([]);
|
|
|
+const deviceData = ref([]);
|
|
|
+const dialogVisible = ref(false);
|
|
|
+const modalType = ref("add");
|
|
|
+const selectConfig = computed(() => []);
|
|
|
+const config = computed(() => {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: "店铺编号",
|
|
|
+ prop: "code",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: " 店铺名称",
|
|
|
+ prop: "name",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: "负责部门",
|
|
|
+ prop: "deptName",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: "操作",
|
|
|
+ width: "120",
|
|
|
+ align: "center",
|
|
|
+ fixed: "right",
|
|
|
+ },
|
|
|
+ renderHTML(row) {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: "修改",
|
|
|
+ type: "primary",
|
|
|
+ text: true,
|
|
|
+ },
|
|
|
+ el: "button",
|
|
|
+ click() {
|
|
|
+ getDtl(row);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ attrs: {
|
|
|
+ label: "删除",
|
|
|
+ type: "danger",
|
|
|
+ text: true,
|
|
|
+ },
|
|
|
+ el: "button",
|
|
|
+ click() {
|
|
|
+ proxy
|
|
|
+ .msgConfirm()
|
|
|
+ .then((res) => {
|
|
|
+ proxy
|
|
|
+ .post("/shopInfo/delete", {
|
|
|
+ id: row.id,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ proxy.msgTip("删除成功", 1);
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((err) => {});
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+});
|
|
|
+const formData = reactive({
|
|
|
+ data: {},
|
|
|
+});
|
|
|
+const formOption = reactive({
|
|
|
+ inline: true,
|
|
|
+ labelWidth: 110,
|
|
|
+ itemWidth: 100,
|
|
|
+});
|
|
|
+const formDom = ref(null);
|
|
|
+const formConfig = computed(() => {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ type: "input",
|
|
|
+ prop: "userUuid",
|
|
|
+ label: "设备唯一标识",
|
|
|
+ itemWidth: 100,
|
|
|
+ disabled: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "select",
|
|
|
+ prop: "id",
|
|
|
+ label: "机台设备",
|
|
|
+ data: deviceData.value,
|
|
|
+ itemWidth: 100,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "select",
|
|
|
+ prop: "prodMode",
|
|
|
+ label: "生产模式",
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ dictKey: "1",
|
|
|
+ dictValue: "批量单",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ dictKey: "2",
|
|
|
+ dictValue: "散单",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ itemWidth: 100,
|
|
|
+ fn: (val) => {
|
|
|
+ if (val == 2) {
|
|
|
+ formData.data.prodTaskId = "";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "select",
|
|
|
+ prop: "prodTaskId",
|
|
|
+ label: "生产任务",
|
|
|
+ data: taskData.value,
|
|
|
+ itemWidth: 100,
|
|
|
+ isShow: formData.data.prodMode == "1",
|
|
|
+ fn: (val) => {
|
|
|
+ if (val) {
|
|
|
+ getPrintData(val);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+});
|
|
|
+const rules = ref({
|
|
|
+ prodTaskId: [
|
|
|
+ { required: true, message: "请选择生产任务", trigger: "change" },
|
|
|
+ ],
|
|
|
+ prodMode: [{ required: true, message: "请选择生产模式", trigger: "change" }],
|
|
|
+ id: [{ required: true, message: "请选择机台设备", trigger: "change" }],
|
|
|
+});
|
|
|
+
|
|
|
+const getDeptData = () => {
|
|
|
+ proxy
|
|
|
+ .get("/tenantDept/list", {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 9999,
|
|
|
+ keyword: "",
|
|
|
+ tenantId: proxy.useUserStore().user.tenantId,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ treeData.value = proxy.handleTree(res.data, "deptId");
|
|
|
+ });
|
|
|
+};
|
|
|
+// getDeptData();
|
|
|
+
|
|
|
+const getList = async (req) => {
|
|
|
+ proxy.post("/productionScheduling/schedulingTaskList").then((res) => {
|
|
|
+ taskData.value = res.map((x) => ({
|
|
|
+ label: x.orderCode + `,${x.productCode}(${x.productName})`,
|
|
|
+ value: x.id,
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ proxy
|
|
|
+ .post("/tdaDevice/page", {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 999,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ deviceData.value = res.rows.map((x) => ({
|
|
|
+ label: x.deviceName,
|
|
|
+ value: x.id,
|
|
|
+ }));
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const openModal = () => {
|
|
|
+ dialogVisible.value = true;
|
|
|
+ modalType.value = "add";
|
|
|
+ formData.data = {
|
|
|
+ definition: "2",
|
|
|
+ };
|
|
|
+ if (currencyData.value && currencyData.value.length > 0) {
|
|
|
+ formData.data.currency = currencyData.value[0].dictKey;
|
|
|
+ formData.data.costCurrency = currencyData.value[0].dictKey;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const submitForm = () => {
|
|
|
+ formDom.value.handleSubmit((valid) => {
|
|
|
+ submitLoading.value = true;
|
|
|
+ proxy.post("/tdaDevice/edit", formData.data).then(
|
|
|
+ (res) => {
|
|
|
+ proxy.msgTip("操作成功", 1);
|
|
|
+ // dialogVisible.value = false;
|
|
|
+ submitLoading.value = false;
|
|
|
+ getDtl();
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ submitLoading.value = false;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ if (window.localStorage.getItem("_deviceId")) {
|
|
|
+ formData.data.userUuid = window.localStorage.getItem("_deviceId");
|
|
|
+ } else {
|
|
|
+ let uuid = uuidv4();
|
|
|
+ formData.data.userUuid = uuid;
|
|
|
+ window.localStorage.setItem("_deviceId", uuid);
|
|
|
+ }
|
|
|
+ getDtl();
|
|
|
+});
|
|
|
+
|
|
|
+const getDtl = (row) => {
|
|
|
+ // modalType.value = "edit";
|
|
|
+ let userUuid = window.localStorage.getItem("_deviceId");
|
|
|
+ if (userUuid) {
|
|
|
+ proxy.post("/tdaDevice/detail", { userUuid: userUuid }).then((res) => {
|
|
|
+ formData.data = res;
|
|
|
+ if (formData.data.prodTaskId) {
|
|
|
+ getPrintData(formData.data.prodTaskId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+getList();
|
|
|
+
|
|
|
+const printList = ref([]);
|
|
|
+const printTime = ref("");
|
|
|
+const prodFileList = ref([]);
|
|
|
+const getPrintData = (val) => {
|
|
|
+ // proxy.msgTip("请稍后", 2);
|
|
|
+ proxy
|
|
|
+ .post("/produceOrderDetail/detailByIds", { taskIds: [val] })
|
|
|
+ .then(async (res) => {
|
|
|
+ const productAllFile = await proxy.getFileData({
|
|
|
+ businessIdList: [res[0].productId],
|
|
|
+ getAll: true,
|
|
|
+ });
|
|
|
+ if (
|
|
|
+ productAllFile &&
|
|
|
+ productAllFile[res[0].productId] &&
|
|
|
+ productAllFile[res[0].productId].length > 0
|
|
|
+ ) {
|
|
|
+ res[0].fileList = productAllFile[res[0].productId].filter(
|
|
|
+ (x) => x.businessType == "0"
|
|
|
+ );
|
|
|
+ }
|
|
|
+ proxy
|
|
|
+ .getFileData({
|
|
|
+ businessIdList: [res[0].contractDetailId],
|
|
|
+ getAll: true,
|
|
|
+ })
|
|
|
+ .then((file) => {
|
|
|
+ if (
|
|
|
+ file &&
|
|
|
+ file[res[0].contractDetailId] &&
|
|
|
+ file[res[0].contractDetailId].length > 0
|
|
|
+ ) {
|
|
|
+ prodFileList.value = file[res[0].contractDetailId].filter(
|
|
|
+ (x) => x.businessType == "2"
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ printList.value = res;
|
|
|
+ // for (let i = 0; i < formData.data.contractProductList.length; i++) {
|
|
|
+ // const ele = formData.data.contractProductList[i];
|
|
|
+ // for (const key in productAllFile) {
|
|
|
+ // if (
|
|
|
+ // ele.productId == key &&
|
|
|
+ // productAllFile[ele.productId] &&
|
|
|
+ // productAllFile[ele.productId].length > 0
|
|
|
+ // ) {
|
|
|
+ // ele.productFile = productAllFile[ele.productId].filter(
|
|
|
+ // (x) => x.businessType == "0"
|
|
|
+ // );
|
|
|
+ // if (ele.productFile && ele.productFile.length > 0) {
|
|
|
+ // ele.fileUrl = ele.productFile[0].fileUrl;
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ printTime.value = moment().format("yyyy-MM-DD HH:mm:ss");
|
|
|
+ nextTick(() => {
|
|
|
+ for (let i = 0; i < printList.value.length; i++) {
|
|
|
+ const row = printList.value[i];
|
|
|
+ proxy.$refs[row.id][0].innerHTML = ""; //清除二维码方法一
|
|
|
+ new QRCode(proxy.$refs[row.id][0], {
|
|
|
+ text: row.id,
|
|
|
+ width: 200,
|
|
|
+ height: 200,
|
|
|
+ colorDark: "#000000",
|
|
|
+ colorLight: "#ffffff",
|
|
|
+ correctLevel: QRCode.CorrectLevel.H,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const printObj = ref({
|
|
|
+ id: "pdfDom",
|
|
|
+ popTitle: "",
|
|
|
+ extraCss:
|
|
|
+ "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
|
|
|
+ extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.main {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+
|
|
|
+ .left {
|
|
|
+ width: calc(100vw - 840px);
|
|
|
+ height: 100%;
|
|
|
+ overflow: auto;
|
|
|
+ // border-right: 1px solid #eee;
|
|
|
+ margin-right: 10px;
|
|
|
+ padding: 15px 15px 4px 4px;
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+ .right {
|
|
|
+ width: 840px;
|
|
|
+ height: 100%;
|
|
|
+ overflow: auto;
|
|
|
+ position: relative;
|
|
|
+ padding: 15px;
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.table {
|
|
|
+ border-collapse: collapse;
|
|
|
+ border-spacing: 0;
|
|
|
+ width: 100%;
|
|
|
+ td {
|
|
|
+ text-align: left;
|
|
|
+ padding: 10px;
|
|
|
+ font-size: 13px;
|
|
|
+ // padding: 5px 10px;
|
|
|
+ .top-title {
|
|
|
+ font-weight: 700;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+ .bigImg {
|
|
|
+ object-fit: contain;
|
|
|
+ width: 160px;
|
|
|
+ height: 320px;
|
|
|
+ cursor: pointer;
|
|
|
+ margin-top: 10px;
|
|
|
+ vertical-align: middle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.son {
|
|
|
+ td {
|
|
|
+ text-align: left;
|
|
|
+ padding: 5px !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|