cz před 2 roky
rodič
revize
8cab28904c

+ 51 - 46
src/components/common-list.vue

@@ -1,59 +1,64 @@
 <template>
-    <div class="common-list">
-        <ul>
-            <li v-for="i in data" :key="i.id" @click="listCk(i)">
-                <!-- <div class="left-box">
+  <div class="common-list">
+    <ul>
+      <li v-for="i in data" :key="i.id" @click="listCk(i)">
+        <!-- <div class="left-box">
                     <van-icon name="location-o" />
                 </div> -->
-                <div class="center-content" style="line-height:24px">
-                    <div v-for="j in config" :key="j.prop"><span>{{ j.label }}:</span>{{ i[j.prop] }}</div>
-                </div>
-                <div class="more-box">
-                    <van-icon name="arrow" />
-                </div>
-            </li>
-        </ul>
-    </div>
+        <div class="center-content" style="line-height: 24px">
+          <div v-for="j in config" :key="j.prop">
+            <span>{{ j.label }}:</span>{{ i[j.prop] }}
+          </div>
+        </div>
+        <div class="more-box" v-if="showMore">
+          <van-icon name="arrow" />
+        </div>
+      </li>
+    </ul>
+  </div>
 </template>
 <script setup>
-import { ref, getCurrentInstance, onMounted,defineProps } from 'vue'
-const proxy = getCurrentInstance().proxy
+import { ref, getCurrentInstance, onMounted, defineProps } from "vue";
+const proxy = getCurrentInstance().proxy;
 defineProps({
-    data: {
-        type: Array,
-        default: []
-    },
-    config: {
-        type: Object,
-        default: []
-    }
-})
+  data: {
+    type: Array,
+    default: [],
+  },
+  config: {
+    type: Object,
+    default: [],
+  },
+  showMore: {
+    type: Boolean,
+    default: true,
+  },
+});
 
 const listCk = (item) => {
-    proxy.$emit('onClick', item)
-}
+  proxy.$emit("onClick", item);
+};
 </script>
 <style lang="scss">
-.common-list{
-    ul{
-        margin-top: 10px;
-        li{
-            list-style: none;
-            position: relative;
-            display: flex;
-            box-sizing: border-box;
-            align-items: center;
-            justify-content: space-between;
-            padding: 12px 16px;
-            background: #fff;
-            border-bottom: 1px solid #f1f1f1;
-            .center-content{
-                flex: 1;
-            }
-            .left-box{
-
-            }
-        }
+.common-list {
+  ul {
+    margin-top: 10px;
+    li {
+      list-style: none;
+      position: relative;
+      display: flex;
+      box-sizing: border-box;
+      align-items: center;
+      justify-content: space-between;
+      padding: 12px 16px;
+      background: #fff;
+      border-bottom: 1px solid #f1f1f1;
+      .center-content {
+        flex: 1;
+      }
+      .left-box {
+      }
     }
+  }
 }
 </style>

+ 68 - 0
src/router/index.js

@@ -117,6 +117,74 @@ const routes = [{
 				name: '工单管理详情',
 				component: () => import('../views/MES/workOrder/details.vue')
 			},
+			{
+				path: 'plan',
+				name: '生产计划',
+				component: () => import('../views/MES/produce/plan/index.vue')
+			},
+			{
+				path: 'planAdd',
+				name: '生产计划新增',
+				component: () => import('../views/MES/produce/plan/add.vue')
+			},
+			{
+				path: 'planDtl',
+				name: '生产计划详情',
+				component: () => import('../views/MES/produce/plan/details.vue')
+			},
+			{
+				path: 'task',
+				name: '生产任务',
+				component: () => import('../views/MES/produce/task/index.vue')
+			},
+			{
+				path: 'taskAdd',
+				name: '生产任务新增',
+				component: () => import('../views/MES/produce/task/add.vue')
+			},
+
+			{
+				path: 'reportWork',
+				name: '生产报工',
+				component: () => import('../views/MES/produceManage/reportWork/index.vue')
+			},
+			{
+				path: 'reportWorkAdd',
+				name: '生产报工新增',
+				component: () => import('../views/MES/produceManage/reportWork/add.vue')
+			},
+			{
+				path: 'reportWorkDtl',
+				name: '生产报工详情',
+				component: () => import('../views/MES/produceManage/reportWork/details.vue')
+			},
+			{
+				path: 'lineSide',
+				name: '线边管理',
+				component: () => import('../views/MES/produceManage/lineSide/index.vue')
+			},
+			{
+				path: 'lineSideAdd',
+				name: '线边管理新增',
+				component: () => import('../views/MES/produceManage/lineSide/add.vue')
+			},
+			{
+				path: 'lineSideEdit',
+				name: '线边处理',
+				component: () => import('../views/MES/produceManage/lineSide/edit.vue')
+			},
+			{
+				path: 'completeProject',
+				name: '完工入库',
+				component: () => import('../views/MES/produceManage/completeProject/index.vue')
+			},
+			{
+				path: 'completeProjectAdd',
+				name: '完工入库新增',
+				component: () => import('../views/MES/produceManage/completeProject/add.vue')
+			},
+
+
 		]
 	},
 

+ 190 - 0
src/views/MES/produce/plan/add.vue

@@ -0,0 +1,190 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="生产计划"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.code"
+          is-link
+          readonly
+          label="选择工单"
+          placeholder="请选择工单"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '工单不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <van-field v-model="formData.productName" readonly label="产品名称" />
+        <van-field
+          v-model="formData.waitQuantity"
+          readonly
+          label="待排程数量"
+        />
+      </van-cell-group>
+
+      <van-cell-group inset style="margin-top: 10px">
+        <van-field
+          v-model="formData.startDate"
+          is-link
+          readonly
+          label="计划开始时间"
+          placeholder="请选择计划开始时间"
+          @click="handleOpenTime(true)"
+          :rules="[{ required: true, message: '计划开始时间不能为空' }]"
+          required
+        />
+        <van-field
+          v-model="formData.stopDate"
+          is-link
+          readonly
+          label="计划结束时间"
+          placeholder="请选择计划结束时间"
+          @click="handleOpenTime(false)"
+          :rules="[{ required: true, message: '计划结束时间不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="showPicker" position="bottom">
+          <van-date-picker
+            @confirm="onConfirmTime"
+            @cancel="showPicker = false"
+          />
+        </van-popup>
+
+        <van-field
+          v-model="formData.quantity"
+          label="计划数量"
+          placeholder="请输入计划数量"
+          :rules="[{ required: true, message: '计划数量不能为空' }]"
+          required
+        />
+      </van-cell-group>
+
+      <div style="margin: 16px">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const showPicker = ref(false);
+const formData = ref({
+  code: "",
+  productName: "",
+  waitQuantity: "",
+  workOrderId: "",
+  startDate: "",
+  stopDate: "",
+  quantity: null,
+});
+
+const getDict = () => {
+  proxy.post("/workOrder/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    columns.value = res.data.rows.map((item, index) => {
+      return {
+        ...item,
+        text: item.code,
+        value: item.id,
+      };
+    });
+  });
+};
+
+const getDetails = (id) => {
+  proxy.post("/stockJournal/detail", { id }).then((res) => {
+    formData.value = res.data;
+    list.value = res.data.list.map((x) => ({
+      productId: x.productId,
+      productName: x.productName,
+      quantity: x.quantity,
+    }));
+  });
+};
+
+const columns = ref([]);
+let isStart = ref(false);
+const handleOpenTime = (type) => {
+  isStart.value = type;
+  showPicker.value = true;
+};
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.workOrderId = selectedOptions[0].value;
+  formData.value.code = selectedOptions[0].text;
+  formData.value.productName = selectedOptions[0].productName;
+  formData.value.waitQuantity = selectedOptions[0].remainingQuantity;
+  typeModal.value = false;
+};
+
+const onConfirmTime = ({ selectdValues, selectedOptions }) => {
+  if (isStart.value) {
+    formData.value.startDate = selectedOptions.reduce(
+      (str, x, i) =>
+        (str += x.value + (i < selectedOptions.length - 1 ? "-" : "")),
+      ""
+    );
+  } else {
+    formData.value.stopDate = selectedOptions.reduce(
+      (str, x, i) =>
+        (str += x.value + (i < selectedOptions.length - 1 ? "-" : "")),
+      ""
+    );
+  }
+  showPicker.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  proxy.post("/productionPlan/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("添加成功");
+        proxy.$router.push("/main/plan");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 121 - 0
src/views/MES/produce/plan/details.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="工单管理"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+
+    <div>
+      <common-top :data="formData" :config="topConfig"> </common-top>
+      <div style="line-height: 32px; color: #999999; padding: 0 15px">
+        生产任务
+      </div>
+      <common-body :data="formData.productionTaskList" :config="bodyConfig">
+      </common-body>
+      <!-- <van-form label-align="top">
+        <div v-for="(item, index) in 3" :key="index" style="margin-top: 10px">
+          <van-field v-model="formData.productName" readonly label="计划日期" />
+          <van-field v-model="formData.productName" readonly label="计划数量" />
+          <van-field v-model="formData.productName" readonly label="计划状态" />
+        </div>
+      </van-form> -->
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { useRoute } from "vue-router";
+
+import commonTop from "@/components/MES/common-top.vue";
+import commonBody from "@/components/MES/common-body.vue";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+
+const formData = ref({
+  source: "",
+  sourceName: "",
+  productId: "1",
+  productName: "",
+  quantity: null,
+  remarks: "",
+});
+
+const topConfig = ref([
+  {
+    label: "计划时间",
+    prop: "time",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+  {
+    label: "计划数量",
+    prop: "quantity",
+  },
+  {
+    label: "计划状态",
+    prop: "statusName",
+  },
+]);
+
+const bodyConfig = ref([
+  {
+    label: "任务数量",
+    prop: "quantity",
+  },
+  {
+    label: "负责人",
+    prop: "personLiableName",
+  },
+  {
+    label: "完成状态",
+    prop: "status",
+  },
+]);
+
+const getDetails = (id) => {
+  proxy.post("/productionPlan/detail", { id }).then((res) => {
+    res.data.time = res.data.startDate + " ~ " + res.data.stopDate;
+    // res.data.productionTaskList=
+    let status = res.data.status;
+    res.data.statusName =
+      status == 0
+        ? "未开始"
+        : status == 1
+        ? "进行中"
+        : status == 2
+        ? "完成"
+        : "";
+
+    formData.value = res.data;
+  });
+};
+
+const onClickLeft = () => history.back();
+
+onMounted(() => {
+  getDetails(route.query.id);
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 138 - 0
src/views/MES/produce/plan/index.vue

@@ -0,0 +1,138 @@
+<template>
+  <div style="padding-bottom: 60px">
+    <van-nav-bar
+      title="生产计划"
+      left-text=""
+      left-arrow
+      @click-left="onClickLeft"
+      @click-right="onClickRight"
+    >
+      <template #right> 添加 </template>
+    </van-nav-bar>
+    <van-search
+      v-model="req.keyword"
+      placeholder="请输入搜索关键词"
+      @search="onRefresh"
+    />
+
+    <van-pull-refresh v-model="loading" @refresh="onRefresh">
+      <div class="list">
+        <van-list
+          v-model:loading="loading"
+          :finished="finished"
+          finished-text="没有更多了"
+          @load="onLoad"
+          style="margin-bottom: 60px"
+        >
+          <commonList
+            :data="listData"
+            @onClick="toDtl"
+            :config="listConfig"
+          ></commonList>
+        </van-list>
+      </div>
+    </van-pull-refresh>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "计划时间",
+    prop: "time",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+
+  {
+    label: "计划数量",
+    prop: "quantity",
+  },
+  {
+    label: "计划状态",
+    prop: "statusName",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/planAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "planDtl",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/productionPlan/page", req.value)
+    .then((res) => {
+      const data = res.data.rows.map((x) => ({
+        ...x,
+        time: x.startDate + " ~ " + x.stopDate,
+        statusName:
+          x.status == 0
+            ? "未开始"
+            : x.status == 1
+            ? "进行中"
+            : x.status == 2
+            ? "完成"
+            : "",
+      }));
+      if (type === "refresh") {
+        listData.value = data;
+      } else {
+        listData.value = listData.value.concat(data);
+      }
+      // listData.value =
+      //   type === "refresh"
+      //     ? res.data.rows
+      //     : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 193 - 0
src/views/MES/produce/task/add.vue

@@ -0,0 +1,193 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="生产任务"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.productionPlanId"
+          is-link
+          readonly
+          label="生产计划"
+          placeholder="请选择生产计划"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '生产计划不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <van-field v-model="formData.productName" readonly label="产品名称" />
+        <van-field
+          v-model="formData.waitQuantity"
+          readonly
+          label="待生产数量"
+        />
+      </van-cell-group>
+
+      <van-cell-group inset style="margin-top: 10px">
+        <van-field
+          v-model="formData.quantity"
+          label="任务数量"
+          placeholder="请输入任务数量"
+          :rules="[{ required: true, message: '任务数量不能为空' }]"
+          required
+        />
+        <van-field
+          v-model="formData.personLiableName"
+          is-link
+          readonly
+          label="负责人"
+          placeholder="请选择负责人"
+          @click="typeModalOne = true"
+          :rules="[{ required: true, message: '负责人不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModalOne" round position="bottom">
+          <van-picker
+            :columns="columnsOne"
+            @cancel="typeModalOne = false"
+            @confirm="onConfirmOne"
+          />
+        </van-popup>
+
+        <van-field
+          v-model="formData.dueDate"
+          is-link
+          readonly
+          label="完成期限"
+          placeholder="请选择完成期限"
+          @click="showPicker = true"
+          :rules="[{ required: true, message: '完成期限不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="showPicker" position="bottom">
+          <van-date-picker
+            @confirm="onConfirmTime"
+            @cancel="showPicker = false"
+          />
+        </van-popup>
+      </van-cell-group>
+
+      <div style="margin: 16px">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+const showPicker = ref(false);
+const formData = ref({
+  productName: "",
+  waitQuantity: "",
+  productionPlanId: "",
+  personLiableId: "",
+  personLiableName: "",
+  status: "",
+  quantity: "",
+  dueDate: "",
+});
+
+const getDict = () => {
+  proxy
+    .post("/productionPlan/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      columns.value = res.data.rows.map((item) => {
+        return {
+          ...item,
+          text: item.productName,
+          value: item.id,
+        };
+      });
+    });
+
+  proxy.get("/system/user/list?pageNum=1&pageSize=9999").then((res) => {
+    console.log(res);
+    columnsOne.value = res.rows.map((item) => {
+      return {
+        text: item.userName,
+        value: item.userId,
+      };
+    });
+  });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.productionPlanId = selectedOptions[0].value;
+  formData.value.productName = selectedOptions[0].productName;
+  formData.value.waitQuantity = selectedOptions[0].remainingQuantity;
+  typeModal.value = false;
+};
+
+const onConfirmTime = ({ selectdValues, selectedOptions }) => {
+  formData.value.dueDate = selectedOptions.reduce(
+    (str, x, i) =>
+      (str += x.value + (i < selectedOptions.length - 1 ? "-" : "")),
+    ""
+  );
+  showPicker.value = false;
+};
+const onConfirmOne = ({ selectedOptions }) => {
+  formData.value.personLiableName = selectedOptions[0].text;
+  formData.value.personLiableId = selectedOptions[0].value;
+  typeModalOne.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  proxy.post("/productionTask/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("添加成功");
+        proxy.$router.push("/main/task");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 142 - 0
src/views/MES/produce/task/index.vue

@@ -0,0 +1,142 @@
+<template>
+  <div style="padding-bottom: 60px">
+    <van-nav-bar
+      title="生产任务"
+      left-text=""
+      left-arrow
+      @click-left="onClickLeft"
+      @click-right="onClickRight"
+    >
+      <template #right> 添加 </template>
+    </van-nav-bar>
+    <van-search
+      v-model="req.keyword"
+      placeholder="请输入搜索关键词"
+      @search="onRefresh"
+    />
+
+    <van-pull-refresh v-model="loading" @refresh="onRefresh">
+      <div class="list">
+        <van-list
+          v-model:loading="loading"
+          :finished="finished"
+          finished-text="没有更多了"
+          @load="onLoad"
+          style="margin-bottom: 60px"
+        >
+          <commonList
+            :data="listData"
+            :config="listConfig"
+            :showMore="false"
+          ></commonList>
+        </van-list>
+      </div>
+    </van-pull-refresh>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "任务编码",
+    prop: "code",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+
+  {
+    label: "任务数量",
+    prop: "quantity",
+  },
+  {
+    label: "完成期限",
+    prop: "dueDate",
+  },
+  {
+    label: "负责人",
+    prop: "personLiableName",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/taskAdd");
+};
+
+// const toDtl = (row) => {
+//   proxy.$router.push({
+//     path: "taskDtl",
+//     query: {
+//       id: row.id,
+//     },
+//   });
+// };
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/productionTask/page", req.value)
+    .then((res) => {
+      // const data = res.data.rows.map((x) => ({
+      //   ...x,
+      //   time: x.startDate + " ~ " + x.stopDate,
+      //   statusName:
+      //     x.status == 0
+      //       ? "未开始"
+      //       : x.status == 1
+      //       ? "进行中"
+      //       : x.status == 2
+      //       ? "完成"
+      //       : "",
+      // }));
+      // if (type === "refresh") {
+      //   listData.value = data;
+      // } else {
+      //   listData.value = listData.value.concat(data);
+      // }
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 145 - 0
src/views/MES/produceManage/completeProject/add.vue

@@ -0,0 +1,145 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="完工入库"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.code"
+          is-link
+          readonly
+          label="生产任务"
+          placeholder="选择生产任务"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '生产任务不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <van-field v-model="formData.productName" readonly label="产品名称" />
+        <van-field v-model="formData.taskQuantity" readonly label="任务数量" />
+        <van-field
+          v-model="formData.personLiableName"
+          readonly
+          label="负责人"
+        />
+        <van-field v-model="formData.dueDate" readonly label="完成期限" />
+      </van-cell-group>
+
+      <van-cell-group inset style="margin-top: 10px">
+        <van-field
+          v-model="formData.quantity"
+          label="完工数量"
+          placeholder="请输入完工数量"
+          :rules="[{ required: true, message: '完工数量不能为空' }]"
+          required
+        />
+      </van-cell-group>
+
+      <div style="margin: 16px" v-if="!route.query.id">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const formData = ref({
+  quantity: "",
+});
+
+const getDict = () => {
+  proxy
+    .post("/productionTask/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      columns.value = res.data.rows.map((item) => {
+        return {
+          ...item,
+          taskQuantity: item.quantity,
+          text: item.code,
+          value: item.id,
+        };
+      });
+    });
+};
+
+const getDetails = (id) => {
+  proxy.post("/completionInfo/detail", { id }).then((res) => {
+    formData.value.quantity = res.data.quantity;
+    formData.value.taskQuantity = res.data.productionTaskQuantity;
+    formData.value.code = res.data.productionTaskCode;
+    formData.value.productName = res.data.productName;
+    formData.value.personLiableName = res.data.personLiableName;
+    formData.value.dueDate = res.data.productionTaskDueDate;
+  });
+};
+
+const columns = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.code = selectedOptions[0].text;
+  formData.value.productionTaskId = selectedOptions[0].value;
+  formData.value.productName = selectedOptions[0].productName;
+  formData.value.taskQuantity = selectedOptions[0].taskQuantity;
+  formData.value.personLiableName = selectedOptions[0].personLiableName;
+  formData.value.dueDate = selectedOptions[0].dueDate;
+  typeModal.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  proxy.post("/completionInfo/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("完工入库成功");
+        proxy.$router.push("/main/completeProject");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+
+onMounted(() => {
+  getDict();
+  route.query.id ? getDetails(route.query.id) : "";
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 15px;
+  justify-content: space-between;
+  align-items: center;
+  color: #999999;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 135 - 0
src/views/MES/produceManage/completeProject/index.vue

@@ -0,0 +1,135 @@
+<template>
+  <div style="padding-bottom: 60px">
+    <van-nav-bar
+      title="完工入库"
+      left-text=""
+      left-arrow
+      @click-left="onClickLeft"
+      @click-right="onClickRight"
+    >
+      <template #right> 添加 </template>
+    </van-nav-bar>
+    <van-search
+      v-model="req.keyword"
+      placeholder="请输入搜索关键词"
+      @search="onRefresh"
+    />
+
+    <van-pull-refresh v-model="loading" @refresh="onRefresh">
+      <div class="list">
+        <van-list
+          v-model:loading="loading"
+          :finished="finished"
+          finished-text="没有更多了"
+          @load="onLoad"
+          style="margin-bottom: 60px"
+        >
+          <commonList
+            :data="listData"
+            @onClick="toDtl"
+            :config="listConfig"
+          ></commonList>
+        </van-list>
+      </div>
+    </van-pull-refresh>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "生产任务",
+    prop: "productionTaskCode",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+
+  {
+    label: "完工数量",
+    prop: "quantity",
+  },
+]);
+
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/completeProjectAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "completeProjectAdd",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/completionInfo/page", req.value)
+    .then((res) => {
+      // const data = res.data.rows.map((x) => ({
+      //   ...x,
+      //   time: x.startDate + " ~ " + x.stopDate,
+      //   statusName:
+      //     x.status == 0
+      //       ? "未开始"
+      //       : x.status == 1
+      //       ? "进行中"
+      //       : x.status == 2
+      //       ? "完成"
+      //       : "",
+      // }));
+      // if (type === "refresh") {
+      //   listData.value = data;
+      // } else {
+      //   listData.value = listData.value.concat(data);
+      // }
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 206 - 0
src/views/MES/produceManage/lineSide/add.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="线边管理"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.typeName"
+          is-link
+          readonly
+          label="物品类型"
+          placeholder="请选择物品类型"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '物品类型不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <van-field
+          v-model="formData.productName"
+          is-link
+          readonly
+          label="物品名称"
+          placeholder="请选择物品名称"
+          @click="typeModalOne = true"
+          :rules="[{ required: true, message: '物品名称不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModalOne" round position="bottom">
+          <van-picker
+            :columns="columnsOne"
+            @cancel="typeModalOne = false"
+            @confirm="(data) => onConfirmOne(data, index)"
+          />
+        </van-popup>
+        <van-field v-model="formData.lineQuantity" readonly label="线边数量" />
+        <van-field
+          v-model="formData.quantity"
+          label="添加数量"
+          placeholder="请输入添加数量"
+          :rules="[{ required: true, message: '添加数量不能为空' }]"
+          required
+        />
+      </van-cell-group>
+
+      <div style="margin: 16px">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+const formData = ref({
+  typeName: "",
+  productId: "",
+  productName: "",
+  lineQuantity: "",
+  quantity: "",
+});
+
+const getDict = () => {
+  columns.value = [
+    {
+      text: "原料",
+      value: "1",
+    },
+    {
+      text: "辅料",
+      value: "2",
+    },
+    {
+      text: "配件",
+      value: "3",
+    },
+    {
+      text: "包材",
+      value: "4",
+    },
+    {
+      text: "其他",
+      value: "5",
+    },
+  ];
+  // proxy.post("/workOrder/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+  //   columns.value = res.data.rows.map((item, index) => {
+  //     return {
+  //       ...item,
+  //       text: item.code,
+  //       value: item.id,
+  //     };
+  //   });
+  // });
+};
+
+const getMaterialData = (type) => {
+  proxy
+    .post("/productInfo/page", {
+      pageNum: 1,
+      pageSize: 9999,
+      definition: "2",
+      type,
+    })
+    .then((res) => {
+      columnsOne.value = res.data.rows.map((item) => {
+        return {
+          text: item.name,
+          value: item.id,
+        };
+      });
+    });
+};
+
+const getDetails = (id, flag) => {
+  proxy.post("/borderOfLine/detail", { id }).then((res) => {
+    if (flag) {
+      if (res.data === null) {
+        formData.value.lineQuantity = 0;
+      } else {
+        formData.value.lineQuantity = res.data.quantity;
+      }
+    }
+    // formData.value = res.data;
+    // list.value = res.data.list.map((x) => ({
+    //   productId: x.productId,
+    //   productName: x.productName,
+    //   quantity: x.quantity,
+    // }));
+  });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  getMaterialData(selectedOptions[0].value);
+  formData.value.typeName = selectedOptions[0].text;
+  typeModal.value = false;
+  formData.value.productId = "";
+  formData.value.productName = "";
+  formData.value.lineQuantity = "";
+};
+
+const onConfirmOne = ({ selectedOptions }) => {
+  getDetails(selectedOptions[0].value, true);
+  formData.value.productName = selectedOptions[0].text;
+  formData.value.productId = selectedOptions[0].value;
+  typeModalOne.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  proxy.post("/borderOfLine/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("添加成功");
+        proxy.$router.push("/main/lineSide");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+
+onMounted(() => {
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 153 - 0
src/views/MES/produceManage/lineSide/edit.vue

@@ -0,0 +1,153 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="线边管理"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <common-top :data="formData" :config="topConfig"> </common-top>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 10px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.typeName"
+          is-link
+          readonly
+          label="处理类型"
+          placeholder="请选择处理类型"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '处理类型不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+
+        <van-field
+          v-model="formData.quantity"
+          label="数量"
+          placeholder="请输入数量"
+          :rules="[{ required: true, message: '数量不能为空' }]"
+          required
+        />
+      </van-cell-group>
+
+      <div style="margin: 16px">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+import commonTop from "@/components/MES/common-top.vue";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const formData = ref({});
+
+const topConfig = ref([
+  {
+    label: "物料类型",
+    prop: "productTypeName",
+  },
+  {
+    label: "物料名称",
+    prop: "productName",
+  },
+  {
+    label: "线边数量",
+    prop: "lineQuantity",
+  },
+]);
+
+const getDict = () => {
+  columns.value = [
+    {
+      text: "用料",
+      value: "1",
+    },
+    {
+      text: "回仓",
+      value: "2",
+    },
+    {
+      text: "报废",
+      value: "3",
+    },
+    {
+      text: "其他",
+      value: "4",
+    },
+  ];
+};
+
+const getDetails = (id, flag) => {
+  proxy.post("/borderOfLine/detail", { id }).then((res) => {
+    res.data.lineQuantity = res.data.quantity;
+    res.data.quantity = "";
+    formData.value = res.data;
+  });
+};
+
+const columns = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.typeName = selectedOptions[0].text;
+  formData.value.type = selectedOptions[0].value;
+  typeModal.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  const data = {
+    id: formData.value.id,
+    type: formData.value.type,
+    quantity: formData.value.quantity,
+  };
+  proxy.post("/borderOfLine/edit", data).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("操作成功");
+        proxy.$router.push("/main/lineSide");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+
+onMounted(() => {
+  getDetails(route.query.id);
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 134 - 0
src/views/MES/produceManage/lineSide/index.vue

@@ -0,0 +1,134 @@
+<template>
+  <div style="padding-bottom: 60px">
+    <van-nav-bar
+      title="线边管理"
+      left-text=""
+      left-arrow
+      @click-left="onClickLeft"
+      @click-right="onClickRight"
+    >
+      <template #right> 添加 </template>
+    </van-nav-bar>
+    <van-search
+      v-model="req.keyword"
+      placeholder="请输入搜索关键词"
+      @search="onRefresh"
+    />
+
+    <van-pull-refresh v-model="loading" @refresh="onRefresh">
+      <div class="list">
+        <van-list
+          v-model:loading="loading"
+          :finished="finished"
+          finished-text="没有更多了"
+          @load="onLoad"
+          style="margin-bottom: 60px"
+        >
+          <commonList
+            :data="listData"
+            @onClick="toDtl"
+            :config="listConfig"
+          ></commonList>
+        </van-list>
+      </div>
+    </van-pull-refresh>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "物料类型",
+    prop: "productTypeName",
+  },
+  {
+    label: "物料名称",
+    prop: "productName",
+  },
+
+  {
+    label: "线边数量",
+    prop: "quantity",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/lineSideAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "lineSideEdit",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/borderOfLine/page", req.value)
+    .then((res) => {
+      // const data = res.data.rows.map((x) => ({
+      //   ...x,
+      //   time: x.startDate + " ~ " + x.stopDate,
+      //   statusName:
+      //     x.status == 0
+      //       ? "未开始"
+      //       : x.status == 1
+      //       ? "进行中"
+      //       : x.status == 2
+      //       ? "完成"
+      //       : "",
+      // }));
+      // if (type === "refresh") {
+      //   listData.value = data;
+      // } else {
+      //   listData.value = listData.value.concat(data);
+      // }
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 247 - 0
src/views/MES/produceManage/reportWork/add.vue

@@ -0,0 +1,247 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="生产报工"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.code"
+          is-link
+          readonly
+          label="生产任务"
+          placeholder="选择生产任务"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '生产任务不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <van-field v-model="formData.productName" readonly label="产品名称" />
+        <van-field v-model="formData.quantity" readonly label="任务数量" />
+        <van-field
+          v-model="formData.personLiableName"
+          readonly
+          label="负责人"
+        />
+        <van-field v-model="formData.dueDate" readonly label="完成期限" />
+      </van-cell-group>
+
+      <!-- 明细列表 -->
+      <div
+        v-for="(item, index) in formData.productionReportingDetailList"
+        :key="index"
+      >
+        <div class="row">
+          <div class="title">明细{{ index + 1 }}</div>
+          <div
+            class="delete"
+            @click.native="handleDel(index)"
+            v-if="!route.query.id"
+          >
+            <van-icon name="cross" />
+          </div>
+        </div>
+        <van-cell-group inset>
+          <van-field
+            v-model="
+              formData.productionReportingDetailList[index]
+                .productionProcessesName
+            "
+            is-link
+            readonly
+            label="工序名称"
+            placeholder="选择工序名称"
+            @click="handleSelect(index)"
+            :rules="[{ required: true, message: '工序名称不能为空' }]"
+            required
+          />
+          <van-field
+            v-model="formData.productionReportingDetailList[index].name"
+            label="姓名"
+            placeholder="请输入姓名"
+            :rules="[{ required: true, message: '姓名不能为空' }]"
+            required
+          />
+
+          <van-field
+            v-model="formData.productionReportingDetailList[index].quantity"
+            label="报工数量"
+            placeholder="请输入报工数量"
+            :rules="[{ required: true, message: '报工数量不能为空' }]"
+            required
+          />
+        </van-cell-group>
+      </div>
+      <van-popup v-model:show="typeModalOne" round position="bottom">
+        <van-picker
+          :columns="columnsOne"
+          @cancel="typeModalOne = false"
+          @confirm="(data) => onConfirmOne(data)"
+        />
+      </van-popup>
+
+      <div style="text-align: center; line-height: 28px" v-if="!route.query.id">
+        <van-button
+          icon="plus"
+          type="primary"
+          plain
+          size="mini"
+          style="margin-top: 10px"
+          @click="handleAddRow"
+          >添加明细</van-button
+        >
+      </div>
+
+      <div style="margin: 16px" v-if="!route.query.id">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+let selectIndex = ref(null);
+const formData = ref({
+  productionTaskId: "",
+  code: "",
+  productName: "",
+  quantity: "",
+  personLiableName: "",
+  dueDate: "",
+  productionReportingDetailList: [],
+});
+const handleAddRow = () => {
+  formData.value.productionReportingDetailList.push({
+    productionProcessesId: "",
+    productionProcessesName: "",
+    name: "",
+    quantity: "",
+  });
+};
+
+const getDict = () => {
+  proxy
+    .post("/productionTask/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      columns.value = res.data.rows.map((item) => {
+        return {
+          ...item,
+          text: item.code,
+          value: item.id,
+        };
+      });
+    });
+
+  proxy
+    .post("/productionProcesses/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      columnsOne.value = res.data.rows.map((item) => {
+        return {
+          ...item,
+          text: item.name,
+          value: item.id,
+        };
+      });
+    });
+};
+
+const getDetails = (id) => {
+  proxy.post("/productionReporting/detail", { id }).then((res) => {
+    res.data.productionReportingDetailList = [
+      ...res.data.productionReportingDetailVoList,
+    ];
+    formData.value = res.data;
+  });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.code = selectedOptions[0].text;
+  formData.value.productionTaskId = selectedOptions[0].value;
+  formData.value.productName = selectedOptions[0].productName;
+  formData.value.quantity = selectedOptions[0].quantity;
+  formData.value.personLiableName = selectedOptions[0].personLiableName;
+  formData.value.dueDate = selectedOptions[0].dueDate;
+  typeModal.value = false;
+};
+
+const onConfirmOne = ({ selectedOptions }) => {
+  formData.value.productionReportingDetailList[
+    selectIndex.value
+  ].productionProcessesId = selectedOptions[0].value;
+  formData.value.productionReportingDetailList[
+    selectIndex.value
+  ].productionProcessesName = selectedOptions[0].text;
+  typeModalOne.value = false;
+};
+
+const handleSelect = (index) => {
+  selectIndex.value = index;
+  typeModalOne.value = true;
+};
+
+const handleDel = (index) => {
+  formData.value.productionReportingDetailList.splice(index, 1);
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  if (!formData.value.productionReportingDetailList.length > 0)
+    return showFailToast("请添加明细!");
+  proxy.post("/productionReporting/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("报工成功");
+        proxy.$router.push("/main/reportWork");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDetails(route.query.id);
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 15px;
+  justify-content: space-between;
+  align-items: center;
+  color: #999999;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 121 - 0
src/views/MES/produceManage/reportWork/details.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="form" style="padding-bottom: 60px">
+    <van-nav-bar
+      title="工单管理"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+
+    <div>
+      <common-top :data="formData" :config="topConfig"> </common-top>
+      <div style="line-height: 32px; color: #999999; padding: 0 15px">
+        生产任务
+      </div>
+      <common-body :data="formData.productionTaskList" :config="bodyConfig">
+      </common-body>
+      <!-- <van-form label-align="top">
+        <div v-for="(item, index) in 3" :key="index" style="margin-top: 10px">
+          <van-field v-model="formData.productName" readonly label="计划日期" />
+          <van-field v-model="formData.productName" readonly label="计划数量" />
+          <van-field v-model="formData.productName" readonly label="计划状态" />
+        </div>
+      </van-form> -->
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { useRoute } from "vue-router";
+
+import commonTop from "@/components/MES/common-top.vue";
+import commonBody from "@/components/MES/common-body.vue";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+
+const formData = ref({
+  source: "",
+  sourceName: "",
+  productId: "1",
+  productName: "",
+  quantity: null,
+  remarks: "",
+});
+
+const topConfig = ref([
+  {
+    label: "计划时间",
+    prop: "time",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+  {
+    label: "计划数量",
+    prop: "quantity",
+  },
+  {
+    label: "计划状态",
+    prop: "statusName",
+  },
+]);
+
+const bodyConfig = ref([
+  {
+    label: "任务数量",
+    prop: "quantity",
+  },
+  {
+    label: "负责人",
+    prop: "personLiableName",
+  },
+  {
+    label: "完成状态",
+    prop: "status",
+  },
+]);
+
+const getDetails = (id) => {
+  proxy.post("/productionPlan/detail", { id }).then((res) => {
+    res.data.time = res.data.startDate + " ~ " + res.data.stopDate;
+    // res.data.productionTaskList=
+    let status = res.data.status;
+    res.data.statusName =
+      status == 0
+        ? "未开始"
+        : status == 1
+        ? "进行中"
+        : status == 2
+        ? "完成"
+        : "";
+
+    formData.value = res.data;
+  });
+};
+
+const onClickLeft = () => history.back();
+
+onMounted(() => {
+  getDetails(route.query.id);
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 114 - 0
src/views/MES/produceManage/reportWork/index.vue

@@ -0,0 +1,114 @@
+<template>
+  <van-nav-bar
+    title="生产报工"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+    @click-right="onClickRight"
+  >
+    <template #right> 报工 </template>
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <commonList
+          :data="listData"
+          @onClick="toDtl"
+          :config="listConfig"
+        ></commonList>
+      </van-list>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  type: "1",
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "任务编码",
+    prop: "code",
+  },
+  {
+    label: "报工时间",
+    prop: "createTime",
+  },
+  {
+    label: "操作人",
+    prop: "operatorName",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/reportWorkAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "reportWorkAdd",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/productionReporting/page", req.value)
+    .then((res) => {
+      console.log(req.value);
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 16 - 10
src/views/MES/workOrder/details.vue

@@ -13,14 +13,7 @@
       <div style="line-height: 32px; color: #999999; padding: 0 15px">
         生产计划
       </div>
-      <common-body
-        :data="[
-          { time: '2022-01-09', quantity: '未完成', productName: '500' },
-          { time: '2022-01-09', quantity: '未完成', productName: '500' },
-          { time: '2022-01-09', quantity: '未完成', productName: '500' },
-        ]"
-        :config="bodyConfig"
-      >
+      <common-body :data="formData.productionPlans" :config="bodyConfig">
       </common-body>
       <!-- <van-form label-align="top">
         <div v-for="(item, index) in 3" :key="index" style="margin-top: 10px">
@@ -78,16 +71,29 @@ const bodyConfig = ref([
   },
   {
     label: "计划数量",
-    prop: "productName",
+    prop: "quantity",
   },
   {
     label: "计划状态",
-    prop: "quantity",
+    prop: "statusName",
   },
 ]);
 
 const getDetails = (id) => {
   proxy.post("/workOrder/detail", { id }).then((res) => {
+    res.data.productionPlans = res.data.productionPlans.map((x) => ({
+      ...x,
+      time: x.startDate + " ~ " + x.stopDate,
+      statusName:
+        x.status == 0
+          ? "未开始"
+          : x.status == 1
+          ? "进行中"
+          : x.status == 2
+          ? "完成"
+          : "",
+    }));
+
     formData.value = res.data;
   });
 };

+ 5 - 9
src/views/purchase-sales/inbound-outbound/waitInbound/add.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="form">
     <van-nav-bar
-      title="手动入库"
+      title="入库"
       left-text="返回"
       left-arrow
       @click-left="onClickLeft"
@@ -9,14 +9,10 @@
     </van-nav-bar>
     <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
       <van-cell-group inset>
-        <van-field v-model="formData.warehouseName" readonly label="数据来源" />
-        <van-field v-model="formData.warehouseName" readonly label="单号" />
-        <van-field v-model="formData.warehouseName" readonly label="物品名称" />
-        <van-field
-          v-model="formData.warehouseName"
-          readonly
-          label="待入库数量"
-        />
+        <van-field v-model="formData.businessType" readonly label="数据来源" />
+        <van-field v-model="formData.businessCode" readonly label="单号" />
+        <van-field v-model="formData.productName" readonly label="物品名称" />
+        <van-field v-model="formData.quantity" readonly label="待入库数量" />
       </van-cell-group>
       <div style="padding: 5px 0 5px 15px; color: #999999">本次入库</div>
       <van-cell-group inset>

+ 9 - 11
src/views/purchase-sales/inbound-outbound/waitInbound/index.vue

@@ -21,9 +21,7 @@
           @onClick="toDtl"
           :config="listConfig"
         ></commonList>
-        <div>
-          <van-button type="success" @click="toDtl">成功按钮</van-button>
-        </div>
+        <div></div>
       </van-list>
     </div>
   </van-pull-refresh>
@@ -46,15 +44,15 @@ const listData = ref([]);
 const listConfig = ref([
   {
     label: "数据来源",
-    prop: "warehouseName",
+    prop: "businessType",
   },
   {
-    label: "入库时间",
-    prop: "createTime",
+    label: "物品名称",
+    prop: "productName",
   },
   {
-    label: "操作人",
-    prop: "userName",
+    label: "代办数量",
+    prop: "quantity",
   },
 ]);
 const onRefresh = () => {
@@ -75,9 +73,9 @@ const onClickRight = () => {
 const toDtl = (row) => {
   proxy.$router.push({
     path: "waitInboundAdd",
-    // query: {
-    //   id: row.id,
-    // },
+    query: {
+      id: row.id,
+    },
   });
 };