Răsfoiți Sursa

Merge remote-tracking branch 'origin/master'

guoyujia 11 luni în urmă
părinte
comite
d400731e8b

+ 8 - 0
src/api/business/daywork.js

@@ -30,6 +30,14 @@ export function processesForOutsource(query) {
 	})
 }
 
+export function processesForOutsourceByFirst(query) {
+	return request({
+		url: baseUrl + '/business/productionDaywork/processesForOutsourceByFirst',
+		method: 'get',
+		params: query
+	})
+}
+
 /**
  * 查询当前报工工序
  * 此方法在非本序废品页面使用

+ 31 - 0
src/api/business/outsourcedOrder.js

@@ -45,6 +45,14 @@ export function submitDetails(data) {
 		data: data
 	})
 }
+
+export function submitDetailsOnFirst(data) {
+	return request({
+		url: baseUrl + '/business/outsource/submitDetailsOnFirst',
+		method: 'post',
+		data: data
+	})
+}
 export function processesForOutsource(data) {
 	return request({
 		url: baseUrl + '/business/outsource/processesForOutsource',
@@ -100,3 +108,26 @@ export function getCarrierInfo(data) {
 		data: data
 	})
 }
+
+export function getProductionPlan(query) {
+	return request({
+		url: baseUrl + '/business/outsource/getProductionPlan',
+		method: 'get',
+		params: query
+	})
+}
+
+export function getLotByProductionPlanSub(data) {
+	return request({
+		url: baseUrl + '/business/outsource/getLotByProductionPlanSub',
+		method: 'post',
+		data: data
+	})
+}
+
+export function getFirstOrder(id) {
+	return request({
+		url: baseUrl + '/business/outsource/getFirst/' + id,
+		method: 'get'
+	})
+}

+ 9 - 0
src/api/business/p2.js

@@ -78,3 +78,12 @@ export function delProductionPlan(id) {
     method: 'delete'
   })
 }
+
+// 获取炉号
+export function getFurnaceNoInfo(params) {
+  return request({
+    url: baseUrl + '/business/furnaceNoInfo/getFurnaceNoInfo',
+    method: 'get',
+    params: params
+  })
+}

+ 129 - 95
src/layout/components/TagsView/index.vue

@@ -1,7 +1,11 @@
 <template>
   <div id="tags-view-container" class="tags-view-container">
     <div class="tags-views-container-bg"></div>
-    <scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll">
+    <scroll-pane
+      ref="scrollPaneRef"
+      class="tags-view-wrapper"
+      @scroll="handleScroll"
+    >
       <router-link
         v-for="tag in visitedViews"
         :key="tag.path"
@@ -15,68 +19,88 @@
       >
         {{ tag.title }}
         <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
-          <close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
+          <close
+            class="el-icon-close"
+            style="width: 1em; height: 1em; vertical-align: middle"
+          />
         </span>
       </router-link>
     </scroll-pane>
-    <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
-      <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em" /> 刷新页面</li>
-      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em" /> 关闭当前</li>
-      <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em" /> 关闭其他</li>
-      <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em" /> 关闭左侧</li>
-      <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em" /> 关闭右侧</li>
-      <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em" /> 全部关闭</li>
+    <ul
+      v-show="visible"
+      :style="{ left: left + 'px', top: top + 'px' }"
+      class="contextmenu"
+    >
+      <li @click="refreshSelectedTag(selectedTag)">
+        <refresh-right style="width: 1em; height: 1em" /> 刷新页面
+      </li>
+      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">
+        <close style="width: 1em; height: 1em" /> 关闭当前
+      </li>
+      <li @click="closeOthersTags">
+        <circle-close style="width: 1em; height: 1em" /> 关闭其他
+      </li>
+      <li v-if="!isFirstView()" @click="closeLeftTags">
+        <back style="width: 1em; height: 1em" /> 关闭左侧
+      </li>
+      <li v-if="!isLastView()" @click="closeRightTags">
+        <right style="width: 1em; height: 1em" /> 关闭右侧
+      </li>
+      <li @click="closeAllTags(selectedTag)">
+        <circle-close style="width: 1em; height: 1em" /> 全部关闭
+      </li>
     </ul>
   </div>
 </template>
 
 <script setup>
-import ScrollPane from './ScrollPane'
-import { getNormalPath } from '@/utils/ruoyi'
-import useTagsViewStore from '@/store/modules/tagsView'
-import useSettingsStore from '@/store/modules/settings'
-import usePermissionStore from '@/store/modules/permission'
+import ScrollPane from "./ScrollPane";
+import { getNormalPath } from "@/utils/ruoyi";
+import useTagsViewStore from "@/store/modules/tagsView";
+import useSettingsStore from "@/store/modules/settings";
+import usePermissionStore from "@/store/modules/permission";
+import lotStore from "@/store/modules/lot";
 
-const visible = ref(false)
-const top = ref(0)
-const left = ref(0)
-const selectedTag = ref({})
-const affixTags = ref([])
-const scrollPaneRef = ref(null)
+const visible = ref(false);
+const top = ref(0);
+const left = ref(0);
+const selectedTag = ref({});
+const affixTags = ref([]);
+const scrollPaneRef = ref(null);
 
-const { proxy } = getCurrentInstance()
-const route = useRoute()
-const router = useRouter()
+const { proxy } = getCurrentInstance();
+const route = useRoute();
+const router = useRouter();
 
-const visitedViews = computed(() => useTagsViewStore().visitedViews)
-const routes = computed(() => usePermissionStore().routes)
-const theme = computed(() => useSettingsStore().theme)
+const visitedViews = computed(() => useTagsViewStore().visitedViews);
+const routes = computed(() => usePermissionStore().routes);
+const theme = computed(() => useSettingsStore().theme);
 
 watch(route, () => {
-  addTags()
-  moveToCurrentTag()
-})
+  addTags();
+  moveToCurrentTag();
+});
 watch(visible, (value) => {
   if (value) {
-    document.body.addEventListener('click', closeMenu)
+    document.body.addEventListener("click", closeMenu);
   } else {
-    document.body.removeEventListener('click', closeMenu)
+    document.body.removeEventListener("click", closeMenu);
   }
-})
+});
 onMounted(() => {
-  initTags()
-  addTags()
-})
+  initTags();
+  addTags();
+});
 
 function isActive(r) {
-  return r.path === route.path
+  return r.path === route.path;
 }
 function activeStyle(tag) {
-  if (!isActive(tag)) return {}
+  if (!isActive(tag)) return {};
   return {
-    'background-color': '#fff',
-    'border-color': '#496bdc'
-  }
+    "background-color": "#fff",
+    "border-color": "#496bdc",
+  };
   /*
   // 原程序,可以通过设置进行颜色调整
   return {
@@ -86,154 +110,164 @@ function activeStyle(tag) {
   */
 }
 function isAffix(tag) {
-  return tag.meta && tag.meta.affix
+  return tag.meta && tag.meta.affix;
 }
 function isFirstView() {
   try {
-    return selectedTag.value.fullPath === visitedViews.value[1].fullPath || selectedTag.value.fullPath === '/index'
+    return (
+      selectedTag.value.fullPath === visitedViews.value[1].fullPath ||
+      selectedTag.value.fullPath === "/index"
+    );
   } catch (err) {
-    return false
+    return false;
   }
 }
 function isLastView() {
   try {
-    return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath
+    return (
+      selectedTag.value.fullPath ===
+      visitedViews.value[visitedViews.value.length - 1].fullPath
+    );
   } catch (err) {
-    return false
+    return false;
   }
 }
-function filterAffixTags(routes, basePath = '') {
-  let tags = []
+function filterAffixTags(routes, basePath = "") {
+  let tags = [];
   routes.forEach((route) => {
     if (route.meta && route.meta.affix) {
-      const tagPath = getNormalPath(basePath + '/' + route.path)
+      const tagPath = getNormalPath(basePath + "/" + route.path);
       tags.push({
         fullPath: tagPath,
         path: tagPath,
         name: route.name,
-        meta: { ...route.meta }
-      })
+        meta: { ...route.meta },
+      });
     }
     if (route.children) {
-      const tempTags = filterAffixTags(route.children, route.path)
+      const tempTags = filterAffixTags(route.children, route.path);
       if (tempTags.length >= 1) {
-        tags = [...tags, ...tempTags]
+        tags = [...tags, ...tempTags];
       }
     }
-  })
-  return tags
+  });
+  return tags;
 }
 function initTags() {
-  const res = filterAffixTags(routes.value)
-  affixTags.value = res
+  const res = filterAffixTags(routes.value);
+  affixTags.value = res;
   for (const tag of res) {
     // Must have tag name
     if (tag.name) {
-      useTagsViewStore().addVisitedView(tag)
+      useTagsViewStore().addVisitedView(tag);
     }
   }
 }
 function addTags() {
-  const { name } = route
+  const { name } = route;
   if (name) {
-    useTagsViewStore().addView(route)
+    useTagsViewStore().addView(route);
     if (route.meta.link) {
-      useTagsViewStore().addIframeView(route)
+      useTagsViewStore().addIframeView(route);
     }
   }
-  return false
+  return false;
 }
 function moveToCurrentTag() {
   nextTick(() => {
     for (const r of visitedViews.value) {
       if (r.path === route.path) {
-        scrollPaneRef.value.moveToTarget(r)
+        scrollPaneRef.value.moveToTarget(r);
         // when query is different then update
         if (r.fullPath !== route.fullPath) {
-          useTagsViewStore().updateVisitedView(route)
+          useTagsViewStore().updateVisitedView(route);
         }
       }
     }
-  })
+  });
 }
 function refreshSelectedTag(view) {
-  proxy.$tab.refreshPage(view)
+  proxy.$tab.refreshPage(view);
   if (route.meta.link) {
-    useTagsViewStore().delIframeView(route)
+    useTagsViewStore().delIframeView(route);
   }
 }
 function closeSelectedTag(view) {
+  //关闭批次查询页面时清空批次查询页面store
+  if ((view.fullPath = "/Production/lot/:productionPlanNo/:lineNumber")) {
+    lotStore().setlotQueryParams(null);
+  }
   proxy.$tab.closePage(view).then(({ visitedViews }) => {
     if (isActive(view)) {
-      toLastView(visitedViews, view)
+      toLastView(visitedViews, view);
     }
-  })
+  });
 }
 function closeRightTags() {
   proxy.$tab.closeRightPage(selectedTag.value).then((visitedViews) => {
     if (!visitedViews.find((i) => i.fullPath === route.fullPath)) {
-      toLastView(visitedViews)
+      toLastView(visitedViews);
     }
-  })
+  });
 }
 function closeLeftTags() {
   proxy.$tab.closeLeftPage(selectedTag.value).then((visitedViews) => {
     if (!visitedViews.find((i) => i.fullPath === route.fullPath)) {
-      toLastView(visitedViews)
+      toLastView(visitedViews);
     }
-  })
+  });
 }
 function closeOthersTags() {
-  router.push(selectedTag.value).catch(() => {})
+  router.push(selectedTag.value).catch(() => {});
   proxy.$tab.closeOtherPage(selectedTag.value).then(() => {
-    moveToCurrentTag()
-  })
+    moveToCurrentTag();
+  });
 }
 function closeAllTags(view) {
   proxy.$tab.closeAllPage().then(({ visitedViews }) => {
     if (affixTags.value.some((tag) => tag.path === route.path)) {
-      return
+      return;
     }
-    toLastView(visitedViews, view)
-  })
+    toLastView(visitedViews, view);
+  });
 }
 function toLastView(visitedViews, view) {
-  const latestView = visitedViews.slice(-1)[0]
+  const latestView = visitedViews.slice(-1)[0];
   if (latestView) {
-    router.push(latestView.fullPath)
+    router.push(latestView.fullPath);
   } else {
     // now the default is to redirect to the home page if there is no tags-view,
     // you can adjust it according to your needs.
-    if (view.name === 'Dashboard') {
+    if (view.name === "Dashboard") {
       // to reload home page
-      router.replace({ path: '/redirect' + view.fullPath })
+      router.replace({ path: "/redirect" + view.fullPath });
     } else {
-      router.push('/')
+      router.push("/");
     }
   }
 }
 function openMenu(tag, e) {
-  const menuMinWidth = 105
-  const offsetLeft = proxy.$el.getBoundingClientRect().left // container margin left
-  const offsetWidth = proxy.$el.offsetWidth // container width
-  const maxLeft = offsetWidth - menuMinWidth // left boundary
-  const l = e.clientX - offsetLeft + 15 // 15: margin right
+  const menuMinWidth = 105;
+  const offsetLeft = proxy.$el.getBoundingClientRect().left; // container margin left
+  const offsetWidth = proxy.$el.offsetWidth; // container width
+  const maxLeft = offsetWidth - menuMinWidth; // left boundary
+  const l = e.clientX - offsetLeft + 15; // 15: margin right
 
   if (l > maxLeft) {
-    left.value = maxLeft
+    left.value = maxLeft;
   } else {
-    left.value = l
+    left.value = l;
   }
 
-  top.value = 34 //e.clientY
-  visible.value = true
-  selectedTag.value = tag
+  top.value = 34; //e.clientY
+  visible.value = true;
+  selectedTag.value = tag;
 }
 function closeMenu() {
-  visible.value = false
+  visible.value = false;
 }
 function handleScroll() {
-  closeMenu()
+  closeMenu();
 }
 </script>
 

+ 13 - 0
src/store/modules/lot.js

@@ -0,0 +1,13 @@
+
+const lotStore = defineStore('lot', {
+  state: () => ({
+      lotQueryParams:null
+  }),
+  actions: {
+    setlotQueryParams(value) { 
+      this.lotQueryParams = value;
+    }
+  }
+})
+
+export default lotStore

+ 136 - 0
src/views/business/firstOutsource/DialogFurnaceNoInfo.vue

@@ -0,0 +1,136 @@
+<template>
+  <el-dialog title="选择炉号" v-model="visible" width="800px" height="400px" @close="close" append-to-body draggable>
+    <!-- <el-form ref="dialogForm" :model="queryParams" :inline="true" style="padding-top: 16px">
+      <el-form-item label="炉号:" prop="code" label-width="104">
+        <el-input v-model.trim="queryParams.processAlias" type="text" @keydown.enter.prevent style="width: 160px"
+          placeholder="请输入关键字" :clearable="true" @keyup.enter="handleSearch" />
+      </el-form-item>
+      <el-form-item label-width="20px">
+        <el-button type="info" icon="Search" @click="handleSearch">搜索</el-button>
+      </el-form-item>
+    </el-form> -->
+
+    <el-table ref="dialogTable" :data="productList" size="small" v-loading="loading" border height="370px"
+      @selection-change="handleSelectionChange">
+      <!-- <el-table-column type="selection" width="40" align="center" /> -->
+      <el-table-column label="序号" width="56" align="center" type="index" />
+      <el-table-column label="材料厂家" align="center" prop="factory" />
+      <el-table-column label="炉号" align="center" prop="furnaceNumber" />
+      <el-table-column label="牌号" align="center" prop="brandNumber" />
+      <el-table-column label="规格" align="center" prop="spec" />
+      <el-table-column label="材料直径" align="center" prop="diameter" />
+      <el-table-column label="形状" align="center" prop="shape" />
+      <el-table-column label="来料日期" align="center" prop="incomingDate" />
+      <el-table-column label="原料编码" align="center" prop="rawMaterialCode" />
+      <el-table-column label="操作" align="center" prop="rawMaterialCode">
+        <template #default="scope">
+          <el-button type="success" icon="finished" circle @click="handleSingleSelected(scope.row)" />
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <!-- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize" @pagination="getList" /> -->
+    <!-- <template #footer>
+      <div class="dialog-footer">
+        <el-button type="primary" icon="Check" :disabled="selections.length === 0" @click="handleMultipleSelected">
+          确 定
+        </el-button>
+        <el-button type="danger" icon="Close" @click="close">取 消</el-button>
+      </div>
+    </template> -->
+  </el-dialog>
+</template>
+<script setup>
+// import { carrierForOutsource } from "@/api/business/outsourcedOrder";
+import { getFurnaceNoInfo } from '@/api/business/p2'
+const { proxy } = getCurrentInstance();
+/** 字典数组区 */
+const { process_status } = proxy.useDict("process_status");
+/** 工序变量 */
+const total = ref(0);
+const props = defineProps({
+  singleSelected: {
+    type: Function,
+    default: null,
+  },
+  multipleSelected: {
+    type: Function,
+    default: null,
+  },
+  supplierId: {
+    type: String,
+    default: "",
+  },
+});
+
+const { multipleSelected, supplierId, singleSelected } = toRefs(props);
+const productList = ref([]);
+const visible = ref(false);
+const lotId = ref({});
+const loading = ref(false);
+const queryParams = ref({
+});
+const details = ref([])
+const selections = ref([]);
+
+/**
+ * 对话框打开 事件
+ */
+function open(data) {
+  queryParams.value = data.queryParams
+  details.value = data.details
+  visible.value = true;
+  getList();
+}
+
+/**
+ * 对话框关闭 事件
+ */
+function close() {
+  // proxy.$refs.dialogForm.resetFields();
+  proxy.$refs.dialogTable.clearSelection();
+  visible.value = false;
+}
+
+/**
+ * 加载数据
+ */
+function getList() {
+  loading.value = true;
+  getFurnaceNoInfo(queryParams.value).then((res) => {
+    productList.value = res.data;
+    loading.value = false;
+  });
+}
+
+/**
+ * 列表checkbox列选择 事件
+ */
+function handleSelectionChange(selection) {
+  selections.value = selection;
+}
+
+/**  搜索 事件 */
+function handleSearch() {
+  getList();
+}
+/** 多选事件 */
+function handleMultipleSelected() {
+  if (multipleSelected.value) {
+    multipleSelected.value(selections.value, lotId.value);
+  }
+  close();
+}
+
+function handleSingleSelected(row) {
+  if (singleSelected.value) {
+    singleSelected.value(details.value, row);
+  }
+  close();
+}
+
+defineExpose({
+  open,
+});
+</script>

+ 56 - 0
src/views/business/firstOutsource/DialogOutsourcedRecords.vue

@@ -0,0 +1,56 @@
+<template>
+	<el-dialog title="历史记录" v-model="visible" width="800px" height="400px" @close="close" append-to-body draggable  style="font-size: 14px;">
+		<el-table ref="dialogTable" :data="recordsList" size="small" v-loading="loading" border height="500px" header-row-class-name="list-header-row" row-class-name="list-row" >
+			<el-table-column type="index" label="序号" width="50" align="center" />
+			<el-table-column label="记录" align="center" prop="records" />
+		</el-table>
+	</el-dialog>
+</template>
+<script setup>
+import { listOutsourcedRecords } from "@/api/business/outsourcedRecords";
+/** 历史记录变量 */
+const recordsList = ref([])
+const visible = ref(false)
+const loading = ref(false)
+const data = reactive({
+	queryParams: {
+		masterId:null
+	}
+})
+const { queryParams } = toRefs(data)
+
+/**
+ * 对话框打开 事件
+ */
+function open(data) {
+	visible.value = true
+	queryParams.value.masterId = data
+	getList()
+}
+
+/**
+ * 对话框关闭 事件
+ */
+function close() {
+	visible.value = false
+}
+
+/**
+ * 加载数据
+ */
+function getList() {
+	loading.value = true
+	listOutsourcedRecords(queryParams.value).then((res) => {
+		recordsList.value = res.rows
+		loading.value = false
+	})
+}
+
+defineExpose({
+	open
+})
+</script>
+<style scoped>
+.el-table--small {
+    font-size: 14px;
+}</style>

+ 122 - 0
src/views/business/firstOutsource/DialogProcesses.vue

@@ -0,0 +1,122 @@
+<template>
+  <el-dialog title="添加工序" v-model="visible" width="800px" height="400px" @close="close" append-to-body draggable>
+    <el-form ref="dialogForm" :model="queryParams" :inline="true" style="padding-top: 16px">
+      <el-form-item label="工序名称:" prop="processAlias" label-width="104">
+        <el-input v-model.trim="queryParams.keyword" type="text" @keydown.enter.prevent style="width: 160px"
+          placeholder="请输入关键字" :clearable="true" @keyup.enter="handleSearch" />
+      </el-form-item>
+      <el-form-item label-width="20px">
+        <el-button type="info" icon="Search" @click="handleSearch">搜索</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table ref="dialogTable" :data="productList" size="small" v-loading="loading" border height="370px"
+      @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="40" align="center" />
+      <el-table-column label="序号" width="56" align="center" type="index" />
+      <el-table-column label="工序名称" align="center" prop="processAlias" />
+    </el-table>
+    <!-- 分页 -->
+    <!-- <pagination
+      v-show="total > 0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    /> -->
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button type="primary" icon="Check" :disabled="selections.length === 0" @click="handleMultipleSelected">
+          确 定
+        </el-button>
+        <el-button type="danger" icon="Close" @click="close">取 消</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+<script setup>
+import { processesForOutsourceByFirst } from "@/api/business/daywork";
+const { proxy } = getCurrentInstance();
+/** 字典数组区 */
+const { process_status } = proxy.useDict("process_status");
+/** 工序变量 */
+const total = ref(0);
+const props = defineProps({
+  multipleSelected: {
+    type: Function,
+    default: null,
+  },
+  supplierId: {
+    type: String,
+    default: "",
+  },
+});
+
+const { multipleSelected, supplierId } = toRefs(props);
+const productList = ref([]);
+const visible = ref(false);
+const loading = ref(false);
+const queryParams = ref({
+  pageNum: 1,
+  pageSize: 10,
+});
+const selections = ref([]);
+
+/**
+ * 对话框打开 事件
+ */
+function open(data) {
+  console.log(data)
+  queryParams.value.id = data.lotId
+  queryParams.value.outsourceDetailId = data.id ? data.id : 0
+  queryParams.value.pageNum = 1;
+  queryParams.value.pageSize = 10;
+  visible.value = true;
+  getList();
+}
+
+/**
+ * 对话框关闭 事件
+ */
+function close() {
+  proxy.$refs.dialogForm.resetFields();
+  proxy.$refs.dialogTable.clearSelection();
+  queryParams.value.pageNum = 1;
+  visible.value = false;
+}
+
+/**
+ * 加载数据
+ */
+function getList() {
+  loading.value = true;
+  processesForOutsourceByFirst(queryParams.value).then((res) => {
+    productList.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+  });
+}
+
+/**
+ * 列表checkbox列选择 事件
+ */
+function handleSelectionChange(selection) {
+  selections.value = selection;
+}
+
+/**  搜索 事件 */
+function handleSearch() {
+  getList();
+}
+/** 多选事件 */
+function handleMultipleSelected() {
+  if (multipleSelected.value) {
+    multipleSelected.value(selections.value);
+  }
+  close();
+}
+
+defineExpose({
+  open,
+});
+</script>

+ 130 - 0
src/views/business/firstOutsource/DialogProducts.vue

@@ -0,0 +1,130 @@
+<template>
+  <el-dialog title="添加产品" v-model="visible" width="800px" height="400px" @close="close" append-to-body draggable>
+    <el-form ref="dialogForm" :model="queryParams" :inline="true" style="padding-top: 16px">
+      <el-form-item label="关键字:" prop="productDescription" label-width="104">
+        <el-input v-model.trim="queryParams.keyword" type="text" @keydown.enter.prevent style="width: 170px"
+          placeholder="请输入批号或产品描述" :clearable="true" @keyup.enter="handleSearch" />
+      </el-form-item>
+      <el-form-item v-if="supplierId !== '' && supplierId !== '0'" label="只看外协商配置的产品:" prop="isSupplierProducts">
+        <el-switch v-model="queryParams.isSupplierProducts" active-text="是" :active-value="1" inactive-text="否"
+          :inactive-value="0" @change="handleSearch" />
+      </el-form-item>
+      <el-form-item label-width="20px">
+        <el-button type="info" icon="Search" @click="handleSearch">搜索</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table ref="dialogTable" :data="productList" size="small" v-loading="loading" border height="370px"
+      @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="40" align="center" />
+      <el-table-column type="index" label="行号" width="50" align="center" />
+      <el-table-column label="生产计划单号" align="center" prop="productionPlanNo" width="96" />
+      <el-table-column label="产品描述" align="center" prop="productDescription" />
+      <el-table-column label="批数" align="center" prop="lotTotalNumber" width="96" />
+      <el-table-column label="单批量" align="center" prop="oneLotQuantity" width="96" />
+    </el-table>
+    <!-- 分页 -->
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button type="primary" icon="Check" :disabled="selections.length === 0" @click="handleMultipleSelected">
+          确 定
+        </el-button>
+        <el-button type="danger" icon="Close" @click="close">取 消</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+<script setup>
+import { getProductionPlan } from "@/api/business/outsourcedOrder";
+const { proxy } = getCurrentInstance();
+/** 字典数组区 */
+const { process_status } = proxy.useDict("process_status");
+/** 工序变量 */
+const total = ref(0);
+const props = defineProps({
+  multipleSelected: {
+    type: Function,
+    default: null,
+  },
+  supplierId: {
+    type: String,
+    default: "",
+  },
+});
+
+const { multipleSelected, supplierId } = toRefs(props);
+const productList = ref([]);
+const visible = ref(false);
+const loading = ref(false);
+const queryParams = ref({
+  existingDayworkIds: [],
+  deptCode: "170000",
+  // 是否看所有产品【0:看全部产品,1:只看该外协商配置的产品】
+  isSupplierProducts: 0,
+  supplierId: "",
+  productDescription: "",
+  pageNum: 1,
+  pageSize: 10,
+});
+const selections = ref([]);
+
+/**
+ * 对话框打开 事件
+ */
+function open() {
+  visible.value = true;
+  // queryParams.value.existingDayworkIds = existingDayworkIds;
+  getList();
+}
+
+/**
+ * 对话框关闭 事件
+ */
+function close() {
+  proxy.$refs.dialogForm.resetFields();
+  proxy.$refs.dialogTable.clearSelection();
+  queryParams.value.pageNum = 1;
+  visible.value = false;
+}
+/**
+ * 加载数据
+ */
+function getList() {
+  loading.value = true;
+  if (queryParams.value.isSupplierProducts === 0 || queryParams.value.isSupplierProducts == null) {
+    queryParams.value.supplierId = null;
+  } else {
+    queryParams.value.supplierId = props.supplierId;
+  }
+  getProductionPlan(queryParams.value).then((res) => {
+    productList.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+  });
+}
+
+/**
+ * 列表checkbox列选择 事件
+ */
+function handleSelectionChange(selection) {
+  selections.value = selection;
+}
+
+/**  搜索 事件 */
+function handleSearch() {
+  getList();
+}
+/** 多选事件 */
+function handleMultipleSelected() {
+  if (multipleSelected.value) {
+    multipleSelected.value(selections.value);
+  }
+  close();
+}
+
+defineExpose({
+  open,
+});
+</script>

+ 165 - 0
src/views/business/firstOutsource/DialogSuppliers.vue

@@ -0,0 +1,165 @@
+<template>
+  <el-dialog
+    title="添加外协商"
+    v-model="visible"
+    width="800px"
+    height="400px"
+    @close="close"
+    append-to-body
+    draggable
+  >
+    <el-form
+      ref="dialogForm"
+      class="master-container"
+      :model="queryParams"
+      :inline="true"
+      style="align-items: center"
+    >
+      <div style="display: flex">
+        <el-form-item label="外协商名称:" prop="name">
+          <el-input
+            v-model.trim="queryParams.name"
+            type="text"
+            @keydown.enter.prevent
+            style="width: 120px"
+            placeholder="请输入关键字"
+            :clearable="true"
+            @keyup.enter="handleSearch"
+          />
+        </el-form-item>
+        <el-form-item label="助记码:" prop="name">
+          <el-input
+            v-model.trim="queryParams.mnemonicCode"
+            type="text"
+            @keydown.enter.prevent
+            style="width: 120px"
+            placeholder="请输入关键字"
+            :clearable="true"
+            @keyup.enter="handleSearch"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="info" icon="Search" @click="handleSearch"
+            >搜索</el-button
+          >
+        </el-form-item>
+      </div>
+    </el-form>
+
+    <el-table
+      ref="dialogTable"
+      :data="dataList"
+      size="small"
+      v-loading="loading"
+      border
+      height="370px"
+    >
+      <el-table-column type="index" label="行号" width="50" align="center" />
+      <el-table-column label="外协商名称" align="center" prop="name" />
+      <el-table-column
+        label="助记码"
+        align="center"
+        prop="mnemonicCode"
+        width="120"
+      />
+      <el-table-column label="操作" width="64" align="center">
+        <template #default="scope">
+          <el-button
+            type="success"
+            icon="finished"
+            circle
+            @click="handleSingleSelected(scope.row)"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </el-dialog>
+</template>
+<script setup>
+import { list } from "@/api/business/supplier";
+const { proxy } = getCurrentInstance();
+/** 字典数组区 */
+const { process_status } = proxy.useDict("process_status");
+/** 工序变量 */
+const total = ref(0);
+const props = defineProps({
+  singleSelected: {
+    type: Function,
+    default: null,
+  },
+});
+
+const { singleSelected } = toRefs(props);
+const dataList = ref([]);
+const visible = ref(false);
+const loading = ref(false);
+const queryParams = ref({
+  name: "",
+  pageNum: 1,
+  pageSize: 10,
+});
+const selections = ref([]);
+
+/**
+ * 对话框打开 事件
+ */
+function open() {
+  visible.value = true;
+  getList();
+}
+
+/**
+ * 对话框关闭 事件
+ */
+function close() {
+  proxy.$refs.dialogForm.resetFields();
+  proxy.$refs.dialogTable.clearSelection();
+  queryParams.value.pageNum = 1;
+  visible.value = false;
+}
+
+/**
+ * 加载数据
+ */
+function getList() {
+  loading.value = true;
+  queryParams.value.supplierId = props.supplierId;
+  list(queryParams.value).then((res) => {
+    dataList.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+  });
+}
+
+/**
+ * 列表checkbox列选择 事件
+ */
+function handleSelectionChange(selection) {
+  selections.value = selection;
+}
+
+/**  搜索 事件 */
+function handleSearch() {
+  getList();
+}
+
+/** 单选事件 */
+function handleSingleSelected(row) {
+  if (singleSelected.value) {
+    singleSelected.value(row);
+  }
+  close();
+}
+
+defineExpose({
+  open,
+});
+</script>

+ 669 - 0
src/views/business/firstOutsource/form.vue

@@ -0,0 +1,669 @@
+<!-- 首序外协 -->
+<template>
+  <el-drawer title="首序外协信息" :with-header="false" v-model="visible" direction="rtl" size="100%">
+    <div class="form-container column-container">
+      <div class="form-btns-container">
+        <span class="title-label">
+          <el-icon>
+            <Document />
+          </el-icon>
+          <span>外协单信息</span>
+        </span>
+
+        <el-button v-show="editStatus && form.isSubmit == 1" type="primary" icon="Download" @click="handleExport"
+          v-hasPermi="['business:outsource:export']">导出</el-button>
+        <el-button v-show="editStatus && form.isSubmit == 1" type="warning" icon="Download" @click="handlePrint"
+          v-hasPermi="['business:outsource:export']">
+          打印
+        </el-button>
+        <el-button v-if="editStatus" type="primary" icon="Finished" @click="handleSubmit">保存</el-button>
+        <el-button v-if="editStatus && form.isSubmit == 1" type="info" icon="Calendar"
+          @click="handleViewRecords">历史记录</el-button>
+        <div class="close-btn" @click="cancel">
+          <i class="fa fa-times" aria-hidden="true" />
+          <!-- <span>关闭</span> -->
+        </div>
+      </div>
+      <el-form ref="formRef" class="master-container" :model="form" v-loading="loading" :rules="rules"
+        label-width="120px">
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <el-form-item label="单据号" prop="formCode">
+              <el-input v-if="editStatus" v-model="form.formCode" disabled placeholder="系统自动生成" />
+              <span v-else>{{ form.formCode }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="表单日期" prop="formDate">
+              <el-date-picker v-if="editStatus && hasReturnReceiptDetailFlag" clearable v-model="form.formDate"
+                type="date" value-format="YYYY-MM-DD" placeholder="请选择表单日期" style="width: 100%">
+              </el-date-picker>
+              <span v-else>{{ parseTime(form.formDate, "{y}-{m}-{d}") }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="外协商名称" prop="supplierName">
+              <el-input v-if="editStatus && form.isSubmit == 0 && hasReturnReceiptDetailFlag"
+                v-model="form.supplierName" readonly placeholder="请输入外协商名称">
+                <template #append>
+                  <el-button icon="Search" @click="handleShowDialogSuppliers" />
+                </template>
+              </el-input>
+              <span v-else>{{ form.supplierName }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6" v-if="false">
+            <el-form-item label="运费单价" prop="freightPrice">
+              <el-input-number v-if="editStatus && hasReturnReceiptDetailFlag" v-model="form.freightPrice" :min="0"
+                :precision="2" controls-position="right" />
+              <span v-else>{{ form.freightPrice }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6" v-if="false">
+            <el-form-item label="运费总价" prop="freightAmount">
+              <el-input-number v-if="editStatus && hasReturnReceiptDetailFlag" v-model="form.freightAmount" :min="0"
+                :precision="2" controls-position="right" />
+              <span v-else>{{ form.freightAmount }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="送货方式" prop="deliveryMethod">
+              <el-select v-if="editStatus && hasReturnReceiptDetailFlag" v-model="form.deliveryMethod" placeholder="请选择"
+                @change="handleChangeDeliveryMethod">
+                <el-option v-for=" dict  in  deliveryMethod " :key="dict.value" :label="dict.label"
+                  :value="dict.value" />
+              </el-select>
+              <span v-else>{{ selectText(form.deliveryMethod, deliveryMethod) }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="带箱方式" prop="packagingMethod">
+              <el-select v-if="editStatus && hasReturnReceiptDetailFlag" v-model="form.packagingMethod"
+                placeholder="请选择" @change="handleChangePackagingMethod">
+                <el-option v-for=" dict  in  packagingMethod " :key="dict.value" :label="dict.label"
+                  :value="dict.value" />
+              </el-select>
+              <span v-else>{{ selectText(form.packagingMethod, packagingMethod) }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="结算方式" prop="settlementType">
+              <el-select v-if="editStatus && hasReturnReceiptDetailFlag" v-model="form.settlementType"
+                placeholder="请选择">
+                <el-option v-for=" dict  in  settlementType " :key="dict.value" :label="dict.label"
+                  :value="dict.value" />
+              </el-select>
+              <span v-else>{{ selectText(form.settlementType, settlementType) }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="备注" prop="remark">
+              <el-input v-if="editStatus" v-model.trim="form.remark" placeholder="请输入备注" />
+              <span v-else>{{ form.remark }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="总箱数" prop="remark">
+              <span>{{ totalCarriersNum }}</span>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <!-- 渲染数据区 -->
+      <div class="form-details-btns-container">
+        <el-button v-show="editStatus" type="primary" icon="Plus" @click="handleShowDialogProducts"
+          v-hasPermi="['business:outsource:add']">
+          添加外协产品明细
+        </el-button>
+        <el-button v-show="editStatus" type="primary" icon="Plus" @click="handleChoiceFurnaceNoInfo()">
+          批量选择炉号
+        </el-button>
+      </div>
+      <div class="el-table-container">
+        <div class="el-table-inner-container">
+          <el-table v-loading="loading" :data="form.details" size="small" border height="100%"
+            @selection-change="handleSelectionChange">
+            <el-table-column type="selection" align="center" width="48" />
+            <el-table-column label="行号" type="index" align="center" width="48" />
+            <el-table-column label="批次号" align="center" prop="lotCode" width="104" />
+            <el-table-column label="产品描述" align="center" prop="productDescription" width="320" />
+            <el-table-column label="产品数" align="center" width="160" prop="productNum">
+            </el-table-column>
+            <el-table-column label="箱数" align="center" prop="carrierNum" width="100">
+              <template #default="scope">
+                <el-input-number v-if="editStatus && scope.row.hasReturnReceiptDetailFlag" :min="0"
+                  v-model="scope.row.carrierNum" :controls="false" placeholder="箱数" @blur="handleCarrierNumChange" />
+                <span v-else>{{ scope.row.carrierNum }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="炉号" align="center" prop="" width="150">
+              <template #default="scope">
+                <el-button link type="primary" icon="Refresh" v-if="editStatus"
+                  @click="handleChoiceFurnaceNoInfo(scope.row)">
+                  {{ scope.row.furnaceNoInfo != null ? scope.row.furnaceNoInfo.furnaceNumber : '选择炉号' }}
+                </el-button>
+                <span v-else>{{ scope.row.furnaceNoInfo.furnaceNumber }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="外协工序" align="center" prop="processNames" width="320">
+              <template #default="scope">
+                <el-input v-if="editStatus && scope.row.hasReturnReceiptDetailFlag" v-model="scope.row.processNames"
+                  readonly placeholder="请选择工序">
+                  <template #append>
+                    <el-button icon="Search" @click="handleShowDialogProcesses(scope.row)" />
+                  </template>
+                </el-input>
+                <span v-else>{{ scope.row.processNames }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="备注" align="center" prop="remark">
+              <template #default="scope">
+                <el-input v-if="editStatus && scope.row.hasReturnReceiptDetailFlag" v-model="scope.row.remark"
+                  placeholder="备注" />
+                <span v-else>{{ scope.row.remark }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column v-if="editStatus" label="操作" align="center" class-name="small-padding fixed-width"
+              width="64">
+              <template #default="scope">
+                <el-button circle type="danger" v-if="scope.row.hasReturnReceiptDetailFlag" icon="Delete"
+                  @click="handleDelete(scope.$index)" v-hasPermi="['business:outsource:remove']" />
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+    </div>
+    <!-- 外协商选择 -->
+    <dialog-suppliers ref="dialogSuppliersRef" :single-selected="handleSingleSelectedSupplier" />
+    <!-- 投产单选择 -->
+    <dialog-products ref="dialogProductsRef" :supplier-id="form.supplierId"
+      :multiple-selected="handleMultipleSelectedProducts" />
+
+    <!-- 工序选择 -->
+    <dialog-processes ref="dialogProcessesRef" :multiple-selected="handleMultipleSelectedProcesses" />
+    <!-- 新箱号选择 -->
+    <DialogFurnaceNoInfo ref="dialogFurnaceNoInfoRef" :singleSelected="handleSingleSelectFurnaceNoInfo" />
+    <!-- 历史记录弹窗 -->
+    <dialog-outsourced-records ref="dialogOutsourcedRecordsRef" />
+    <!-- 收回明细带回 -->
+    <!-- <form-details-recycling ref="formDetailsRecyclingRef" :singleSelected="handleSingleSelectedRecycling"/> -->
+  </el-drawer>
+</template>
+<script setup>
+import {
+  getOrder,
+  getFirstOrder,
+  saveOrder,
+  carrierForOutsource,
+  submitOrder,
+  exportOutsource,
+  printOutsource,
+  submitDetails,
+  submitDetailsOnFirst,
+  getLotByProductionPlanSub
+} from "@/api/business/outsourcedOrder";
+import DialogFurnaceNoInfo from "./DialogFurnaceNoInfo";
+import dialogSuppliers from "./DialogSuppliers";
+import dialogProducts from "./DialogProducts";
+import dialogProcesses from "./DialogProcesses";
+import dialogOutsourcedRecords from "./DialogOutsourcedRecords"
+// import FormDetailsRecycling from "./detailsRecyclingForm";
+const { proxy } = getCurrentInstance();
+/** 父组件传参 */
+const props = defineProps({
+  getList: {
+    type: Function,
+    default: () => { },
+  },
+  deliveryMethod: {
+    type: Array,
+    default: [],
+  },
+  settlementType: {
+    type: Array,
+    default: [],
+  },
+  packagingMethod: {
+    type: Array,
+    default: [],
+  },
+});
+const { getList, deliveryMethod, packagingMethod, settlementType } =
+  toRefs(props);
+/** 字典数组区 */
+/** 表单抽屉 页变量 */
+
+const loading = ref(false);
+const multiple = ref(true);
+const visible = ref(false);
+const editStatus = ref(true);
+const hasReturnReceiptDetailFlag = ref(true);
+const totalCarriersNum = ref(0);
+const detailInfo = ref({});
+const loadingCarrier = ref(false);
+const carriers = ref([]);
+const webHost = import.meta.env.VITE_APP_BASE_API;
+const form = ref({});
+const selections = ref([])
+// const formatDetails = ref([])
+const currentDetail = ref({});
+const dialogFurnaceNoInfoRef = ref(null)
+const rules = {
+  supplierName: [
+    { required: true, message: "外协商名称不能为空", trigger: "change" },
+  ],
+};
+
+/***********************  方法区  ****************************/
+/** 导出按钮操作 */
+function handleExport() {
+  exportOutsource({ id: form.value.id });
+}
+
+/** 打印按钮操作 */
+function handlePrint() {
+  printOutsource({ id: form.value.id });
+}
+
+/** 打开抽屉 */
+function open(row) {
+  reset();
+  totalCarriersNum.value = 0
+  visible.value = true;
+  if (row) {
+    console.log(row)
+    detailInfo.value = row
+    form.value.id = row.id;
+    getForm();
+  } else {
+    editStatus.value = true;
+    hasReturnReceiptDetailFlag.value = true
+  }
+}
+/** 查询表单信息  */
+function getForm() {
+  loading.value = true;
+  getFirstOrder(form.value.id).then((response) => {
+    form.value = response.data;
+    //如果发出单明细里收回单,主表除了备注之外不能编辑
+    form.value.details.forEach((item) => {
+      item.hasReturnReceiptDetailFlag = true
+      if (item.returnReceiptDetailList && item.returnReceiptDetailList.length > 0) {
+        hasReturnReceiptDetailFlag.value = false
+      }
+      if (item.returnReceiptDetailList && item.returnReceiptDetailList.length > 0 && item.returnReceiptDetailList[0].status == 1) {
+        item.hasReturnReceiptDetailFlag = false
+      }
+    });
+    form.value.details.forEach((item) => {
+      item.editStatus = false;
+      totalCarriersNum.value += item.carrierNum == null ? 0 : item.carrierNum;
+    });
+
+    editStatus.value = form.value.isSubmit == 1;
+    if (!detailInfo.value.flag) {
+      editStatus.value = false
+      console.log(editStatus.value)
+    }
+    console.log(hasReturnReceiptDetailFlag.value)
+    loading.value = false;
+  });
+}
+//改变带箱方式
+function handleChangePackagingMethod() {
+  totalCarriersNum.value = 0
+  if (!editStatus) {
+    if (form.value.packagingMethod == 1 && form.value.details.length > 0) {
+      form.value.details.forEach(item => { item.newCarriers = []; item.carrierIds = []; item.carriers = carriers.value })
+    } if (form.value.packagingMethod == 0 && form.value.details.length > 0) {
+      form.value.details.forEach(item => {
+        item.carriers = carriers.value;
+        item.newCarriers = [];
+        item.carrierIds = [];
+        item.newCarriers.push(...item.originalCarrierList.map(v => ({ id: v.carrierId, code: v.carrierCode })));
+        item.carriers.push(...item.originalCarrierList.map((v) => ({ value: v.carrierId, label: v.carrierCode })));
+        item.carrierIds = item.originalCarrierList.map(info => { return info.carrierId })
+      })
+    }
+  } else {
+    form.value.details.forEach(item => {
+      console.log(item.editStatus)
+      if (item.editStatus) {
+        item.newCarriers = []; item.carrierIds = []; item.carriers = carriers.value
+      }
+    })
+  }
+  console.log(form.value.details)
+  for (let i = 0; i < form.value.details.length; i++) {
+    console.log(form.value.details)
+    totalCarriersNum.value += form.value.details[i].carrierNum == null ? 0 : form.value.details[i].carrierNum
+  }
+}
+//改变送货方式
+function handleChangeDeliveryMethod() {
+  if (form.value.deliveryMethod == 1) {
+    form.value.freightAmount = form.value.freightPrice * totalCarriersNum.value;
+  } else {
+    form.value.freightAmount = 0.0;
+  }
+
+}
+//打开历史记录弹窗
+function handleViewRecords() {
+  proxy.$refs.dialogOutsourcedRecordsRef.open(form.value.id);
+}
+
+function selectText(value, data) {
+  if (value) {
+    return data.filter((item) => item.value == value)[0].label;
+  }
+}
+
+/** 取消按钮 */
+function cancel() {
+  visible.value = false;
+  // reset();
+}
+
+const handleDelete = (index) => {
+  totalCarriersNum.value -= (form.value.details[index].carrierNum == null ? 0 : form.value.details[index].carrierNum);
+  if (form.value.deliveryMethod == 1) {
+    form.value.freightAmount = form.value.freightPrice * totalCarriersNum.value;
+  } else {
+    form.value.freightAmount = 0.0;
+  }
+  form.value.details.splice(index, 1);
+};
+
+/** 表单重置 */
+function reset() {
+  // console.log(proxy.parseTime(new Date(), "{y}-{m}-{d}"))
+  form.value = {
+    id: null,
+    tenantId: null,
+    formCode: null,
+    formDate: proxy.parseTime(new Date(), "{y}-{m}-{d}"),
+    supplierId: "0",
+    supplierName: "",
+    deliveryMethod: "0",
+    freightPrice: 0.0,
+    freightAmount: 0.0,
+    packagingMethod: "0",
+    remark: null,
+    details: [],
+    isSubmit: 0,
+    isFirstProcess: 1
+  };
+  proxy.resetForm("formRef");
+}
+/** 保存 */
+function saveFrom() {
+  if (!form.value.details || form.value.details.length == 0) {
+    proxy.$modal.msgError("请添加产品明细");
+    return;
+  }
+
+  proxy.$refs["formRef"].validate((valid) => {
+    for (const item of form.value.details) {
+      if (!item.processNames) {
+        proxy.$modal.msgError("请选择" + item.lotCode + "批次的工序");
+        return;
+      }
+    }
+
+    if (form.value.packagingMethod == 1) {
+      console.log("form.value.details", form.value.details);
+      for (const item of form.value.details) {
+        if (item.newCarriers.length == 0) {
+          proxy.$modal.msgError("请选择" + item.lotCode + "批次的新箱号");
+          return;
+        }
+      }
+    }
+    if (valid) {
+      saveOrder(form.value).then((response) => {
+        if (response.code == 200) {
+          proxy.$modal.msgSuccess("保存成功");
+          visible.value = false;
+          getList.value();
+        }
+      });
+    }
+  });
+}
+
+/** 保存并提交 */
+function submitFrom() {
+  console.log("from", form.value);
+  proxy.$modal
+    .confirm("是否确定提交,提交后不可修改,删除")
+    .then(function () {
+      return;
+    })
+    .then(() => {
+      if (!form.value.details || form.value.details.length == 0) {
+        proxy.$modal.msgError("请添加产品明细");
+        return;
+      }
+
+      proxy.$refs["formRef"].validate((valid) => {
+        for (const item of form.value.details) {
+          if (!item.processNames) {
+            proxy.$modal.msgError("请选择" + item.lotCode + "批次的工序");
+            return;
+          }
+        }
+        if (form.value.packagingMethod == 1) {
+          console.log("form.value.details", form.value.details);
+          for (const item of form.value.details) {
+            if (item.newCarriers.length == 0) {
+              proxy.$modal.msgError("请选择" + item.lotCode + "批次的新箱号");
+              return;
+            }
+          }
+        }
+        if (valid) {
+          console.log(form.value);
+          submitOrder(form.value).then((response) => {
+            proxy.$modal.msgSuccess("提交成功");
+            visible.value = false;
+            getList.value();
+          });
+        }
+      });
+    })
+    .catch(() => { });
+}
+//5.29保存
+function handleSubmit() {
+  if (form.value.isSubmit == 0) {
+    proxy.$modal
+      .confirm("是否确定保存,保存后外协商不可编辑!")
+      .then(function () {
+        return;
+      })
+      .then(() => {
+        if (!form.value.details || form.value.details.length == 0) {
+          proxy.$modal.msgError("请添加产品明细");
+          return;
+        }
+
+        proxy.$refs["formRef"].validate((valid) => {
+          for (const item of form.value.details) {
+            if (!item.processNames) {
+              proxy.$modal.msgError("请选择" + item.lotCode + "批次的工序");
+              return;
+            }
+          }
+          // 判断是否有批次没有炉号
+          const unfurnace = form.value.details.find(v => v.furnaceNoInfo == null)
+          if (unfurnace != null) {
+            proxy.$modal.msgError("请选择" + unfurnace.lotCode + "批次的炉号")
+          }
+          if (valid) {
+            console.log(form.value)
+            submitDetailsOnFirst(form.value).then((response) => {
+              proxy.$modal.msgSuccess("提交成功");
+              visible.value = false;
+              getList.value();
+            });
+          }
+        });
+      })
+  } else {
+    if (!form.value.details || form.value.details.length == 0) {
+      proxy.$modal.msgError("请添加产品明细");
+      return;
+    }
+
+    proxy.$refs["formRef"].validate((valid) => {
+      for (const item of form.value.details) {
+        if (!item.processNames) {
+          proxy.$modal.msgError("请选择" + item.lotCode + "批次的工序");
+          return;
+        }
+      }
+      if (form.value.packagingMethod == 1) {
+        console.log("form.value.details", form.value.details);
+        for (const item of form.value.details) {
+          if (item.newCarriers.length == 0) {
+            proxy.$modal.msgError("请选择" + item.lotCode + "批次的新箱号");
+            return;
+          }
+        }
+      }
+      if (valid) {
+        console.log(form.value)
+        submitDetailsOnFirst(form.value).then((response) => {
+          proxy.$modal.msgSuccess("提交成功");
+          visible.value = false;
+          getList.value();
+        });
+      }
+    });
+  }
+}
+
+/***************************** 外协商对话框相关 *****************************/
+// 打开外协商选择对话框
+const handleShowDialogSuppliers = () => {
+  proxy.$refs.dialogSuppliersRef.open();
+};
+// 外协商选择带回
+const handleSingleSelectedSupplier = (data) => {
+  console.log(data);
+  form.value.supplierId = data.id;
+  form.value.lossLimit = data.lossLimit;
+  form.value.supplierName = data.name;
+  form.value.deliveryMethod = data.deliveryMethod;
+  form.value.freightPrice = data.freightPrice;
+  form.value.settlementType = data.settlementType;
+  if (form.value.deliveryMethod == 1) {
+    form.value.freightAmount = form.value.freightPrice * totalCarriersNum.value;
+  } else {
+    form.value.freightAmount = 0.0;
+  }
+};
+/***************************** 外协收回明细相关 *****************************/
+//打开收回明细表单
+function handleDetailsRecycling() {
+  proxy.$refs.formDetailsRecyclingRef.open(row);
+}
+function handleSingleSelectedRecycling() { }
+/***************************** 产品对话框相关 *****************************/
+// 打开产品选择对话框
+const handleShowDialogProducts = () => {
+  // const dayworkIds = form.value.details.map((item) => item.dayworkId);
+  // console.log(dayworkIds);
+  proxy.$refs.dialogProductsRef.open();
+};
+// 产品选择带回
+const handleMultipleSelectedProducts = (selection) => {
+  // 获取所有批次信息
+  const requestData = {
+    planDetails: selection,
+    supplierId: form.value.supplierId,
+    supplierName: form.value.supplierName,
+    masterId: form.value.id
+  }
+  getLotByProductionPlanSub(requestData).then(res => {
+    // console.log(res)
+    if (res.code === 200) {
+      form.value.details.push(...res.data.filter(e => form.value.details.findIndex(t => t.lotId === e.lotId) < 0).map(e => ({ ...e, hasReturnReceiptDetailFlag: true })))
+    }
+  })
+
+};
+
+/***************************** 外协工序对话框相关 *****************************/
+// 打开外协工序选择对话框
+const handleShowDialogProcesses = (row) => {
+  currentDetail.value = row;
+  proxy.$refs.dialogProcessesRef.open(row);
+};
+
+// 工序选择带回
+const handleMultipleSelectedProcesses = (selection) => {
+  currentDetail.value.processes = []
+  console.log(selection);
+  const processNames = selection.sort((a, b) => a.processStepNumber - b.processStepNumber).map((item) => item.processAlias);
+  // 使用join方法将数组转换为以逗号分隔的字符串
+  let commaSeparatedString = processNames.join(",");
+  currentDetail.value.processes = [];
+  currentDetail.value.processNames = commaSeparatedString;
+  selection.forEach((item) => {
+    const newProcess = {
+      processId: item.processId,
+      processCode: item.processCode,
+      processAlias: item.processAlias,
+      processStepNumber: item.processStepNumber,
+      technologicalProcessDetailId: item.id,
+    };
+    currentDetail.value.processes.push(newProcess);
+  });
+};
+
+function handleSelectionChange(selection) {
+  selections.value = selection
+}
+
+// 选择炉号
+const handleChoiceFurnaceNoInfo = (row) => {
+  // 判断选择的产品是不是同一个
+  const changeFurnaceNoInfo = row ? [row] : selections.value;
+  let checkSame = true
+  changeFurnaceNoInfo.forEach(l => {
+    checkSame = checkSame && l.productId == changeFurnaceNoInfo[0].productId
+  })
+  console.log(checkSame)
+  if (!checkSame) {
+    proxy.$modal.msgError('请选择相同计划单批量选择炉号')
+    return
+  }
+  if (changeFurnaceNoInfo.length === 0) {
+    proxy.$modal.msgError('请选择需要变更炉号的计划单')
+    return
+  }
+  dialogFurnaceNoInfoRef.value.open({ details: changeFurnaceNoInfo, queryParams: { ...changeFurnaceNoInfo[0] } })
+}
+
+const handleSingleSelectFurnaceNoInfo = (details, info) => {
+  details.forEach(l => {
+    l.furnaceNoInfo = info
+  })
+}
+
+function handleCarrierNumChange() {
+  let sumNum = 0
+  form.value.details.forEach(v => {
+    sumNum += (v.carrierNum == null ? 0 : v.carrierNum)
+  })
+  totalCarriersNum.value = sumNum
+}
+
+/** 暴露给父组件的方法 */
+defineExpose({
+  open,
+});
+</script>

+ 261 - 0
src/views/business/firstOutsource/index.vue

@@ -0,0 +1,261 @@
+<!-- 首序外协列表 -->
+<template>
+  <div class="page-container column-container">
+    <!-- 搜索区 -->
+    <el-form class="list-search-container" :model="queryParams" ref="queryRef" :inline="true">
+      <el-form-item label="单据号:" prop="formCode">
+        <el-input v-model="queryParams.formCode" placeholder="请输入单据号" style="width: 144px" clearable
+          @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="表单日期:" prop="formDate">
+        <el-date-picker v-model="queryParams.formDate" type="date" style="width: 144px" clearable
+          value-format="YYYY-MM-DD" placeholder="请选择表单日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="外协商名称:" prop="supplierName">
+        <el-input v-model="queryParams.supplierName" placeholder="请输入关键字" style="width: 144px" clearable
+          @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="送货方式:" prop="deliveryMethod">
+        <el-select v-model="queryParams.deliveryMethod" style="width: 144px" clearable placeholder="请选择">
+          <el-option v-for="dict in delivery_method" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="带箱方式:" prop="packagingMethod">
+        <el-select v-model="queryParams.packagingMethod" style="width: 144px" clearable placeholder="请选择">
+          <el-option v-for="dict in packaging_method" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 功能按钮区 -->
+    <div class="list-btns-container">
+      <el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['business:outsource:add']">
+        新增
+      </el-button>
+      <el-button type="danger" icon="Delete" :disabled="multiple" @click="handleDelete"
+        v-hasPermi="['business:outsource:remove']">
+        删除
+      </el-button>
+      <el-button type="warning" icon="Download" :disabled="ids.length != 1" @click="handleExport"
+        v-hasPermi="['business:outsource:export']">
+        导出
+      </el-button>
+      <el-button type="warning" icon="Download" :disabled="ids.length != 1" @click="handlePrint"
+        v-hasPermi="['business:outsource:export']">
+        打印
+      </el-button>
+    </div>
+
+    <!-- 渲染数据区 -->
+    <div class="el-table-container">
+      <div class="el-table-inner-container">
+        <el-table v-loading="loading" :data="orderList" size="small" border height="100%"
+          @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="48" align="center" />
+          <el-table-column label="外协单号" align="center" prop="formCode" width="120" />
+          <el-table-column label="外协日期" align="center" prop="formDate" width="120">
+            <template #default="scope">
+              {{ parseTime(scope.row.formDate, "{y}-{m}-{d}") }}
+            </template>
+          </el-table-column>
+          <el-table-column label="外协商名称" align="center" prop="supplierName" width="320" />
+          <el-table-column label="结算方式" align="center" prop="settlementType" width="120">
+            <template #default="scope">
+              <dict-tag :options="settlement_type" :value="scope.row.settlementType" />
+            </template>
+          </el-table-column>
+          <el-table-column label="送货方式" align="center" prop="deliveryMethod" width="120">
+            <template #default="scope">
+              <dict-tag :options="delivery_method" :value="scope.row.deliveryMethod" />
+            </template>
+          </el-table-column>
+          <el-table-column label="带箱方式" align="center" prop="packagingMethod" width="120">
+            <template #default="scope">
+              <dict-tag :options="packaging_method" :value="scope.row.packagingMethod" />
+            </template>
+          </el-table-column>
+          <el-table-column label="备注" align="center" prop="remark" />
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
+            <template #default="scope">
+              <el-button v-if="scope.row.isSubmit == 1" link type="warning" icon="Edit" @click="handleUpdate(scope.row)"
+                v-hasPermi="['business:outsource:edit']">
+                编辑
+              </el-button>
+              <el-button link type="primary" icon="View" @click="handleView(scope.row)"
+                v-hasPermi="['business:outsource:query']">
+                查看
+              </el-button>
+              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
+                v-hasPermi="['business:outsource:remove']">
+                删除
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+    <!-- 分页 -->
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
+
+    <!-- 表单 -->
+    <order-form ref="orderRef" :get-list="getList" :delivery-method="delivery_method" :settlement-type="settlement_type"
+      :packaging-method="packaging_method" />
+    <!-- 打印箱码 -->
+    <div id="image-group" style="height: 0px; width: 0px">
+      <el-image v-for="item in printCarriers" :key="item.id" :src="webHost + item.qcCode" fit="cover"
+        style="width: 100mm; height: 100mm">
+      </el-image>
+    </div>
+  </div>
+</template>
+
+<script setup name="FirstOutsource">
+import {
+  listOrder,
+  delOrder,
+  exportOutsource,
+  printOutsource,
+  getCarrierInfo
+} from "@/api/business/outsourcedOrder";
+import orderForm from "./form";
+import printJS from "print-js";
+import { nextTick } from "vue";
+const { proxy } = getCurrentInstance();
+/** 字典数组区 */
+const { delivery_method } = proxy.useDict("delivery_method");
+const { settlement_type } = proxy.useDict("settlement_type");
+const { packaging_method } = proxy.useDict("packaging_method");
+
+const orderList = ref([]);
+const loading = ref(true);
+const ids = ref([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const printCarriers = ref([])
+const webHost = import.meta.env.VITE_APP_PRODUCTION_API;
+/** 查询对象 */
+const queryParams = ref({
+  pageNum: 1,
+  pageSize: 10,
+  formCode: null,
+  formDate: null,
+  startTime: null,
+  endTime: null,
+  supplierName: null,
+  deliveryMethod: null,
+  packagingMethod: null,
+  freightPrice: null,
+  freightAmount: null,
+  isFirstProcess: 1
+});
+
+/***********************  方法区  ****************************/
+
+/** 查询外协单主
+带箱方式,是整单的。如果换新箱子,明细中,都需要更换箱子列表 */
+function getList() {
+  loading.value = true;
+  listOrder(queryParams.value).then((response) => {
+    orderList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  proxy.$refs.orderRef.open();
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  const id = row.id || ids.value;
+  row.flag = true
+  proxy.$refs.orderRef.open(row);
+}
+function handleView(row) {
+  const id = row.id || ids.value;
+  row.flag = false
+  proxy.$refs.orderRef.open(row);
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _ids = row.id || ids.value;
+  proxy.$modal
+    .confirm("是否确认删除选中的数据项?")
+    .then(function () {
+      return delOrder(_ids);
+    })
+    .then(() => {
+      getList();
+      proxy.$modal.msgSuccess("删除成功!");
+    })
+    .catch(() => { });
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  exportOutsource({ id: ids.value[0] });
+}
+
+/** 导出按钮操作 */
+function handlePrint() {
+  printOutsource({ id: ids.value[0] });
+}
+/** 打印箱码 */
+function handlePrintCarrierCode() {
+  // 获取箱码地址
+  if (ids.value.length === 0) {
+    // 判断是否选中行
+    proxy.$modal.msgWarning('请选择需要打印箱码的外协单')
+    return
+  }
+  getCarrierInfo(ids.value).then(res => {
+    if (res.code === 200) {
+      printCarriers.value = res.data
+      nextTick(_ => {
+        if (printCarriers.value.length == 0) {
+          proxy.$modal.msgWarning('选中外协单无可打印箱码')
+          return
+        }
+        const imageGroup = document.getElementById("image-group");
+        printJS({
+          printable: "image-group", // 这里是你要打印内容的DOM元素的id
+          type: "html",
+          style: "@page { size: auto;  margin: 0mm; }", // 可以添加打印样式
+        });
+      })
+    }
+  })
+}
+
+getList();
+</script>

+ 246 - 58
src/views/business/lot/index.vue

@@ -1,33 +1,65 @@
 <template>
   <div class="page-container column-container">
     <!-- 搜索区 -->
-    <el-form class="list-search-container" :model="queryParams" ref="queryRef" :inline="true">
+    <el-form
+      class="list-search-container"
+      :model="queryParams"
+      ref="queryRef"
+      :inline="true"
+    >
       <el-form-item label="产品描述:">
-        <el-input placeholder="请输入产品描述" v-model.trim="queryParams.productDescription" style="width: 150px" clearable
-          @keyup.enter="handleQuerydaywork" @keydown.enter.prevent />
+        <el-input
+          placeholder="请输入产品描述"
+          v-model.trim="queryParams.productDescription"
+          style="width: 150px"
+          clearable
+          @keyup.enter="handleQuerydaywork"
+          @keydown.enter.prevent
+        />
       </el-form-item>
       <el-form-item label="生产计划单号:">
-        <el-input placeholder="请输入生产计划单号" v-model.trim="queryParams.productionPlanNo" style="width: 120px" clearable
-          @keyup.enter="handleQuerydaywork" @keydown.enter.prevent />
+        <el-input
+          placeholder="请输入生产计划单号"
+          v-model.trim="queryParams.productionPlanNo"
+          style="width: 120px"
+          clearable
+          @keyup.enter="handleQuerydaywork"
+          @keydown.enter.prevent
+        />
       </el-form-item>
       <!-- <el-form-item label="序号:">
         <el-input placeholder="请输入序号" v-model.trim="queryParams.lineNumber" style="width: 130px" clearable
           @keyup.enter="handleQuerydaywork" @keydown.enter.prevent />
       </el-form-item> -->
       <el-form-item label="批次号:">
-        <el-input placeholder="请输入批次号" v-model.trim="queryParams.lotCode" style="width: 130px" clearable
-          @keyup.enter="handleQuerydaywork" @keydown.enter.prevent />
+        <el-input
+          placeholder="请输入批次号"
+          v-model.trim="queryParams.lotCode"
+          style="width: 130px"
+          clearable
+          @keyup.enter="handleQuerydaywork"
+          @keydown.enter.prevent
+        />
       </el-form-item>
       <el-form-item label="工段:">
         <!-- <el-select-v2 v-model="queryParams.deptId" :options="deptList" placeholder="请选择工段" style="width: 140px" /> -->
-        <el-autocomplete v-model.trim="deptName" clearable :fetch-suggestions="queryDeptSearchAsync" placeholder="请选择工段"
-          @select="handleDeptSelect" style="width: 140px" @clear="handleClearDept">
+        <el-autocomplete
+          v-model.trim="deptName"
+          clearable
+          :fetch-suggestions="queryDeptSearchAsync"
+          placeholder="请选择工段"
+          @select="handleDeptSelect"
+          style="width: 140px"
+          @clear="handleClearDept"
+        >
           <template #default="{ item }">
-            <div style="
+            <div
+              style="
                 display: flex;
                 flex-direction: row;
                 justify-content: space-between;
-              ">
+              "
+            >
               <div class="name" style="font-size: 12px">
                 {{ item.deptName }}
               </div>
@@ -36,30 +68,67 @@
         </el-autocomplete>
       </el-form-item>
       <el-form-item label="标识:">
-        <el-select style="width: 160px" multiple v-model="queryParams.flags" collapse-tags collapse-tags-tooltip
-          clearable placeholder="请选择标识" @change="handleFlagChange">
-          <el-option v-for="item in is_identification" :key="item.value" :label="item.label"
-            :value="item.value"></el-option>
+        <el-select
+          style="width: 160px"
+          multiple
+          v-model="queryParams.flags"
+          collapse-tags
+          collapse-tags-tooltip
+          clearable
+          placeholder="请选择标识"
+          @change="handleFlagChange"
+        >
+          <el-option
+            v-for="item in is_identification"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          ></el-option>
         </el-select>
       </el-form-item>
       <el-form-item label="时间:">
-        <el-date-picker v-model="queryParams.startTime" type="date" value-format="YYYY-MM-DD" :editable="false"
-          :clearable="false" placeholder="请选择开始时间" style="width: 130px" @change="handleDateChange" />
+        <el-date-picker
+          v-model="queryParams.startTime"
+          type="date"
+          value-format="YYYY-MM-DD"
+          :editable="false"
+          :clearable="false"
+          placeholder="请选择开始时间"
+          style="width: 130px"
+          @change="handleDateChange"
+        />
         <span>To</span>
-        <el-date-picker v-model="queryParams.endTime" type="date" value-format="YYYY-MM-DD" :editable="false"
-          :clearable="false" placeholder="请选择结束时间" style="width: 130px" @change="handleDateChange" />
+        <el-date-picker
+          v-model="queryParams.endTime"
+          type="date"
+          value-format="YYYY-MM-DD"
+          :editable="false"
+          :clearable="false"
+          placeholder="请选择结束时间"
+          style="width: 130px"
+          @change="handleDateChange"
+        />
       </el-form-item>
       <el-form-item label="工序:">
         <!-- <el-select-v2 v-model="processAlias" :options="processList" placeholder="请选择工序" style="width: 140px"
           @change="handleProcessChange" /> -->
-        <el-autocomplete v-model.trim="processAlias" clearable :fetch-suggestions="queryProcessSearchAsync"
-          placeholder="请选择工序" @select="handleProcessSelect" style="width: 140px" @clear="handleClearProcess">
+        <el-autocomplete
+          v-model.trim="processAlias"
+          clearable
+          :fetch-suggestions="queryProcessSearchAsync"
+          placeholder="请选择工序"
+          @select="handleProcessSelect"
+          style="width: 140px"
+          @clear="handleClearProcess"
+        >
           <template #default="{ item }">
-            <div style="
+            <div
+              style="
                 display: flex;
                 flex-direction: row;
                 justify-content: space-between;
-              ">
+              "
+            >
               <div class="name" style="font-size: 12px">
                 {{ item.label }}
               </div>
@@ -68,68 +137,176 @@
         </el-autocomplete>
       </el-form-item>
       <el-form-item>
-        <el-button type="info" icon="Search" @click="handleQuerydaywork">搜索</el-button>
+        <el-button type="info" icon="Search" @click="handleQuerydaywork"
+          >搜索</el-button
+        >
       </el-form-item>
       <div style="margin-top: 20px">
-        <el-button type="primary" @click="handleWasteRecycling"
+        <el-button
+          type="primary"
+          @click="handleWasteRecycling"
           :disabled="selections.length == 0 || selections.length > 1"
-          v-hasPermi="['business:lot:wasteRecycling']">添加废品回用</el-button>
-        <el-button :disabled="selections.length !== 1" type="primary" @click="showInBatch"
-          v-hasPermi="['business:lot:inBatch']">分批</el-button>
-        <el-button type="primary" :disabled="once" @click="handleOnceSingleChange"
-          v-hasPermi="['business:lot:onceSingleChange']">单批单改</el-button>
-        <el-button type="primary" :disabled="multi" @click="handleMultiSingleChange"
-          v-hasPermi="['business:lot:multiSingleChange']">多批单改</el-button>
+          v-hasPermi="['business:lot:wasteRecycling']"
+          >添加废品回用</el-button
+        >
+        <el-button
+          :disabled="selections.length !== 1"
+          type="primary"
+          @click="showInBatch"
+          v-hasPermi="['business:lot:inBatch']"
+          >分批</el-button
+        >
+        <el-button
+          type="primary"
+          :disabled="once"
+          @click="handleOnceSingleChange"
+          v-hasPermi="['business:lot:onceSingleChange']"
+          >单批单改</el-button
+        >
+        <el-button
+          type="primary"
+          :disabled="multi"
+          @click="handleMultiSingleChange"
+          v-hasPermi="['business:lot:multiSingleChange']"
+          >多批单改</el-button
+        >
       </div>
     </el-form>
     <!-- 列表区 -->
     <div class="el-table-container">
       <div class="el-table-inner-container">
-        <el-table ref="dayworkTable" v-loading="loading" row-key="lotId" @selection-change="handleSelectionChange"
-          height="100%" :data="lotList">
+        <el-table
+          ref="dayworkTable"
+          v-loading="loading"
+          row-key="lotId"
+          @selection-change="handleSelectionChange"
+          height="100%"
+          :data="lotList"
+        >
           <el-table-column type="selection" width="40" align="center" />
-          <el-table-column label="客户简称" prop="companyAlias" width="120" align="center" />
-          <el-table-column label="生产计划单号" width="100" prop="productionPlanNo" align="center" />
-          <el-table-column label="序号" width="60" prop="lineNumber" align="center" />
+          <el-table-column
+            label="客户简称"
+            prop="companyAlias"
+            width="120"
+            align="center"
+          />
+          <el-table-column
+            label="生产计划单号"
+            width="100"
+            prop="productionPlanNo"
+            align="center"
+          />
+          <el-table-column
+            label="序号"
+            width="60"
+            prop="lineNumber"
+            align="center"
+          />
 
-          <el-table-column label="批次号" prop="lotCode" align="center" width="150px">
+          <el-table-column
+            label="批次号"
+            prop="lotCode"
+            align="center"
+            width="150px"
+          >
             <template #default="scope">
-              <el-button link type="primary" @click="handleColumnClick(scope.row.lotCode)"><span>{{ scope.row.lotCode
-                  }}</span></el-button>
+              <el-button
+                link
+                type="primary"
+                @click="handleColumnClick(scope.row.lotCode)"
+                ><span>{{ scope.row.lotCode }}</span></el-button
+              >
             </template>
           </el-table-column>
-          <el-table-column label="产品描述" prop="productDescription" align="center" />
-          <el-table-column label="图纸版本" width="80" prop="technologyVersion" align="center" />
-          <el-table-column label="投产量" width="100" prop="productionQuantity" align="center" />
-          <el-table-column label="下达日期" prop="createTime" width="100" align="center">
+          <el-table-column
+            label="产品描述"
+            prop="productDescription"
+            align="center"
+          />
+          <el-table-column
+            label="图纸版本"
+            width="80"
+            prop="technologyVersion"
+            align="center"
+          />
+          <el-table-column
+            label="投产量"
+            width="100"
+            prop="productionQuantity"
+            align="center"
+          />
+          <el-table-column
+            label="下达日期"
+            prop="createTime"
+            width="100"
+            align="center"
+          >
             <template #default="scope">
               <span>{{
-      proxy.moment(scope.row.createTime).format("YYYY-MM-DD")
-    }}</span>
+                proxy.moment(scope.row.createTime).format("YYYY-MM-DD")
+              }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="当前工段" width="100" prop="deptName" align="center" />
-          <el-table-column label="当前工序" width="120" prop="processAlias" align="center" />
+          <el-table-column
+            label="当前工段"
+            width="100"
+            prop="deptName"
+            align="center"
+          />
+          <el-table-column
+            label="当前工序"
+            width="120"
+            prop="processAlias"
+            align="center"
+          />
           <el-table-column label="标识" width="300" align="center">
             <template #default="scope">
-              <el-tag v-if="scope.row.isWaste == 1" class="spacing" type="danger">{{ "批废" }}</el-tag>
-              <el-tag v-if="scope.row.isAmend == 1" class="spacing" type="danger">{{ "工艺修改" }}</el-tag>
-              <el-tag v-if="scope.row.isWasteRecycling == 1" class="spacing" type="primary">{{ "废品回用" }}</el-tag>
+              <el-tag
+                v-if="scope.row.isWaste == 1"
+                class="spacing"
+                type="danger"
+                >{{ "批废" }}</el-tag
+              >
+              <el-tag
+                v-if="scope.row.isAmend == 1"
+                class="spacing"
+                type="danger"
+                >{{ "工艺修改" }}</el-tag
+              >
+              <el-tag
+                v-if="scope.row.isWasteRecycling == 1"
+                class="spacing"
+                type="primary"
+                >{{ "废品回用" }}</el-tag
+              >
             </template>
           </el-table-column>
           <el-table-column label="母批号" prop="fromCode" align="center">
             <template #default="scope">
-              <el-button link type="primary" width="150px" @click="handleColumnClick(scope.row.fromCode)"><span>{{
-      scope.row.fromCode }}</span></el-button>
+              <el-button
+                link
+                type="primary"
+                width="150px"
+                @click="handleColumnClick(scope.row.fromCode)"
+                ><span>{{ scope.row.fromCode }}</span></el-button
+              >
             </template>
           </el-table-column>
         </el-table>
       </div>
     </div>
     <!-- 分页 -->
-    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
-      v-model:limit="queryParams.pageSize" @pagination="getLot" />
-    <waste-recycling-dialog ref="wasteRecyclingDialogRef" @handleSaveSuccess="getLot()"></waste-recycling-dialog>
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getLot"
+    />
+    <waste-recycling-dialog
+      ref="wasteRecyclingDialogRef"
+      @handleSaveSuccess="getLot()"
+    ></waste-recycling-dialog>
     <InBatchesDialog ref="inBatchesDialogRef" :getList="handleQuerydaywork" />
     <once-change ref="onceChangeRef" @handleSaveSuccess="getLot()" />
     <multi-change ref="multiChangeRef" @handleSaveSuccess="getLot()" />
@@ -145,6 +322,8 @@ import multiChange from "@/views/business/reviseBath/multiSingleChangeDialog.vue
 import onceChange from "@/views/business/reviseBath/onceSingleChangeDialog.vue";
 import InBatchesDialog from "@/views/business/lot/InBatchesDialog.vue";
 import { ref } from "vue";
+import lotStore from "@/store/modules/lot";
+
 const route = useRoute();
 const { proxy } = getCurrentInstance();
 /** 字典数组区 */
@@ -162,6 +341,7 @@ const visible = ref(false);
 const selections = ref([]);
 const processList = ref([]);
 const deptList = ref([]);
+
 /** 查询对象 */
 const queryParams = ref({
   pageNum: 1,
@@ -260,6 +440,12 @@ function handleOnceSingleChange() {
 
 /**获取生产计划列表 */
 function getLot() {
+  console.log("storeLot", lotStore().lotQueryParams);
+
+  if (lotStore().lotQueryParams != null) {
+    queryParams.value = lotStore().lotQueryParams;
+  }
+
   loading.value = true;
   getLotList(queryParams.value).then((res) => {
     if (res.code == 200) {
@@ -336,6 +522,7 @@ function handleQuerydaywork() {
   ) {
     proxy.$modal.msgError("结束时间不能小于开始时间");
   } else {
+    lotStore().setlotQueryParams(queryParams.value);
     getLot();
   }
 }
@@ -433,8 +620,9 @@ const handleFlagChange = (selection) => {
 };
 const checkRecycle = () => {
   // 判断是否是废品回用,废品回用的无论分批还是单批单改多批单改废品回用都不能做
-  return selections.value.some(v => v.isWasteRecycling == 1)
-}
+  return selections.value.some((v) => v.isWasteRecycling == 1);
+};
+getLot();
 onMounted(() => {
   getDept();
 });

+ 23 - 16
src/views/business/outsource/index.vue

@@ -130,6 +130,7 @@ import {
 } from "@/api/business/outsourcedOrder";
 import orderForm from "./form";
 import printJS from "print-js";
+import { nextTick } from "vue";
 const { proxy } = getCurrentInstance();
 /** 字典数组区 */
 const { delivery_method } = proxy.useDict("delivery_method");
@@ -211,16 +212,16 @@ function handleView(row) {
 /** 删除按钮操作 */
 function handleDelete(row) {
   const _ids = row.id || ids.value;
-    proxy.$modal
-      .confirm("是否确认删除选中的数据项?")
-      .then(function () {
-        return delOrder(_ids);
-      })
-      .then(() => {
-        getList();
-        proxy.$modal.msgSuccess("删除成功!");
-      })
-      .catch(() => {});
+  proxy.$modal
+    .confirm("是否确认删除选中的数据项?")
+    .then(function () {
+      return delOrder(_ids);
+    })
+    .then(() => {
+      getList();
+      proxy.$modal.msgSuccess("删除成功!");
+    })
+    .catch(() => { });
 }
 
 /** 导出按钮操作 */
@@ -243,12 +244,18 @@ function handlePrintCarrierCode() {
   getCarrierInfo(ids.value).then(res => {
     if (res.code === 200) {
       printCarriers.value = res.data
-      const imageGroup = document.getElementById("image-group");
-      printJS({
-        printable: "image-group", // 这里是你要打印内容的DOM元素的id
-        type: "html",
-        style: "@page { size: auto;  margin: 0mm; }", // 可以添加打印样式
-      });
+      nextTick(_ => {
+        if (printCarriers.value.length == 0) {
+          proxy.$modal.msgWarning('选中外协单无可打印箱码')
+          return
+        }
+        const imageGroup = document.getElementById("image-group");
+        printJS({
+          printable: "image-group", // 这里是你要打印内容的DOM元素的id
+          type: "html",
+          style: "@page { size: auto;  margin: 0mm; }", // 可以添加打印样式
+        });
+      })
     }
   })
 }

+ 56 - 256
src/views/business/productionBatch/index.vue

@@ -2,190 +2,63 @@
   <div class="page-container column-container">
     <section class="list-part-container column-container" style="flex: 1">
       <!-- 搜索区 -->
-      <el-form
-        class="list-search-container"
-        :model="queryParams"
-        ref="queryRef"
-        :inline="true"
-      >
+      <el-form class="list-search-container" :model="queryParams" ref="queryRef" :inline="true">
         <el-form-item class="section-title" label="生产计划" />
         <el-form-item label="生产计划单号:">
-          <el-input
-            placeholder="请输入生产计划单号"
-            v-model.trim="queryParams.productionPlanNo"
-            @keyup.enter="handleQueryProductionPlanDetail"
-            @keydown.enter.prevent
-            clearable
-            style="width: 200px"
-          />
+          <el-input placeholder="请输入生产计划单号" v-model.trim="queryParams.productionPlanNo"
+            @keyup.enter="handleQueryProductionPlanDetail" @keydown.enter.prevent clearable style="width: 200px" />
         </el-form-item>
         <el-form-item label="产品描述:">
-          <el-input
-            placeholder="请输入产品描述"
-            v-model.trim="queryParams.keywords"
-            @keyup.enter="handleQueryProductionPlanDetail"
-            @keydown.enter.prevent
-            clearable
-            style="width: 200px"
-          />
+          <el-input placeholder="请输入产品描述" v-model.trim="queryParams.keywords"
+            @keyup.enter="handleQueryProductionPlanDetail" @keydown.enter.prevent clearable style="width: 200px" />
         </el-form-item>
 
         <el-form-item>
-          <el-button
-            type="info"
-            icon="Search"
-            @click="handleQueryProductionPlanDetail"
-          >
+          <el-button type="info" icon="Search" @click="handleQueryProductionPlanDetail">
             搜索
           </el-button>
         </el-form-item>
         <el-form-item class="section-title" label="请选择当前工段:">
-          <el-select-v2
-            v-model="queryParams.deptId"
-            filterable
-            :options="deptList"
-            placeholder="请选择工段"
-            style="width: 100%"
-            @change="handleDeptChange"
-          />
+          <el-select-v2 v-model="queryParams.deptId" filterable :options="deptList" placeholder="请选择工段"
+            style="width: 100%" @change="handleDeptChange" />
         </el-form-item>
       </el-form>
       <div class="el-table-container">
         <div class="el-table-inner-container">
-          <el-table
-            ref="planDetailTable"
-            :data="detailPlanList"
-            v-loading="detailLoading"
-            highlight-current-row
-            height="100%"
-            @current-change="handlePlanDetailCurrentChange"
-          >
-            <el-table-column
-              label="客户简称"
-              prop="companyAlias"
-              width="120"
-              align="center"
-            />
-            <el-table-column
-              label="生产计划单号"
-              prop="productionPlanNo"
-              width="110"
-              align="center"
-            />
-            <el-table-column
-              label="序号"
-              width="60"
-              prop="lineNumber"
-              align="center"
-            />
-            <el-table-column
-              label="产品描述"
-              prop="productDescription"
-              align="center"
-            />
-            <el-table-column
-              label="图纸版本"
-              prop="technologyVersion"
-              width="70"
-              align="center"
-            />
-            <el-table-column
-              label="总投产量"
-              prop="productionQuantity"
-              width="80"
-              align="center"
-            />
-            <el-table-column
-              label="总批数"
-              prop="totalLotNumber"
-              width="70"
-              align="center"
-            />
-            <el-table-column
-              label="单批量"
-              prop="oneLotQuantity"
-              width="80"
-              align="center"
-            />
-            <el-table-column
-              label="尾批量"
-              prop="lastLotQuantity"
-              width="80"
-              align="center"
-            />
-            <el-table-column
-              label="批号状态"
-              prop="lotCodeStatusCode"
-              width="100"
-              align="center"
-            >
+          <el-table ref="planDetailTable" :data="detailPlanList" v-loading="detailLoading" highlight-current-row
+            height="100%" @current-change="handlePlanDetailCurrentChange">
+            <el-table-column label="客户简称" prop="companyAlias" width="120" align="center" />
+            <el-table-column label="生产计划单号" prop="productionPlanNo" width="110" align="center" />
+            <el-table-column label="序号" width="60" prop="lineNumber" align="center" />
+            <el-table-column label="产品描述" prop="productDescription" align="center" />
+            <el-table-column label="图纸版本" prop="technologyVersion" width="70" align="center" />
+            <el-table-column label="总投产量" prop="productionQuantity" width="80" align="center" />
+            <el-table-column label="总批数" prop="totalLotNumber" width="70" align="center" />
+            <el-table-column label="单批量" prop="oneLotQuantity" width="80" align="center" />
+            <el-table-column label="尾批量" prop="lastLotQuantity" width="80" align="center" />
+            <el-table-column label="批号状态" prop="lotCodeStatusCode" width="100" align="center">
               <template #default="scope">
-                <dict-tag
-                  :options="lot_code_status_code"
-                  :value="scope.row.lotCodeStatusCode"
-                />
+                <dict-tag :options="lot_code_status_code" :value="scope.row.lotCodeStatusCode" />
               </template>
             </el-table-column>
-            <el-table-column
-              label="累计投产量"
-              prop="pickUpQuantity"
-              width="80"
-              align="center"
-            />
-            <el-table-column
-              label="累计投产批数"
-              prop="lotTotalNumber"
-              width="90"
-              align="center"
-            />
-            <el-table-column
-              label="库位"
-              prop="storageLocation"
-              width="80"
-              align="center"
-            />
-            <el-table-column
-              label="领料部门"
-              prop="requisitionDepartmentName"
-              width="100"
-              align="center"
-            >
+            <el-table-column label="累计投产量" prop="pickUpQuantity" width="80" align="center" />
+            <el-table-column label="累计投产批数" prop="lotTotalNumber" width="90" align="center" />
+            <el-table-column label="库位" prop="storageLocation" width="80" align="center" />
+            <el-table-column label="领料部门" prop="requisitionDepartmentName" width="100" align="center">
               <template #default="scope">
                 <span>{{ scope.row.requisitionDepartmentName }}</span>
               </template>
             </el-table-column>
-            <el-table-column
-              label="下达日期"
-              prop="issueDate"
-              width="100"
-              align="center"
-            />
-            <el-table-column
-              label="操作"
-              width="240"
-              align="center"
-              fixed="right"
-            >
+            <el-table-column label="下达日期" prop="issueDate" width="100" align="center" />
+            <el-table-column label="操作" width="240" align="center" fixed="right">
               <template #default="scope">
-                <el-button
-                  link
-                  type="success"
-                  icon="View"
-                  @click="handleCheckMarterialInfo(scope.row)"
-                  >领料信息
+                <el-button link type="success" icon="View" @click="handleCheckMarterialInfo(scope.row)">领料信息
                 </el-button>
-                <el-button
-                  :disabled="
-                    !(
-                      queryParams.deptId == scope.row.requisitionDepartmentId
-                    ) || scope.row.totalLotNumber == scope.row.lotTotalNumber
-                  "
-                  link
-                  type="primary"
-                  icon="Postcard"
-                  @click="handleAddSubDetail(scope.row)"
-                  v-hasPermi="['business:productionBatch:add']"
-                  >投产
+                <el-button :disabled="!(
+          queryParams.deptId == scope.row.requisitionDepartmentId
+        ) || scope.row.totalLotNumber == scope.row.lotTotalNumber
+        " link type="primary" icon="Postcard" @click="handleAddSubDetail(scope.row)"
+                  v-hasPermi="['business:productionBatch:add']">投产
                 </el-button>
                 <!-- <el-button
                   icon="edit"
@@ -201,13 +74,8 @@
       </div>
     </section>
     <!-- 分页 -->
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      v-model:page="queryParams.pageNum"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getProductionPlanDetail"
-    />
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize" @pagination="getProductionPlanDetail" />
 
     <section class="list-part-container row-container" style="flex: 1">
       <section class="list-part-container" style="flex: 4">
@@ -218,98 +86,33 @@
         </el-form>
         <div class="el-table-container">
           <div class="el-table-inner-container">
-            <el-table
-              ref="subDetailsTable"
-              v-loading="subDetailsLoading"
-              :data="subList"
-              highlight-current-row
-              height="100%"
-            >
-              <el-table-column
-                type="index"
-                label="行号"
-                width="50"
-                align="center"
-              />
-              <el-table-column
-                label="生产计划单号"
-                prop="productionPlanNo"
-                width="110"
-                align="center"
-              />
-              <el-table-column
-                label="产品描述"
-                prop="productDescription"
-                align="center"
-              />
-              <el-table-column
-                label="首序投产量"
-                prop="productionQuantity"
-                width="80"
-                align="center"
-              />
-              <el-table-column
-                label="首序投产批数"
-                prop="lotNumber"
-                width="100"
-                align="center"
-              >
+            <el-table ref="subDetailsTable" v-loading="subDetailsLoading" :data="subList" highlight-current-row
+              height="100%">
+              <el-table-column type="index" label="行号" width="50" align="center" />
+              <el-table-column label="生产计划单号" prop="productionPlanNo" width="110" align="center" />
+              <el-table-column label="产品描述" prop="productDescription" align="center" />
+              <el-table-column label="首序投产量" prop="productionQuantity" width="80" align="center" />
+              <el-table-column label="首序投产批数" prop="lotNumber" width="100" align="center">
                 <template #default="scope">
-                  <el-input-number
-                    v-if="scope.row.editStatus"
-                    v-model="scope.row.lotNumber"
-                    placeholder="当前投产批数"
-                    :controls="false"
-                    :precision="0"
-                    :min="0"
-                    :max="scope.row.totalLotNumber"
-                    align="center"
-                  />
+                  <el-input-number v-if="scope.row.editStatus" v-model="scope.row.lotNumber" placeholder="当前投产批数"
+                    :controls="false" :precision="0" :min="0" :max="scope.row.totalLotNumber" align="center" />
                   <span v-else>{{ scope.row.lotNumber }}</span>
                 </template>
               </el-table-column>
-              <el-table-column
-                label="下达日期"
-                prop="issuanceDate"
-                width="120"
-                align="center"
-              >
+              <el-table-column label="下达日期" prop="issuanceDate" width="120" align="center">
                 <template #default="scope">
-                  <el-date-picker
-                    v-if="scope.row.editStatus"
-                    clearable
-                    v-model="scope.row.issuanceDate"
-                    type="date"
-                    value-format="YYYY-MM-DD"
-                    placeholder="请选择实际开始 时间"
-                  />
+                  <el-date-picker v-if="scope.row.editStatus" clearable v-model="scope.row.issuanceDate" type="date"
+                    value-format="YYYY-MM-DD" placeholder="请选择实际开始 时间" />
                   <span v-else>{{ scope.row.issuanceDate }}</span>
                 </template>
               </el-table-column>
-              <el-table-column
-                label="操作"
-                width="150"
-                align="center"
-                v-if="flag"
-              >
+              <el-table-column label="操作" width="150" align="center" v-if="flag">
                 <template #default="scope">
-                  <el-button
-                    v-if="!scope.row.editStatus"
-                    icon="edit"
-                    link
-                    type="warning"
-                    @click="handleShowSubDetailDialog(scope.row)"
-                    v-hasPermi="['business:productionBatch:edit']"
-                    >编辑
+                  <el-button v-if="!scope.row.editStatus" icon="edit" link type="warning"
+                    @click="handleShowSubDetailDialog(scope.row)" v-hasPermi="['business:productionBatch:edit']">编辑
                   </el-button>
-                  <el-button
-                    v-if="!scope.row.editStatus"
-                    icon="delete"
-                    link
-                    type="danger"
-                    @click="handleDelSubDetail(scope.row)"
-                    v-hasPermi="['business:productionBatch:remove']"
-                    >删除
+                  <el-button v-if="!scope.row.editStatus" icon="delete" link type="danger"
+                    @click="handleDelSubDetail(scope.row)" v-hasPermi="['business:productionBatch:remove']">删除
                   </el-button>
                 </template>
               </el-table-column>
@@ -319,10 +122,7 @@
       </section>
     </section>
     <!-- 投产表单 -->
-    <production-lot-form
-      ref="productionRef"
-      @handleSaveSuccess="handleFresh()"
-    />
+    <production-lot-form ref="productionRef" @handleSaveSuccess="handleFresh()" />
     <!-- 领料信息弹窗 -->
     <check-material ref="checkMaterialRef" />
     <!-- 工艺版本变更弹窗
@@ -544,15 +344,15 @@ function handleDelSubDetail(row) {
         updateLotCodeStatus({
           id: currentPlanDetail.value.id,
           lotCodeStatusCode: "NA",
-        }).then((res) => {});
+        }).then((res) => { });
       }
       handleFresh();
       proxy.$modal.msgSuccess("删除成功!");
     })
-    .catch(() => {});
+    .catch(() => { });
 }
 onMounted(() => {
-  getProductionPlanDetail();
+  // getProductionPlanDetail();
   getList();
 });
 </script>