Quellcode durchsuchen

fix: 开发商品管理、BOM、生产管理、财务、调整出库入库部分字段

wuguojie vor 4 Monaten
Ursprung
Commit
f03e2bd83a

+ 9 - 0
src/api/finance/index.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request';
+
+export function getProduct(query) {
+    return request({
+        url: '/wms/cost/finished/product',
+        method: 'get',
+        params: query
+    })
+}

+ 76 - 0
src/api/production/task.js

@@ -0,0 +1,76 @@
+import request from '@/utils/request';
+
+/**
+ * 查询sku信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export function taskList(query) {
+    return request({
+        url: '/wms/task/list',
+        method: 'get',
+        params: query
+    });
+};
+
+export function addTask(query) {
+    return request({
+        url: '/wms/task',
+        method: 'post',
+        data: query
+    })
+}
+
+export function BOMVersion(query) {
+    return request({
+        url: '/wms/bom/version',
+        method: 'get',
+        params: query
+    })
+}
+
+export function taskDetails(query) {
+    return request({
+        url: '/wms/task/details',
+        method: 'get',
+        params: query
+    })
+}
+
+export function detailTask(query) {
+    return request({
+        url: `/wms/task/${query}`,
+        method: 'get'
+    })
+}
+
+export function editTask(query) {
+    return request({
+        url: `/wms/task/${query}`,
+        method: 'put'
+    })
+}
+
+export function taskComplete(query) {
+    return request({
+        url: `/wms/task/complete/${query}`,
+        method: 'put'
+    })
+}
+
+export function taskRevoke(query) {
+    return request({
+        url: `/wms/task/revoke/${query}`,
+        method: 'put'
+    })
+}
+
+export function addBom(query) {
+    return request({
+        url: '/wms/bom',
+        method: 'post',
+        data: query
+    })
+}
+

+ 9 - 0
src/api/wms/item.js

@@ -81,3 +81,12 @@ export function delItem(id) {
     method: 'delete'
   });
 };
+
+export function bomList(query) {
+  return request({
+    url: '/wms/bom/list',
+    method: 'get',
+    params: query
+  })
+}
+

+ 27 - 8
src/views/components/SkuSelect.vue

@@ -19,11 +19,18 @@
             </el-col>
           </el-row>
           <el-row :gutter="20">
-            <el-col :span="8">
-              <el-form-item label="规格编号">
-                <el-input class="w200" v-model="query.barcode" clearable placeholder="规格编号"></el-input>
-              </el-form-item>
-            </el-col>
+              <el-col :span="8">
+                  <el-form-item label="规格编号">
+                      <el-input class="w200" v-model="query.barcode" clearable placeholder="规格编号"></el-input>
+                  </el-form-item>
+              </el-col>
+              <el-col :span="8" v-if="props.isNeedType">
+                  <el-form-item label="商品类型">
+                      <el-select style="width: 90%" v-model="query.itemType" clearable filterable>
+                          <el-option v-for="item in item_type" :value="item.value" :label="item.label"></el-option>
+                      </el-select>
+                  </el-form-item>
+              </el-col>
             <el-col :span="8">
               <el-button type="primary" @click="loadAll">查询</el-button>
             </el-col>
@@ -45,6 +52,11 @@
                   <div v-if="row.itemSku.barcode">条码:{{ row.itemSku.barcode }}</div>
                 </template>
               </el-table-column>
+                <el-table-column label="类型" v-if="props.isNeedType">
+                    <template #default="{ row }">
+                        <span>{{ row.item.itemType == '1'?'成品':row.item.itemType == '2'?'原料':row.item.itemType == '3'?'包材':'' }}</span>
+                    </template>
+                </el-table-column>
               <el-table-column label="价格(元)" width="160" align="left">
                 <template #default="{ row }">
                   <div v-if="row.itemSku.costPrice" class="flex-space-between">
@@ -93,7 +105,7 @@
         <span>
           <el-button @click="handleCancelClick">取消</el-button>
           <el-button type="primary" @click="handleOkClick" v-if="!singleSelect">确认</el-button>
-      </span>
+        </span>
       </div>
     </template>
   </el-drawer>
@@ -107,6 +119,8 @@ import {useWmsStore} from '@/store/modules/wms'
 
 const { proxy } = getCurrentInstance()
 
+const { item_type } = proxy.useDict('item_type')
+
 const router = useRouter()
 const loading = ref(false)
 const deptOptions = ref([]);
@@ -114,7 +128,8 @@ const query = reactive({
   itemName: '',
   itemCode: '',
   skuName: '',
-  barcode: ''
+  barcode: '',
+  itemType: ''
 });
 const selectItemSkuVoCheck = ref([])
 const skuSelectFormRef = ref(null)
@@ -172,7 +187,11 @@ const props = defineProps({
   selectedSku: {
     type: Array,
     default: []
-  }
+  },
+    isNeedType: {
+        type: Boolean,
+        default: false
+    }
 })
 
 const show = computed(() => {

+ 183 - 0
src/views/finance/cost/index.vue

@@ -0,0 +1,183 @@
+<template>
+    <div class="app-container">
+        <el-form
+            :model="form"
+            label-width="120"
+        >
+            <el-row :gutter="10">
+                <el-col :span="8">
+                    <el-form-item label="任务编号">
+                        <el-input v-model="form.taskCode" clearable placeholder="请输入任务编号" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="商品名称">
+                        <el-input v-model="form.itemName" clearable placeholder="请输入商品名称" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="商品编号">
+                        <el-input v-model="form.itemCode" clearable placeholder="请输入商品编号" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="规格名称">
+                        <el-input v-model="form.skuName" clearable placeholder="请输入规格名称" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="BOM版本">
+                        <el-select style="width: 100%" v-model="form.versionId" clearable placeholder="请选择BOM版本">
+                            <el-option v-for="item in BOMList" :value="item.value" :label="item.label"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="生产时间">
+                        <el-date-picker
+                            type="daterange"
+                            v-model="form.date"
+                            format="yyyy-MM-DD"
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                            style="width: 100%"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-button icon="Search" type="primary" @click="initList">搜索</el-button>
+                    <el-button icon="Refresh" @click="refresh">重置</el-button>
+                </el-col>
+            </el-row>
+        </el-form>
+        <el-table
+            :data="list"
+        >
+            <el-table-column label="商品信息">
+                <template #default="{ row }">
+                    <div>{{ row.itemName + (row.itemCode ? ('(' +  row.itemCode + ')') : '') }}</div>
+                    <div v-if="row.itemBrand">{{ row.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.itemBrand)?.brandName) : '' }}</div>
+                    <div v-if="row.itemCategory">{{ row.itemCategory ? ('分类:' + useWmsStore().itemCategoryMap.get(row.itemCategory)?.categoryName) : '' }}</div>
+                </template>
+            </el-table-column>
+            <el-table-column label="规格信息">
+                <template #default="{ row }">
+                    <div>{{ row.skuName }}</div>
+                    <div v-if="row.skuCode">编号:{{ row.skuCode }}</div>
+                    <div v-if="row.barcode">条码:{{ row.barcode }}</div>
+                </template>
+            </el-table-column>
+            <el-table-column prop="c" label="材料成本"></el-table-column>
+            <el-table-column prop="d" label="包材成本"></el-table-column>
+            <el-table-column prop="e" label="总成本"></el-table-column>
+            <el-table-column prop="f" label="生产数量"></el-table-column>
+            <el-table-column prop="g" label="最低成本"></el-table-column>
+            <el-table-column prop="h" label="最高成本"></el-table-column>
+            <el-table-column prop="i" label="成本变动率"></el-table-column>
+        </el-table>
+        <div class="pagination">
+            <el-pagination
+                :current-page="form.pageNum"
+                :page-size="form.pageSize"
+                background
+                small
+                :total="total"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+            ></el-pagination>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { getProduct } from '@/api/finance/index'
+import { BOMVersion } from '@/api/production/task'
+import { useWmsStore } from "@/store/modules/wms";
+
+let form = ref({
+    taskCode: '',
+    itemName: '',
+    itemCode: '',
+    skuName: '',
+    versionId: '',
+    date: '',
+    pageNum: 1,
+    pageSize: 10
+})
+let total = ref(0)
+let list = ref([])
+
+const handleSizeChange = (size) => {
+    form.value.pageSize = size
+    initList()
+}
+const handleCurrentChange = (page) => {
+    form.value.pageNum = page
+    initList()
+}
+const initList = () => {
+    let params = {
+        taskCode: form.value.taskCode,
+        itemName: form.value.itemName,
+        itemCode: form.value.itemCode,
+        skuName: form.value.skuName,
+        versionId: form.value.versionId,
+        startDate: form.value.date[0],
+        endDate: form.value.date[1],
+        pageNum: form.value.pageNum,
+        pageSize: form.value.pageSize
+    }
+    getProduct({
+        ...params
+    }).then(res => {
+        if(res.code == 200) {
+            list.value = res.data.rows
+            total.value = res.data.total
+        } else {
+            list.value = []
+        }
+    })
+}
+const refresh = () => {
+    form.value = {
+        taskCode: '',
+        itemName: '',
+        itemCode: '',
+        skuName: '',
+        versionId: '',
+        date: [],
+        pageNum: 1,
+        pageSize: 10
+    }
+}
+
+let BOMList = ref([])
+const getBOM = () => {
+    BOMVersion({
+        skuId: ''
+    }).then(res => {
+        if(res.code == 200) {
+            BOMList.value = res.data
+        } else {
+            BOMList.value = []
+        }
+    })
+}
+
+onMounted(() => {
+    initList()
+    getBOM()
+})
+
+</script>
+
+<style scoped>
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+</style>

+ 94 - 0
src/views/finance/inventory/index.vue

@@ -0,0 +1,94 @@
+<template>
+    <div class="app-container">
+        <el-form
+            :model="form"
+            label-width="120"
+        >
+            <el-row :gutter="10">
+                <el-col :span="8">
+                    <el-form-item label="商品名称">
+                        <el-input v-model="form.b" clearable placeholder="请输入商品名称" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="商品编号">
+                        <el-input v-model="form.c" clearable placeholder="请输入商品编号" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="规格名称">
+                        <el-input v-model="form.d" clearable placeholder="请输入规格名称" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="客户">
+                        <el-select style="width: 100%" v-model="form.e" clearable placeholder="请选择BOM版本">
+                            <el-option value="1" label="1"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="统计时间">
+                        <el-date-picker
+                            type="daterange"
+                            v-model="form.f"
+                            format="yyyy-MM-DD"
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                            style="width: 100%"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-button icon="Search" type="primary">搜索</el-button>
+                    <el-button icon="Refresh">重置</el-button>
+                </el-col>
+            </el-row>
+        </el-form>
+        <el-table
+            :data="list"
+        >
+            <el-table-column prop="a" label="商品信息"></el-table-column>
+            <el-table-column prop="b" label="规格信息"></el-table-column>
+            <el-table-column prop="c" label="生产入库"></el-table-column>
+            <el-table-column prop="d" label="销售出库"></el-table-column>
+            <el-table-column prop="e" label="终端销售"></el-table-column>
+            <el-table-column prop="f" label="终端库存"></el-table-column>
+        </el-table>
+        <div class="pagination">
+            <el-pagination
+                :current-page="form.current"
+                :page-size="form.size"
+                background
+                small
+                :total="total"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+            ></el-pagination>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+let form = ref({})
+let total = ref(0)
+let list = ref([])
+
+const handleSizeChange = (size) => {
+
+}
+const handleCurrentChange = (page) => {
+
+}
+</script>
+
+<style scoped>
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+</style>

+ 398 - 0
src/views/production/task/edit.vue

@@ -0,0 +1,398 @@
+<template>
+    <div class="app-container">
+        <div class="content">
+            <div class="title">基本信息</div>
+            <el-form :disabled="isView" :model="addForm" :rules="addRules" label-width="120">
+                <el-row :gutter="10">
+                    <el-col :span="8">
+                        <el-form-item prop="taskCode" label="任务编号">
+                            <el-input v-model="addForm.taskCode" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="startDate" label="生产开始时间">
+                            <el-date-picker
+                                v-model="addForm.startDate"
+                                type="datetime"
+                                format="YYYY-MM-DD"
+                                value-format="YYYY-MM-DD"
+                                style="width: 100%"
+                            ></el-date-picker>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="endDate" label="生产结束时间">
+                            <el-date-picker
+                                v-model="addForm.endDate"
+                                type="datetime"
+                                format="YYYY-MM-DD"
+                                value-format="YYYY-MM-DD"
+                                style="width: 100%"
+                            ></el-date-picker>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="d" label="备注">
+                            <el-input v-model="addForm.remark" type="textarea" maxlength="500" show-word-limit />
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+            </el-form>
+            <div class="title">
+                <span>生产明细</span>
+                <el-button size="small" icon="Plus" @click="initList">添加商品</el-button>
+            </div>
+            <el-table
+                :data="addList"
+            >
+                <el-table-column label="商品信息">
+                    <template #default="{ row }">
+                        <div>{{ row.item.itemName + (row.item.itemCode ? ('(' +  row.item.itemCode + ')') : '') }}</div>
+                        <div v-if="row.item.itemBrand">{{ row.item.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.item.itemBrand)?.brandName) : '' }}</div>
+                        <div v-if="row.item.itemCategory">{{ row.item.itemCategory ? ('分类:' + useWmsStore().itemCategoryMap.get(row.item.itemCategory)?.categoryName) : '' }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="规格信息">
+                    <template #default="{ row }">
+                        <div>{{ row.itemSku.skuName }}</div>
+                        <div v-if="row.itemSku.skuCode">编号:{{ row.itemSku.skuCode }}</div>
+                        <div v-if="row.itemSku.barcode">条码:{{ row.itemSku.barcode }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="versionId" label="BOM版本">
+                    <template #default="scope">
+                        <el-select :disabled="isView" v-model="scope.row.versionId" style="width: 100%">
+                            <el-option v-for="item in BOMList" :value="item.id" :label="item.version"></el-option>
+                        </el-select>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="quantity" label="生产数量">
+                    <template #default="scope">
+                        <el-input :disabled="isView" v-model="scope.row.quantity" />
+                    </template>
+                </el-table-column>
+<!--                <el-table-column label="操作">
+                    <template #default="scope">
+                        <el-button link type="primary">删除</el-button>
+                    </template>
+                </el-table-column>-->
+            </el-table>
+        </div>
+        <div class="footer">
+            <el-button @click="handleCancel">取消</el-button>
+            <el-button type="primary" @click="handleAddTask">确定生产</el-button>
+        </div>
+        <el-drawer size="80%" title="商品选择" v-model="addItemShow">
+            <el-form :model="itemForm" label-width="120">
+                <el-row :gutter="10">
+                    <el-col :span="8">
+                        <el-form-item label="商品名称">
+                            <el-input v-model="itemForm.itemName" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="商品编号">
+                            <el-input v-model="itemForm.itemCode" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="规格名称">
+                            <el-input v-model="itemForm.skuName" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="规格编号">
+                            <el-input v-model="itemForm.skuCode" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-button type="primary">搜索</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+            <el-table
+                :data="itemList"
+                @selection-change="handleSelectChange"
+            >
+                <el-table-column type="selection"></el-table-column>
+                <el-table-column label="商品信息">
+                    <template #default="{ row }">
+                        <div>{{ row.item.itemName + (row.item.itemCode ? ('(' +  row.item.itemCode + ')') : '') }}</div>
+                        <div v-if="row.item.itemBrand">{{ row.item.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.item.itemBrand)?.brandName) : '' }}</div>
+                        <div v-if="row.item.itemCategory">{{ row.item.itemCategory ? ('分类:' + useWmsStore().itemCategoryMap.get(row.item.itemCategory)?.categoryName) : '' }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="规格信息">
+                    <template #default="{ row }">
+                        <div>{{ row.itemSku.skuName }}</div>
+                        <div v-if="row.itemSku.skuCode">编号:{{ row.itemSku.skuCode }}</div>
+                        <div v-if="row.itemSku.barcode">条码:{{ row.itemSku.barcode }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="价格(元)">
+                    <template #default="{ row }">
+                        <div v-if="row.itemSku.costPrice" class="flex-space-between">
+                            <span>成本价:</span>
+                            <div>{{ (row.itemSku.costPrice || row.itemSku.costPrice === 0) ? row.itemSku.costPrice : '' }}</div>
+                        </div>
+                        <div v-if="row.itemSku.sellingPrice" class="flex-space-between">
+                            <span>销售价:</span>
+                            <div>{{ (row.itemSku.sellingPrice || row.itemSku.sellingPrice === 0) ? row.itemSku.sellingPrice : '' }}</div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="重量(Kg)">
+                    <template #default="{ row }">
+                        <div v-if="row.itemSku.netWeight" class="flex-space-between">
+                            <span>净重:</span>
+                            <div>
+                                {{ (row.itemSku.netWeight || row.itemSku.netWeight === 0) ? row.itemSku.netWeight : '' }}
+                            </div>
+                        </div>
+                        <div v-if="row.itemSku.grossWeight" class="flex-space-between">
+                            <span>毛重:</span>
+                            <div>
+                                {{ (row.itemSku.grossWeight || row.itemSku.grossWeight === 0) ? row.itemSku.grossWeight : '' }}
+                            </div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="长宽高(cm)">
+                    <template #default="{ row }">
+                        <div>{{ getVolumeText(row.itemSku) }}</div>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <div class="pagination">
+                <el-pagination
+                    v-model:current-page="itemForm.pageNum"
+                    v-model:page-size="itemForm.pageSize"
+                    background
+                    small
+                    :total="total"
+                    @size-change="handleSizeChange"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+            <template #footer>
+                <div class="btn">
+                    <div class="left">
+                        <el-button icon="Plus" @click="createItem">创建商品</el-button>
+                        <el-button icon="refresh">刷新</el-button>
+                    </div>
+                    <div class="right">
+                        <el-button @click="handleSelectCancel">取消</el-button>
+                        <el-button type="primary" @click="handleSelectConfirm">确定</el-button>
+                    </div>
+                </div>
+            </template>
+        </el-drawer>
+    </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from 'vue'
+const { proxy } = getCurrentInstance();
+import {addTask, BOMVersion, detailTask, editTask} from '@/api/production/task'
+import { listItemSkuPage } from "@/api/wms/itemSku";
+import { useWmsStore } from "@/store/modules/wms";
+import { ElMessage } from "element-plus";
+import { useRoute } from 'vue-router'
+
+const route = useRoute()
+
+const getVolumeText = (itemSku) => {
+    if((itemSku.length || itemSku.length === 0) && (itemSku.width || itemSku.width === 0) && (itemSku.height || itemSku.height === 0)) {
+        return itemSku.length + ' * ' + itemSku.width + ' * ' + itemSku.height
+    }
+    return ((itemSku.length || itemSku.length === 0) ? ('长:' + itemSku.length) : '')
+        + ((itemSku.width || itemSku.width === 0) ? (' 宽:' + itemSku.width) : '')
+        + ((itemSku.height || itemSku.height === 0) ? (' 高:' + itemSku.height) : '')
+}
+
+let addForm = ref({
+    taskCode: '',
+    startDate: '',
+    endDate: '',
+    remark: ''
+})
+let total = ref(0)
+let addRules = ref({
+    taskCode: [
+        {required: true, message: "商品编号不能为空", trigger: "blur"}
+    ],
+    startDate: [
+        {required: true, message: "生产开始时间不能为空", trigger: "change"}
+    ],
+    endDate: [
+        {required: true, message: "生产结束时间不能为空", trigger: "change"}
+    ]
+})
+let addList = ref([])
+
+let addItemShow = ref(false)
+let itemForm = ref({
+    itemName: '',
+    itemCode: '',
+    skuName: '',
+    skuCode: '',
+    pageNum: 1,
+    pageSize: 10
+})
+let itemList = ref([])
+const handleSizeChange = (size) => {
+    itemForm.value.pageSize = size
+    initList()
+}
+const handleCurrentChange = (page) => {
+    itemForm.value.pageNum = page
+    initList()
+}
+
+const createItem = () => {
+    proxy.$router.push({
+        path: '/basic/item',
+        query: {
+            fromProduct: true
+        }
+    })
+}
+
+const handleAddTask = () => {
+    let list = addList.value?.map(item => {
+        return {
+            taskItemSkuId: item.itemSku.id,
+            versionId: item.versionId,
+            quantity: item.quantity
+        }
+    })
+    if(route.query.data) {
+        editTask({
+            id: route.query.data,
+            ...addForm.value,
+            taskItemSkuDtoList: [ ...list ]
+        }).then(res => {
+            if(res.code == 200 ) {
+                ElMessage({
+                    type: 'success',
+                    message: res.msg
+                })
+            } else {
+                ElMessage({
+                    type: 'error',
+                    message: res.msg
+                })
+            }
+        })
+    } else {
+        addTask({
+            ...addForm.value,
+            taskItemSkuDtoList: [ ...list ]
+        }).then(res => {
+            if(res.code == 200 ) {
+                ElMessage({
+                    type: 'success',
+                    message: res.msg
+                })
+            } else {
+                ElMessage({
+                    type: 'error',
+                    message: res.msg
+                })
+            }
+        })
+    }
+}
+const handleCancel = () => {
+
+}
+
+let selected = ref([])
+const handleSelectChange = (rows) => {
+    selected.value = rows
+}
+const handleSelectCancel = () => {
+    selected.value = []
+    addItemShow.value = false
+}
+const handleSelectConfirm = () => {
+    addList.value = selected.value
+    addItemShow.value = false
+}
+const initList = () => {
+    addItemShow.value = true
+    listItemSkuPage({
+        ...itemForm.value
+    }).then(res => {
+        itemList.value = res.rows
+        total.value = res.total
+    })
+}
+
+let BOMList = ref([])
+const initBOMVersion = () => {
+    BOMVersion({
+        skuId: ''
+    }).then(res => {
+        BOMList.value = res.data
+    })
+}
+
+let isView = ref(false)
+onMounted(() => {
+    initBOMVersion()
+    if(route.query.data) {
+        detailTask(route.query.data).then(res => {
+            if(res.code == 200){
+
+            }
+        })
+    }
+    if(route.query.type) {
+        isView.value = true
+    }
+})
+
+</script>
+
+<style scoped>
+.app-container{
+    height: calc(100vh - 84px);
+}
+.title{
+    margin: 0 0 20px 20px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+.btn{
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+.left{
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+.right{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+.content{
+    height: calc(100% - 40px);
+}
+.footer{
+    height: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+</style>

+ 273 - 0
src/views/production/task/index.vue

@@ -0,0 +1,273 @@
+<template>
+    <div class="app-container">
+        <el-form :model="form" label-width="100">
+            <el-row :gutter="10">
+                <el-col :span="8">
+                    <el-form-item label="任务编号">
+                        <el-input v-model="form.taskCode" clearable />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="开始时间">
+                        <el-date-picker
+                            type="datetimerange"
+                            v-model="form.DateFrom"
+                            format="yyyy-MM-DD HH:mm:ss"
+                            clearable
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="结束时间">
+                        <el-date-picker
+                            type="datetimerange"
+                            v-model="form.DateTo"
+                            format="yyyy-MM-DD HH:mm:ss"
+                            clearable
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="状态">
+                        <el-select v-model="form.status" clearable style="width: 100%">
+                            <el-option value="1" label="1"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="创建时间">
+                        <el-date-picker
+                            style="width: 100%"
+                            type="datetime"
+                            clearable
+                            v-model="form.createTime"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-button type="primary" icon="Search" @click="initTaskList">搜索</el-button>
+                    <el-button icon="Refresh" @click="reset">重置</el-button>
+                    <el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
+                </el-col>
+            </el-row>
+        </el-form>
+        <el-table
+            :data="list"
+        >
+            <el-table-column prop="taskCode" label="任务编号"></el-table-column>
+            <el-table-column prop="startDate" label="生产开始时间"></el-table-column>
+            <el-table-column prop="endDate" label="生产结束时间"></el-table-column>
+            <el-table-column prop="status" label="状态">
+                <template #default="scope">
+                    <span class="one" v-if="scope.row.status === 1">待生产</span>
+                    <span class="two" v-if="scope.row.status === 2">生产完成</span>
+                    <span class="three" v-if="scope.row.status === 3">已作废</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="quantity" label="目标数量"></el-table-column>
+            <el-table-column prop="createTime" label="创建时间"></el-table-column>
+            <el-table-column prop="createBy" label="创建人"></el-table-column>
+            <el-table-column label="操作" width="240">
+                <template #default="scope">
+                    <el-button link type="primary" @click="handleEdit(scope, 'view')">详情</el-button>
+                    <el-button link type="primary" v-if="scope.row.status === 1" @click="handleEdit(scope)">编辑</el-button>
+                    <el-button link type="primary" v-if="scope.row.status === 1" @click="handleConfirm(scope)">生产完成</el-button>
+                    <el-button link type="primary" v-if="scope.row.status != 3" @click="handleRevoke(scope)">作废</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination">
+            <el-pagination
+                :current-page="form.current"
+                :page-size="form.size"
+                background
+                small
+                :total="total"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+            ></el-pagination>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, ref} from "vue";
+const { proxy } = getCurrentInstance();
+import { ElMessageBox, ElMessage } from 'element-plus'
+import { taskList, taskComplete, taskRevoke } from '@/api/production/task'
+
+let form = ref({
+    taskCode: '',
+    DateFrom: [],
+    DateTo: [],
+    status: '',
+    createTime: ''
+})
+let total = ref(0)
+let list = ref([])
+
+const initTaskList = () => {
+    let params = {
+        taskCode: form.value.taskCode,
+        startDateFrom: form.value.DateFrom[0],
+        endDateFrom: form.value.DateFrom[1],
+        startDateTo: form.value.DateTo[0],
+        endDateTo: form.value.DateTo[1],
+        status: form.value.status,
+        createTime: form.value.createTime
+    }
+    taskList({
+        wmsTaskQueryDto: { ...params }
+    }).then(res => {
+        if(res.code == 200) {
+            list.value = res.data
+            total.value = res.data.total
+        } else {
+            list.value = []
+            total.value = 0
+        }
+    })
+}
+
+const reset = () => {
+    form.value = {
+        taskCode: '',
+        DateFrom: [],
+        DateTo: [],
+        status: '',
+        createTime: ''
+    }
+}
+
+const handleAdd = () => {
+    proxy.$router.push({
+        path: '/productionTaskEdit'
+    })
+}
+const handleSizeChange = (size) => {
+    form.value.size = size
+}
+const handleCurrentChange = (page) => {
+    form.value.current = page
+}
+const handleEdit = (scope, type) => {
+    proxy.$router.push({
+        path: '/productionTaskEdit',
+        query: {
+            data: scope.row.id,
+            type: type
+        }
+    })
+}
+const handleConfirm = (scope) => {
+    ElMessageBox.confirm(
+        '确定该生产任务已完成了生产了吗?',
+        '系统提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'success',
+        }
+    )
+        .then(() => {
+            taskComplete(scope.row.id).then(res => {
+                if(res.code == 200) {
+                    initTaskList()
+                    ElMessage({
+                        type: 'success',
+                        message: res.msg,
+                    })
+                } else {
+                    ElMessage({
+                        type: 'error',
+                        message: res.msg,
+                    })
+                }
+             })
+        })
+        .catch(() => {
+            // ElMessage({
+            //     type: 'info',
+            //     message: 'Delete canceled',
+            // })
+        })
+}
+const handleRevoke = (scope) => {
+    ElMessageBox.confirm(
+        '确定该生产任务要作废吗?',
+        '系统提示',
+        {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'success',
+        }
+    )
+        .then(() => {
+            taskRevoke(scope.row.id).then(res => {
+                if(res.code == 200) {
+                    initTaskList()
+                    ElMessage({
+                        type: 'success',
+                        message: res.msg,
+                    })
+                } else {
+                    ElMessage({
+                        type: 'error',
+                        message: res.msg,
+                    })
+                }
+            })
+        })
+        .catch(() => {
+            // ElMessage({
+            //     type: 'info',
+            //     message: 'Delete canceled',
+            // })
+        })
+}
+
+onMounted(() => {
+    initTaskList()
+})
+</script>
+
+<style scoped lang="scss">
+.one{
+    display: block;
+    width: 60px;
+    text-align: center;
+    background: #FE7300;
+    border-radius: 2px;
+    font-size: 12px;
+    color: white;
+}
+.two{
+    display: block;
+    width: 60px;
+    text-align: center;
+    background: #0093FF;
+    border-radius: 2px;
+    font-size: 12px;
+    color: white;
+}
+.three{
+    display: block;
+    width: 60px;
+    text-align: center;
+    background: #E7E7E7;
+    border-radius: 2px;
+    font-size: 12px;
+}
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+</style>

+ 195 - 0
src/views/production/task/list.vue

@@ -0,0 +1,195 @@
+<template>
+    <div class="app-container">
+        <el-form :model="form" label-width="100">
+            <el-row :gutter="10">
+                <el-col :span="8">
+                    <el-form-item label="任务编号">
+                        <el-input v-model="form.taskCode" clearable />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="商品名称">
+                        <el-input v-model="form.itemName" clearable />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="商品编号">
+                        <el-input v-model="form.itemCode" clearable />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="规格名称">
+                        <el-input v-model="form.skuName" clearable />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="BOM版本">
+                        <el-select v-model="form.versionId" clearable style="width: 100%">
+                            <el-option v-for="item in BOMList" :value="item.id" :label="item.version"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="完成时间">
+                        <el-date-picker
+                            type="daterange"
+                            v-model="form.completionTime"
+                            format="YYYY-MM-DD"
+                            value-format="YYYY-MM-DD"
+                            clearable
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-form-item label="创建时间">
+                        <el-date-picker
+                            type="daterange"
+                            v-model="form.createTime"
+                            format="YYYY-MM-DD"
+                            value-format="YYYY-MM-DD"
+                            clearable
+                            range-separator="至"
+                            start-placeholder="开始时间"
+                            end-placeholder="结束时间"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                    <el-button type="primary" icon="Search" @click="initList">搜索</el-button>
+                    <el-button icon="refresh" @click="refresh">重置</el-button>
+                </el-col>
+            </el-row>
+        </el-form>
+        <el-table
+            :data="list"
+        >
+            <el-table-column prop="taskCode" label="任务编号"></el-table-column>
+            <el-table-column label="商品信息">
+                <template #default="{ row }">
+                    <div>{{ row.itemName + (row.itemCode ? ('(' +  row.itemCode + ')') : '') }}</div>
+                    <div v-if="row.itemBrand">{{ row.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.itemBrand)?.brandName) : '' }}</div>
+                </template>
+            </el-table-column>
+            <el-table-column label="规格信息">
+                <template #default="{ row }">
+                    <div>{{ row.skuName }}</div>
+                    <div v-if="row.skuCode">编号:{{ row.skuCode }}</div>
+                </template>
+            </el-table-column>
+            <el-table-column prop="version" label="BOM版本"></el-table-column>
+            <el-table-column prop="quantity" label="生产数量"></el-table-column>
+            <el-table-column prop="completionTime" label="完成时间"></el-table-column>
+        </el-table>
+        <div class="pagination">
+            <el-pagination
+                :current-page="form.current"
+                :page-size="form.size"
+                background
+                small
+                :total="total"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+            ></el-pagination>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import {BOMVersion, taskDetails} from '@/api/production/task'
+import {useWmsStore} from "@/store/modules/wms";
+
+let form = ref({
+    taskCode: '',
+    itemName: '',
+    itemCode: '',
+    skuName: '',
+    versionId: '',
+    completionTime: [],
+    createTime: [],
+    pageSize: 10,
+    pageNum: 1
+})
+let list = ref([])
+let total = ref(0)
+
+const handleSizeChange = (size) => {
+    form.value.pageSize = size
+    initList()
+}
+const handleCurrentChange = (page) => {
+    form.value.pageNum = page
+    initList()
+}
+const initList = () => {
+    let params = {
+        taskCode: form.value.taskCode,
+        itemName: form.value.itemName,
+        itemCode: form.value.itemCode,
+        skuName: form.value.skuName,
+        versionId: form.value.versionId,
+        startCompletionTime: form.value.completionTime[0],
+        endCompletionTime: form.value.completionTime[1],
+        startCreateTime: form.value.createTime[0],
+        endCreateTime: form.value.createTime[1],
+        pageSize: form.value.pageSize,
+        pageNum: form.value.pageNum
+    }
+    taskDetails({
+        ...params
+    }).then(res => {
+        if(res.code == 200) {
+            list.value = res.data.rows
+            total.value = res.data.total
+        } else {
+            list.value = []
+            total.value = 0
+        }
+    })
+}
+const refresh = () => {
+    form.value = {
+        taskCode: '',
+        itemName: '',
+        itemCode: '',
+        skuName: '',
+        versionId: '',
+        completionTime: [],
+        createTime: [],
+        pageSize: 10,
+        pageNum: 1
+    }
+    initList()
+}
+
+let BOMList = ref([])
+const getBOM = () => {
+    BOMVersion({
+        skuId: ''
+    }).then(res => {
+        if(res.code == 200) {
+            BOMList.value = res.data
+        } else {
+            BOMList.value = []
+        }
+    })
+}
+
+onMounted(() => {
+    initList()
+    getBOM()
+})
+
+</script>
+
+<style scoped>
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+</style>

+ 177 - 18
src/views/wms/basic/item/index.vue

@@ -18,6 +18,13 @@
             ></el-option>
           </el-select>
         </el-form-item>
+        <el-form-item label="商品类型" prop="itemType">
+            <el-select v-model="queryParams.itemType" clearable filterable>
+                <el-option value="1" label="成品"></el-option>
+                <el-option value="2" label="原料"></el-option>
+                <el-option value="3" label="包材"></el-option>
+            </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>
@@ -162,18 +169,29 @@
               </el-col>
             </el-row>
             <el-row :gutter="24">
+                <el-col :span="12">
+                    <el-form-item label="商品类型" prop="itemType">
+                        <el-select :disabled="dialog.title != '新增商品'" v-model="form.itemType" clearable filterable style="width: 100%">
+                            <el-option value="1" label="成品"></el-option>
+                            <el-option value="2" label="原料"></el-option>
+                            <el-option value="3" label="包材"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
               <el-col :span="12">
                 <el-form-item label="商品编号" prop="itemCode">
                   <el-input v-model="form.itemCode" placeholder="请输入编号"/>
                 </el-form-item>
               </el-col>
-              <el-col :span="12">
-                <el-form-item label="商品单位" prop="unit">
-                  <el-input v-model="form.unit" placeholder="请输入单位类别"/>
-                </el-form-item>
-              </el-col>
             </el-row>
             <el-row :gutter="24">
+                <el-col :span="12">
+                    <el-form-item label="商品单位" prop="unit">
+                        <el-select style="width: 100%" v-model="form.unit" placeholder="请选择商品单位">
+                            <el-option :value="item.value" :label="item.label" v-for="(item, index) in conventional_units"></el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
               <el-col :span="12">
                 <el-form-item label="商品品牌" prop="itemBrand">
                   <el-select v-model="form.itemBrand" clearable filterable style="width: 100%!important;">
@@ -205,18 +223,30 @@
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column label="编号/条码" width="250">
-                <template #default="scope">
-                  <div class="flex-center">
-                    <span class="mr5" style="width: 50px">编号</span>
-                    <el-input v-model="scope.row.skuCode" />
-                  </div>
-                  <div class="flex-center mt5">
-                    <span class="mr5" style="width: 50px">条码</span>
-                    <el-input v-model="scope.row.barcode" />
-                  </div>
-                </template>
-              </el-table-column>
+                <el-table-column label="编号/条码" width="250">
+                    <template #default="scope">
+                        <div class="flex-center">
+                            <span class="mr5" style="width: 50px">编号</span>
+                            <el-input v-model="scope.row.skuCode" />
+                        </div>
+                        <div class="flex-center mt5">
+                            <span class="mr5" style="width: 50px">条码</span>
+                            <el-input v-model="scope.row.barcode" />
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="计量单位" width="250">
+                    <template #default="scope">
+                        <div class="flex-center">
+                            <el-select :disabled="scope.row.isMultiUom" v-model="scope.row.unit">
+                                <el-option :value="item.value" :label="item.label" v-for="(item, index) in conventional_units"></el-option>
+                            </el-select>
+                        </div>
+                        <div class="flex-center mt5">
+                            <el-checkbox v-model="scope.row.isMultiUom" @change="handleManyUnit($event, scope)">多单位</el-checkbox>
+                        </div>
+                    </template>
+                </el-table-column>
               <el-table-column label="长/宽/高(cm)" width="200">
                 <template #default="scope">
                   <div class="flex-center">
@@ -314,6 +344,46 @@
       </template>
       <div id="qrcode"></div>
     </el-dialog>
+    <!--多单位配置-->
+      <el-dialog title="计量单位" v-model="addManyUnitShow" width="600px" append-to-body>
+          <el-form :model="unitForm" label-width="120">
+              <el-form-item label="出库默认单位">
+                  <el-select v-model="unitForm.outboundUnit" style="width: 100%">
+                      <el-option :value="item.value" :label="item.label" v-for="(item, index) in quantity_unit"></el-option>
+                  </el-select>
+              </el-form-item>
+              <el-form-item label="入库默认单位">
+                  <el-select v-model="unitForm.warehousingUnit" style="width: 100%">
+                      <el-option :value="item.value" :label="item.label" v-for="(item, index) in quantity_unit"></el-option>
+                  </el-select>
+              </el-form-item>
+              <el-form-item label="主单位">
+                  <div style="display: flex; align-items: center; justify-content: flex-start; width: 100%;">
+                      <el-select v-model="unitForm.mainUnit" style="width: 40%">
+                          <el-option :value="item.value" :label="item.label" v-for="(item, index) in quantity_unit"></el-option>
+                      </el-select>
+                      <span style="margin-left: 10px">主单位应为最小度量单位</span>
+                  </div>
+              </el-form-item>
+              <el-form-item label="辅助单位" v-for="sub in unitForm.unitAuxiliaryBo">
+                  <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
+                      <el-select v-model="sub.auxiliaryUnit" style="width: 40%">
+                          <el-option :value="item.value" :label="item.label" v-for="(item, index) in quantity_unit"></el-option>
+                      </el-select>
+                      <span>=</span>
+                      <el-input v-model="sub.quantity" style="width: 40%" />
+                      <span>个</span>
+                  </div>
+              </el-form-item>
+              <el-button icon="Plus" @click="handleAddUnit">增加辅助单位</el-button>
+          </el-form>
+          <template #footer>
+              <div class="dialog-footer">
+                  <el-button :loading="unitLoading" type="primary" @click="handleSubmitUnit">确 定</el-button>
+                  <el-button @click="handleCancelUnit">取 消</el-button>
+              </div>
+          </template>
+      </el-dialog>
     <div id="outSkuIdBox" style="display: none">
       <img :src="qrcode"/>
       <canvas ref="barcode"></canvas>
@@ -324,7 +394,7 @@
 <script setup name="Item">
 import {getItem, delItem, addItem, updateItem} from '@/api/wms/item';
 import {computed, getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from 'vue';
-import {ElForm, ElTree, ElTreeSelect} from 'element-plus';
+import {ElForm, ElMessage, ElTree, ElTreeSelect,ElMessageBox} from 'element-plus';
 import {
   updateItemCategory,
   addItemCategory,
@@ -337,6 +407,7 @@ import {useRoute} from "vue-router";
 import Qrcode from 'qrcode'
 import JSBarcode from 'jsbarcode'
 import {useWmsStore} from '@/store/modules/wms'
+import {delDemo} from "@/api/demo/demo";
 
 const barcode = ref(null)
 const route = useRoute()
@@ -352,6 +423,10 @@ const itemCategoryTreeOptionsList = computed(() => {
   });
   return data;
 });
+
+const { conventional_units } = proxy.useDict('conventional_units')
+const { quantity_unit } = proxy.useDict('quantity_unit')
+
 const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
@@ -408,6 +483,7 @@ const initFormData = {
   unit: undefined,
   itemBrand: undefined,
   remark: undefined,
+  itemType: undefined
 }
 const initCategoryFormData = {
   id: undefined,
@@ -445,6 +521,12 @@ const data = reactive({
     remark: [
       {required: true, message: "备注不能为空", trigger: "blur"}
     ],
+    itemType: [
+        {required: true, message: "商品类型不能为空", trigger: "change"}
+    ],
+    unit: [
+        {required: true, message: "商品单位不能为空", trigger: "change"}
+    ]
   }
 });
 const categoryData = reactive({
@@ -613,6 +695,7 @@ const handleAdd = () => {
   });
 }
 /** 修改按钮操作 */
+let editData = ref({})
 const handleUpdate = (row) => {
   resetItemSkuList()
   skuLoading.value = true
@@ -625,6 +708,7 @@ const handleUpdate = (row) => {
     Object.assign(skuForm.itemSkuList, res.data)
     skuLoading.value = false
     Object.assign(form.value, row.item);
+    Object.assign(editData.value, row.item)
   });
 }
 const handleQueryType = (node, data) => {
@@ -642,6 +726,11 @@ const handleQueryType = (node, data) => {
 /** 提交按钮 */
 const submitForm = () => {
   form.value.sku = skuForm.itemSkuList
+    if(form.value.sku.length > 0) {
+        form.value.sku.forEach(item => {
+            item.isMultiUom = item.isMultiUom?1:0
+        })
+    }
   itemFormRef.value.validate(async (valid) => {
     if (valid) {
       let flag = true
@@ -743,7 +832,77 @@ onMounted(() => {
       handleAdd()
     }
   })
+  if(proxy.$route.query.fromProduct) {
+      handleAdd()
+  }
 });
+
+// 计多单位配置
+let unitForm = ref({
+    outboundUnit: '',
+    warehousingUnit: '',
+    mainUnit: '',
+    unitAuxiliaryBo: [
+        {
+            auxiliaryUnit: '',
+            quantity: 0
+        }
+    ]
+})
+let manyUnitShow = ref(false)
+let addManyUnitShow = ref(false)
+let unitLoading = ref(false)
+
+const handleAddUnit = () => {
+  unitForm.value.unitAuxiliaryBo.push({
+      auxiliaryUnit: '',
+      quantity: 0
+  })
+}
+
+let itemListIndex = ref(0)
+const handleManyUnit = (e, scope) => {
+    itemListIndex.value = scope.$index
+    if(form.value.id && form.value.id === editData.value.id&&e) {
+        if(!editData.value.isMultiUom) {
+            ElMessageBox.confirm(
+                '针对单单位商品修改为多单位商品时,可能会造成存计算误差,一经修改多单位无法修改为原单单位,请谨慎修改。<br>1.原单位为克,但是现在修改为多单位"千克"和"吨",基本单位为"千克"<br>2.则该商品之前的单据和库存统计表里,会用"千克"替换"克"这个单位<br>3.数量上是没有变化切正确,但是由于我们认知的原因,认为"千克"=1000"克"<br>这就可能造成认知上的数量和库存误差,所以请谨慎修改,一经修改多单位无法更改回原单单位。', // 消息内容
+                '系统提示', // 标题
+                {
+                    type: '', // 图标类型:success/warning/info/error/primary
+                    confirmButtonText: '确定修改', // 确认按钮文字
+                    cancelButtonText: '取消', // 取消按钮文字
+                    dangerouslyUseHTMLString: true
+                }
+            )
+                .then(() => {
+                    manyUnitShow.value = e
+                    if(e) {
+                        addManyUnitShow.value = true
+                    }
+                })
+                .catch(() => {
+
+                })
+        }
+    } else {
+        manyUnitShow.value = e
+        if(e) {
+            addManyUnitShow.value = true
+        }
+    }
+}
+const handleSubmitUnit = () => {
+    skuForm.itemSkuList[itemListIndex.value].unitConfig = {
+      ...unitForm.value
+    }
+    skuForm.itemSkuList[itemListIndex.value].unit = ''
+    addManyUnitShow.value = false
+}
+const handleCancelUnit = ()=> {
+    addManyUnitShow.value = false
+}
+
 </script>
 <style>
 .custom-tree-node {

+ 1210 - 0
src/views/wms/basic/product/index.vue

@@ -0,0 +1,1210 @@
+<template>
+    <div class="app-container">
+        <el-card>
+            <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
+                <el-form-item label="商品编号" prop="itemCode">
+                    <el-input v-model="queryParams.itemCode" placeholder="请输入商品编号" clearable @keyup.enter="handleQuery"/>
+                </el-form-item>
+                <el-form-item label="商品名称" prop="itemName">
+                    <el-input v-model="queryParams.itemName" placeholder="请输入商品名称" clearable @keyup.enter="handleQuery"/>
+                </el-form-item>
+                <el-form-item label="商品品牌" prop="itemBrand">
+                    <el-select v-model="queryParams.itemBrand" clearable filterable>
+                        <el-option
+                            v-for="item in useWmsStore().itemBrandList"
+                            :key="item.id"
+                            :label="item.brandName"
+                            :value="item.id"
+                        ></el-option>
+                    </el-select>
+                </el-form-item>
+<!--                <el-form-item label="商品类型" prop="type">
+                    <el-select v-model="queryParams.type" clearable filterable>
+                        <el-option value="1" label="成品"></el-option>
+                        <el-option value="2" label="原料"></el-option>
+                        <el-option value="3" label="包材"></el-option>
+                    </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>
+        </el-card>
+        <el-card class="mt20">
+            <div style="display: flex;align-items: start">
+                <div>
+                    <div style="display: flex;align-items: center;justify-content: space-between">
+                        <span style="font-size: 18px;line-height: 18px">商品分类</span>
+                        <el-button class="mr10" style="font-size:12px;line-height: 14px" plain
+                                   @click="handleAddType(false)"
+                                   type="primary" icon="Plus">新增分类
+                        </el-button>
+                    </div>
+                    <el-tree
+                        :data="itemCategoryTreeOptionsList"
+                        :props="{ value: 'id', label: 'label', children: 'children' }"
+                        value-key="id"
+                        style="width: 400px;"
+                        class="mr10 mt10"
+                        @nodeClick="handleQueryType"
+                        :default-expand-all="true"
+                        :highlight-current="true"
+                        node-key="label"
+                        current-node-key="全部"
+                        draggable
+                        :allow-drop="collapse"
+                        @node-drop="handleNodeDrop"
+                        :expand-on-click-node="false"
+                    >
+                        <template #default="{ node, data }">
+            <span class="custom-tree-node">
+              <span>{{ node.label }}</span>
+              <span>
+                <el-button type="primary" @click.stop="append(data)" link
+                           v-if="data.label !== '全部' && node.level < 2" icon="Plus" style="font-size: 12px">新增子分类</el-button>
+                <el-button type="primary" @click.stop="remove(node, data)" link
+                           v-if="data.label !== '全部'" icon="Delete" style="font-size: 12px">删除</el-button>
+                <el-button type="primary" icon="Edit" @click.stop="edit(node, data)" link
+                           v-if="data.label !== '全部'" style="font-size: 12px">修改</el-button>
+              </span>
+            </span>
+                        </template>
+                    </el-tree>
+                </div>
+                <div style="width: 100%;position: relative">
+                    <div style="display: flex;align-items: start;justify-content: space-between">
+                        <span class="mr10" style="font-size: 18px;">商品列表</span>
+                        <el-button type="primary" plain icon="Plus" @click="handleAdd" class="mb10">新增商品</el-button>
+                    </div>
+                    <el-table :data="itemList" @selection-change="handleSelectionChange" :span-method="spanMethod" border empty-text="暂无商品" v-loading="loading" cell-class-name="my-cell">
+                        <el-table-column label="商品信息" prop="itemId">
+                            <template #default="{ row }">
+                                <div>{{ row.item.itemName + (row.item.itemCode ? ('(' +  row.item.itemCode + ')') : '') }}</div>
+                                <div v-if="row.item.itemBrand">{{ row.item.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.item.itemBrand)?.brandName) : '' }}</div>
+                                <div v-if="row.item.itemCategory">{{ row.item.itemCategory ? ('分类:' + useWmsStore().itemCategoryMap.get(row.item.itemCategory)?.categoryName) : '' }}</div>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="规格信息" prop="skuName" align="left">
+                            <template #default="{ row }">
+                                <div>{{ row.itemSku.skuName }}</div>
+                                <div v-if="row.itemSku.skuCode">编号:{{ row.itemSku.skuCode }}</div>
+                                <div v-if="row.itemSku.barcode">条码:{{ row.itemSku.barcode }}</div>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="金额(元)" width="160" align="left">
+                            <template #default="{ row }">
+                                <div v-if="row.itemSku.costPrice" class="flex-space-between">
+                                    <span>成本价:</span>
+                                    <div>{{ (row.itemSku.costPrice || row.itemSku.costPrice === 0) ? row.itemSku.costPrice : '' }}</div>
+                                </div>
+                                <div v-if="row.itemSku.sellingPrice" class="flex-space-between">
+                                    <span>销售价:</span>
+                                    <div>{{ (row.itemSku.sellingPrice || row.itemSku.sellingPrice === 0) ? row.itemSku.sellingPrice : '' }}</div>
+                                </div>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="重量(kg)" width="160" align="left">
+                            <template #default="{ row }">
+                                <div v-if="row.itemSku.netWeight" class="flex-space-between">
+                                    <span>净重:</span>
+                                    <div>
+                                        {{ (row.itemSku.netWeight || row.itemSku.netWeight === 0) ? row.itemSku.netWeight : '' }}
+                                    </div>
+                                </div>
+                                <div v-if="row.itemSku.grossWeight" class="flex-space-between">
+                                    <span>毛重:</span>
+                                    <div>
+                                        {{ (row.itemSku.grossWeight || row.itemSku.grossWeight === 0) ? row.itemSku.grossWeight : '' }}
+                                    </div>
+                                </div>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="物料清单" align="right" width="250">
+                            <template #default="{ row }">
+                                <div style="color: #409eff; cursor: pointer" @click="handleShowProduct(row)">{{ row.itemSku.quantity }}</div>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="操作" align="right" width="200">
+                            <template #default="{ row }">
+                                <el-button link type="primary" @click="handleShowProduct(row)" icon="Delete">物料清单</el-button>
+                                <el-button link type="primary" @click="configurate(row, 1)" icon="Edit">BOM配置</el-button>
+                            </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"/>
+                </div>
+            </div>
+        </el-card>
+        <!-- 添加或修改物料对话框 -->
+        <el-drawer :title="dialog.title" v-model="dialog.visible" size="80%" append-to-body :close-on-click-modal="false">
+            <div v-loading="skuLoading">
+                <el-card>
+                    <el-form ref="itemFormRef" :model="form" :rules="rules" label-width="108px">
+                        <el-row :gutter="24">
+                            <el-col :span="12">
+                                <el-form-item label="商品名称" prop="itemName">
+                                    <el-input v-model="form.itemName" placeholder="请输入名称"/>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="10">
+                                <el-form-item label="商品分类" prop="itemCategory">
+                                    <el-tree-select
+                                        ref="treeRef"
+                                        v-model="form.itemCategory"
+                                        :data="itemCategoryTreeSelectList"
+                                        :props="{ value: 'id', label: 'label', children: 'children' }"
+                                        value-key="id"
+                                        placeholder="请选择分类"
+                                        check-strictly
+                                        style="width: 100%!important;"
+                                    />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="1">
+                                <el-button link icon="Plus" type="primary" style="height: 32px!important;line-height: 32px!important;"
+                                           @click="handleAddType(true)">新增分类
+                                </el-button>
+                            </el-col>
+                        </el-row>
+                        <el-row :gutter="24">
+                            <el-col :span="12">
+                                <el-form-item label="商品类型" prop="type">
+                                    <el-select v-model="form.type" clearable filterable style="width: 100%">
+                                        <el-option value="1" label="成品"></el-option>
+                                        <el-option value="2" label="原料"></el-option>
+                                        <el-option value="3" label="包材"></el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="商品编号" prop="itemCode">
+                                    <el-input v-model="form.itemCode" placeholder="请输入编号"/>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-row :gutter="24">
+                            <el-col :span="12">
+                                <el-form-item label="商品单位" prop="unit">
+                                    <el-input v-model="form.unit" placeholder="请输入单位类别"/>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="商品品牌" prop="itemBrand">
+                                    <el-select v-model="form.itemBrand" clearable filterable style="width: 100%!important;">
+                                        <el-option
+                                            v-for="item in useWmsStore().itemBrandList"
+                                            :key="item.id"
+                                            :label="item.brandName"
+                                            :value="item.id"
+                                        ></el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                    </el-form>
+                </el-card>
+                <el-card class="mt20">
+                    <template #header>
+                        <div class="card-header">
+                            <span>规格</span>
+                        </div>
+                    </template>
+                    <el-form :model="skuForm" :rules="skuRules" ref="skuFormRef" :show-message="false">
+                        <el-table :data="skuForm.itemSkuList" border cell-class-name="my-cell">
+                            <el-table-column label="规格名称" prop="skuName">
+                                <template #default="scope">
+                                    <el-form-item :prop="'itemSkuList.' + scope.$index + '.skuName'" :rules="skuRules.skuName"
+                                                  style="margin-bottom: 0!important;">
+                                        <el-input v-model="scope.row.skuName" placeholder="请输入规格名称"/>
+                                    </el-form-item>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="编号/条码" width="250">
+                                <template #default="scope">
+                                    <div class="flex-center">
+                                        <span class="mr5" style="width: 50px">编号</span>
+                                        <el-input v-model="scope.row.skuCode" />
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <span class="mr5" style="width: 50px">条码</span>
+                                        <el-input v-model="scope.row.barcode" />
+                                    </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="计量单位" width="250">
+                                <template #default="scope">
+                                    <div class="flex-center">
+                                        <el-select :disabled="scope.row.many" v-model="scope.row.unitType">
+                                            <el-option value="1" label="单位1"></el-option>
+                                        </el-select>
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <el-checkbox v-model="scope.row.many" @change="handleManyUnit">多单位</el-checkbox>
+                                    </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="长/宽/高(cm)" width="200">
+                                <template #default="scope">
+                                    <div class="flex-center">
+                                        <span class="mr5">长</span>
+                                        <el-input-number :controls="false" :min="0" :precision="1" class="mr5" v-model="scope.row.length" />
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <span class="mr5">宽</span>
+                                        <el-input-number :controls="false" :min="0" :precision="1" class="mr5" v-model="scope.row.width" />
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <span class="mr5">高</span>
+                                        <el-input-number :controls="false" :min="0" :precision="1" v-model="scope.row.height" />
+                                    </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="净重/毛重(kg)" width="240">
+                                <template #default="scope">
+                                    <div class="flex-center">
+                                        <span class="mr5">净重</span>
+                                        <el-input-number :controls="false" :min="0" :precision="3" v-model="scope.row.netWeight"/>
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <span class="mr5">毛重</span>
+                                        <el-input-number :controls="false" :min="0" :precision="3" v-model="scope.row.grossWeight"/>
+                                    </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="成本价/销售价(元)" width="240">
+                                <template #default="scope">
+                                    <div class="flex-center">
+                                        <span class="mr5">成本价</span>
+                                        <el-input-number :controls="false" :min="0" :precision="2" v-model="scope.row.costPrice"/>
+                                    </div>
+                                    <div class="flex-center mt5">
+                                        <span class="mr5">销售价</span>
+                                        <el-input-number :controls="false" :min="0" :precision="2" v-model="scope.row.sellingPrice"/>
+                                    </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="操作" class-name="small-padding fixed-width" width="80" align="right">
+                                <template #default="scope">
+                                    <el-button link icon="Delete" type="primary" @click="handleDeleteItemSku(scope.row, scope.$index)">删除</el-button>
+                                </template>
+                            </el-table-column>
+                            <template #append v-if="skuForm.itemSkuList.length">
+                                <div style="padding: 6px 2px 6px 2px;text-align: center;">
+                                    <el-button text class="add-btn" icon="Plus" type="primary" @click="onAppendBtnClick">添加商品规格
+                                    </el-button>
+                                </div>
+                            </template>
+                            <template #empty>
+                                <div style="padding: 2px 2px 6px 2px;text-align: center;width: 100%!important;">
+                                    <el-button text class="add-btn" icon="Plus" type="primary" @click="onAppendBtnClick">添加商品规格
+                                    </el-button>
+                                </div>
+                            </template>
+                        </el-table>
+                    </el-form>
+                </el-card>
+            </div>
+
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
+                    <el-button @click="cancel">取 消</el-button>
+                </div>
+            </template>
+        </el-drawer>
+        <!-- 添加或修改物料类型对话框 -->
+        <el-dialog :title="categoryDialog.title" v-model="categoryDialog.visible" width="500px" append-to-body
+                   :close-on-click-modal="false">
+            <el-form ref="itemCategoryFormRef" :model="categoryForm" :rules="typeRules" label-width="128px" @submit.native.prevent>
+                <el-form-item label="上级分类" prop="parentId">
+                    <el-tree-select
+                        v-model="categoryForm.parentId"
+                        :data="itemCategoryTreeSelectList"
+                        :props="{ value: 'id', label: 'label', children: 'children' }"
+                        value-key="id"
+                        placeholder="上级分类"
+                        check-strictly
+                        style="width: 100%!important;"
+                        clearable
+                    />
+                </el-form-item>
+                <el-form-item label="商品分类名称" prop="categoryName">
+                    <el-input v-model="categoryForm.categoryName" placeholder="请输入商品分类名称" @keyup.enter="submitCategoryForm"/>
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button :loading="buttonLoading" type="primary" @click="submitCategoryForm">确 定</el-button>
+                    <el-button @click="cancelType">取 消</el-button>
+                </div>
+            </template>
+            <div id="qrcode"></div>
+        </el-dialog>
+        <el-drawer title="物料清单" v-model="productShow" size="80%" append-to-body :close-on-click-modal="false">
+            <el-form :model="BOMForm" label-width="120">
+                <el-form-item label="BOM版本">
+                    <el-select v-model="BOMForm.version" @change="handleShowProduct">
+                        <el-option v-for="item in BOMList" :value="item.id" :label="item.version"></el-option>
+                    </el-select>
+                </el-form-item>
+            </el-form>
+            <el-table :data="productList">
+
+                <el-table-column prop="itemName" label="商品名称"></el-table-column>
+                <el-table-column prop="itemCode" label="商品编号"></el-table-column>
+                <el-table-column prop="itemBrand" label="商品品牌"></el-table-column>
+                <el-table-column prop="skuName" label="规格名称"></el-table-column>
+                <el-table-column prop="version" label="BOM版本"></el-table-column>
+                <el-table-column prop="f" label="价格"></el-table-column>
+                <el-table-column prop="unit" label="单位"></el-table-column>
+                <el-table-column label="重量">
+                    <template #default="{ row }">
+                        <div v-if="row.netWeight" class="flex-space-between">
+                            <span>净重:</span>
+                            <div>
+                                {{ (row.netWeight || row.netWeight === 0) ? row.netWeight : '' }}
+                            </div>
+                        </div>
+                        <div v-if="row.grossWeight" class="flex-space-between">
+                            <span>毛重:</span>
+                            <div>
+                                {{ (row.grossWeight || row.grossWeight === 0) ? row.grossWeight : '' }}
+                            </div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="长宽高">
+                    <template #default="{ row }">
+                        {{ `${row.length?row.length:0}*${row.width?row.width:0}*${row.height?row.height:0}` }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作">
+                    <template #default="{ row }">
+                        <el-button size="small" @click="configurate(row)">BOM配置</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </el-drawer>
+        <el-drawer title="BOM配置" v-model="configurateShow" size="80%" append-to-body :close-on-click-modal="false">
+            <el-form :model="BOMDataForm" label-width="80">
+                <el-row :gutter="10">
+                    <el-col :span="8">
+                        <el-form-item label="BOM版本">
+                            <el-input v-model="BOMDataForm.version" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="商品名称">
+                            <el-input disabled v-model="BOMDataForm.itemName" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="商品编号">
+                            <el-input disabled v-model="BOMDataForm.itemCode" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="商品类型">
+                            <el-select disabled v-model="BOMDataForm.itemType" clearable filterable style="width: 100%">
+                                <el-option value="1" label="成品"></el-option>
+                                <el-option value="2" label="原料"></el-option>
+                                <el-option value="3" label="包材"></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item label="商品规格">
+                            <el-input disabled v-model="BOMDataForm.skuName" />
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+            </el-form>
+            <el-table :data="BOMDataList">
+                <el-table-column label="商品信息">
+                    <template #default="{ row }">
+                        <div>{{ row.item.itemName + (row.item.itemCode ? ('(' +  row.item.itemCode + ')') : '') }}</div>
+                        <div v-if="row.item.itemBrand">{{ row.item.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.item.itemBrand)?.brandName) : '' }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="itemType" label="类型"></el-table-column>
+                <el-table-column label="规格信息">
+                    <template #default="{ row }">
+                        <div>{{ row.itemSku.skuName }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="价格(元)">
+                    <template #default="{ row }">
+                        <div v-if="row.itemSku.costPrice" class="flex-space-between">
+                            <span>成本价:</span>
+                            <div>{{ (row.itemSku.costPrice || row.itemSku.costPrice === 0) ? row.itemSku.costPrice : '' }}</div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="quantity" label="数量">
+                    <template #default="{ row }">
+                        <el-input v-model="row.quantity" />
+                    </template>
+                </el-table-column>
+                <el-table-column prop="unit" label="单位">
+                    <template #default="{ row }">
+                        <el-select v-model="row.unit">
+                            <el-option :value="item.value" :label="item.label" v-for="(item, index) in conventional_units"></el-option>
+                        </el-select>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <template #footer>
+                <div class="btns">
+                    <div class="left">
+                        <el-button @click="handleAddUnit">添加物料</el-button>
+                    </div>
+                    <div class="right">
+                        <el-button @click="handleBOMDataCancel">取消</el-button>
+                        <el-button type="primary" @click="handleBOMDataConfirm">确定</el-button>
+                    </div>
+                </div>
+            </template>
+        </el-drawer>
+        <el-dialog title="添加物料" v-model="addShow">
+            <el-form :model="addForm" label-width="80">
+                <el-row :gutter="10">
+                    <el-col :span="8">
+                        <el-form-item prop="itemName" label="商品名称">
+                            <el-input v-model="addForm.itemName" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="itemCode" label="商品编码">
+                            <el-input v-model="addForm.itemCode" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="skuName" label="规格名称">
+                            <el-input v-model="addForm.skuName" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-form-item prop="itemType" label="商品类型">
+                            <el-select v-model="addForm.itemType" clearable filterable style="width: 100%">
+                                <el-option value="1" label="成品"></el-option>
+                                <el-option value="2" label="原料"></el-option>
+                                <el-option value="3" label="包材"></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="8">
+                        <el-button type="primary" @click="handleSearch">搜索</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+            <el-table
+                :data="materialList"
+                @selection-change="handleSelectChange"
+            >
+                <el-table-column type="selection"></el-table-column>
+                <el-table-column label="商品信息">
+                    <template #default="{ row }">
+                        <div>{{ row.item.itemName + (row.item.itemCode ? ('(' +  row.item.itemCode + ')') : '') }}</div>
+                        <div v-if="row.item.itemBrand">{{ row.item.itemBrand ? ('品牌:' + useWmsStore().itemBrandMap.get(row.item.itemBrand)?.brandName) : '' }}</div>
+                        <div v-if="row.item.itemCategory">{{ row.item.itemCategory ? ('分类:' + useWmsStore().itemCategoryMap.get(row.item.itemCategory)?.categoryName) : '' }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="规格信息">
+                    <template #default="{ row }">
+                        <div>{{ row.itemSku.skuName }}</div>
+                        <div v-if="row.itemSku.skuCode">编号:{{ row.itemSku.skuCode }}</div>
+                        <div v-if="row.itemSku.barcode">条码:{{ row.itemSku.barcode }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="价格(元)">
+                    <template #default="{ row }">
+                        <div v-if="row.itemSku.costPrice" class="flex-space-between">
+                            <span>成本价:</span>
+                            <div>{{ (row.itemSku.costPrice || row.itemSku.costPrice === 0) ? row.itemSku.costPrice : '' }}</div>
+                        </div>
+                        <div v-if="row.itemSku.sellingPrice" class="flex-space-between">
+                            <span>销售价:</span>
+                            <div>{{ (row.itemSku.sellingPrice || row.itemSku.sellingPrice === 0) ? row.itemSku.sellingPrice : '' }}</div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="重量(Kg)">
+                    <template #default="{ row }">
+                        <div v-if="row.itemSku.netWeight" class="flex-space-between">
+                            <span>净重:</span>
+                            <div>
+                                {{ (row.itemSku.netWeight || row.itemSku.netWeight === 0) ? row.itemSku.netWeight : '' }}
+                            </div>
+                        </div>
+                        <div v-if="row.itemSku.grossWeight" class="flex-space-between">
+                            <span>毛重:</span>
+                            <div>
+                                {{ (row.itemSku.grossWeight || row.itemSku.grossWeight === 0) ? row.itemSku.grossWeight : '' }}
+                            </div>
+                        </div>
+                    </template>
+                </el-table-column>
+                <el-table-column label="长宽高(cm)">
+                    <template #default="{ row }">
+                        <div>{{ getVolumeText(row.itemSku) }}</div>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <div class="pagination">
+                <el-pagination
+                    v-model:current-page="addForm.pageNum"
+                    v-model:page-size="addForm.pageSize"
+                    background
+                    small
+                    :total="addTotal"
+                    @size-change="handleSizeChange"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+            <template #footer>
+                <div class="btn">
+                    <el-button @click="handleSelectCancel">取消</el-button>
+                    <el-button type="primary" @click="handleSelectConfirm">确定</el-button>
+                </div>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup>
+
+import {getItem, delItem, addItem, updateItem, listItemPage, bomList, listItem} from '@/api/wms/item';
+import {computed, getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from 'vue';
+import {ElForm, ElMessage, ElTree, ElTreeSelect} from 'element-plus';
+import {
+    updateItemCategory,
+    addItemCategory,
+    delItemCategory,
+    updateOrderNum
+} from "@/api/wms/itemCategory";
+import {getRowspanMethod} from "@/utils/getRowSpanMethod";
+import {listItemSkuPage, delItemSku, listItemSku} from "@/api/wms/itemSku";
+import {useRoute} from "vue-router";
+import Qrcode from 'qrcode'
+import JSBarcode from 'jsbarcode'
+import {useWmsStore} from '@/store/modules/wms'
+import {addBom, BOMVersion} from "@/api/production/task";
+
+const barcode = ref(null)
+const route = useRoute()
+const {proxy} = getCurrentInstance();
+const { conventional_units } = proxy.useDict('conventional_units')
+console.log(1231232, conventional_units)
+const itemList = ref([]);
+const itemCategoryTreeSelectList = computed(() => useWmsStore().itemCategoryTreeList);
+const itemCategoryTreeOptionsList = computed(() => {
+    let data = [...itemCategoryTreeSelectList.value];
+    data.unshift({
+        id: -1,
+        label: '全部',
+        children: []
+    });
+    return data;
+});
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const skuLoading = ref(false)
+const queryFormRef = ref(ElForm);
+const itemFormRef = ref(ElForm);
+const itemCategoryFormRef = ref(ElForm);
+const spanMethod = computed(() => getRowspanMethod(itemList.value, rowSpanArray.value))
+const rowSpanArray = ref(['itemId'])
+const qrcode = ref(null)
+const append = (data) => {
+    // resetType();
+    categoryForm.value.categoryName = undefined;
+    categoryForm.value.parentId = data.id;
+    categoryDialog.visible = true;
+}
+
+const remove = async (node, data) => {
+    const ids = data.id
+    await proxy?.$modal.confirm('确认删除分类【' + data.label + '】吗?');
+    await delItemCategory(ids);
+    proxy?.$modal.msgSuccess("删除成功");
+    useWmsStore().getItemCategoryList();
+    useWmsStore().getItemCategoryTreeList();
+}
+const edit = (node, data) => {
+    if (node.level > 1) {
+        categoryForm.value.parentId = node.parent.data.id
+    }
+    categoryForm.value.id = data.id;
+    // resetType();
+    categoryForm.value.categoryName = data.label;
+    categoryDialog.title = "修改商品分类";
+    categoryDialog.visible = true;
+}
+const dialog = reactive({
+    visible: false,
+    title: ''
+});
+const categoryDialog = reactive({
+    visible: false,
+    title: ''
+});
+const showParent = ref(false)
+const initFormData = {
+    id: undefined,
+    itemCode: undefined,
+    itemName: undefined,
+    itemCategory: undefined,
+    unit: undefined,
+    itemBrand: undefined,
+    remark: undefined,
+}
+const initCategoryFormData = {
+    id: undefined,
+    parentId: undefined,
+    ancestors: undefined,
+    categoryName: undefined,
+    orderNum: 0,
+    status: undefined,
+}
+const data = reactive({
+    form: {...initFormData},
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        itemCode: undefined,
+        itemName: undefined,
+        itemType: 1,
+    },
+    rules: {
+        id: [
+            {required: true, message: "不能为空", trigger: "blur"}
+        ],
+        itemName: [
+            {required: true, message: "名称不能为空", trigger: "blur"}
+        ],
+        itemCategory: [
+            {required: true, message: "分类不能为空", trigger: "blur"}
+        ],
+        warehouseId: [
+            {required: true, message: "所属仓库不能为空", trigger: "blur"}
+        ],
+        quantity: [
+            {required: true, message: "安全库存不能为空", trigger: "blur"}
+        ],
+        remark: [
+            {required: true, message: "备注不能为空", trigger: "blur"}
+        ],
+        type: [
+            {required: true, message: "商品类型不能为空", trigger: "change"}
+        ]
+    }
+});
+const categoryData = reactive({
+    form: {...initCategoryFormData},
+    queryParams: {
+        pageNum: 1,
+        pageSize: 1000,
+        parentId: undefined,
+        categoryName: undefined,
+        orderNum: undefined,
+        status: undefined,
+        itemType: 1,
+    },
+    rules: {
+        id: [
+            {required: true, message: "商品分类id不能为空", trigger: "blur"}
+        ],
+        // parentId: [
+        //   {required: true, message: "父物料类型id不能为空", trigger: "blur"}
+        // ],
+        categoryName: [
+            {required: true, message: "商品分类名称不能为空", trigger: "blur"}
+        ],
+        status: [
+            {required: true, message: "商品分类状态不能为空", trigger: "change"}
+        ],
+    }
+});
+const {queryParams, form, rules} = toRefs(data);
+
+const {queryParams: typeQueryParams, form: categoryForm, rules: typeRules} = toRefs(categoryData);
+const currentType = ref()
+/** 查询物料列表 */
+const getList = async () => {
+    loading.value = true;
+    const res = await listItemSkuPage(queryParams.value);
+    const content = [...res.rows];
+    itemList.value = content.map((it) => ({...it, id: it.skuId,itemId: it?.item?.id}));
+    total.value = res.total;
+    loading.value = false;
+}
+const handleAddType = (show) => {
+    categoryDialog.title = "新增商品分类";
+    showParent.value = show
+    categoryDialog.visible = true;
+    if (show) {
+        categoryForm.value.parentId = undefined
+    }
+    nextTick(() => {
+        categoryForm.value.categoryName = undefined;
+    });
+}
+const skuForm = reactive({
+    itemSkuList: []
+})
+const skuFormRef = ref(ElForm)
+const skuRules = {
+    skuName: [{required: true, message: '规格名称不能为空', trigger: 'blur'}]
+}
+// sku 管理
+const resetItemSkuList = () => {
+    skuForm.itemSkuList = []
+    skuForm.itemSkuList.push({
+        id: '',
+        itemId: '',
+        barcode: '',
+        inPrice: null,
+        outPrice: null,
+        skuName: '',
+        quantity: null,
+    })
+}
+
+const onAppendBtnClick = () => {
+    skuForm.itemSkuList.push({
+        id: '',
+        itemId: '',
+        barcode: '',
+        inPrice: null,
+        outPrice: null,
+        skuName: '',
+        quantity: null,
+    })
+}
+const handleDeleteItemSku = async (row, index) => {
+    if (!row.id) {
+        skuForm.itemSkuList.splice(index, 1);
+        return
+    }
+    if (skuForm.itemSkuList.length === 1) {
+        return proxy?.$modal.msgError("至少包含一个商品规格");
+    }
+    await proxy?.$modal.confirm('确认删除规格【' + row.skuName + '】吗?');
+    loading.value = true;
+    await delItemSku(row.id).finally(()=> loading.value = false);
+    proxy?.$modal.msgSuccess("删除成功");
+    const res = await getItem(row.itemId);
+    skuForm.itemSkuList = res.data.sku
+    form.value = res.data
+}
+const collapse = (draggingNode, dropNode, type) => {
+    //注掉的是同级拖拽
+    if (draggingNode.data.label !== '全部' && draggingNode.level === dropNode.level && draggingNode.parent.id == dropNode.parent.id) {
+        if (dropNode.data.label === '全部') {
+            return type === 'next';
+        } else {
+            return type === 'prev' || type === 'next'
+        }
+    } else {
+        // 不同级进行处理
+        return false
+    }
+}
+const handleNodeDrop = async (draggingNode, dropNode, dropType, ev) => {
+    if (dropNode.level === 1) {
+        await updateOrderNum(dropNode.parent.data.filter(it => it.id !== -1));
+    } else {
+        await updateOrderNum(dropNode.parent.data.children);
+    }
+}
+/** 取消按钮 */
+const cancel = () => {
+    reset();
+    dialog.visible = false;
+}
+const cancelType = () => {
+    resetType();
+    categoryDialog.visible = false;
+}
+/** 表单重置 */
+const reset = () => {
+    form.value = {...initFormData};
+    itemFormRef.value.resetFields();
+}
+
+/** 表单重置 */
+const resetType = () => {
+    categoryForm.value = {...initCategoryFormData};
+    itemCategoryFormRef.value.resetFields();
+}
+/** 搜索按钮操作 */
+const handleQuery = () => {
+    queryParams.value.pageNum = 1;
+    getList();
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+    queryFormRef.value.resetFields();
+    handleQuery();
+}
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection) => {
+    ids.value = selection.map(item => item.id);
+    single.value = selection.length != 1;
+    multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+    resetItemSkuList()
+    dialog.visible = true;
+    dialog.title = "新增商品";
+    nextTick(async () => {
+        reset();
+    });
+}
+/** 修改按钮操作 */
+const handleUpdate = (row) => {
+    resetItemSkuList()
+    skuLoading.value = true
+    dialog.visible = true;
+    dialog.title = "修改商品";
+    nextTick(async () => {
+        reset();
+        const _id = row?.itemId || ids.value[0]
+        const res = await listItemSku({'itemId':_id});
+        Object.assign(skuForm.itemSkuList, res.data)
+        skuLoading.value = false
+        Object.assign(form.value, row.item);
+    });
+}
+const handleQueryType = (node, data) => {
+    queryParams.value.pageNum = 1
+    if (data.data.label === '全部') {
+        queryParams.value.itemCategory = '';
+        currentType.value = '';
+        getList();
+    } else {
+        queryParams.value.itemCategory = data.data.id;
+        currentType.value = data.data.id;
+        getList();
+    }
+}
+/** 提交按钮 */
+const submitForm = () => {
+    form.value.sku = skuForm.itemSkuList
+    itemFormRef.value.validate(async (valid) => {
+        if (valid) {
+            let flag = true
+            if (!skuForm.itemSkuList || skuForm.itemSkuList.length === 0) {
+                proxy?.$modal.msgError("至少包含一个商品规格");
+                flag = false
+            }
+            await skuFormRef.value.validate((valid2) => {
+                if (!valid2) {
+                    flag = false;
+                }
+            })
+            if (flag) {
+                buttonLoading.value = true;
+                if (form.value.id) {
+                    await updateItem(form.value).finally(() => buttonLoading.value = false);
+                } else {
+                    await addItem(form.value).finally(() => buttonLoading.value = false);
+                }
+                proxy?.$modal.msgSuccess("修改成功");
+                dialog.visible = false;
+                await getList();
+            }
+        }
+    });
+}
+const submitCategoryForm = () => {
+    itemCategoryFormRef.value.validate(async (valid) => {
+        if (valid) {
+            buttonLoading.value = true;
+            if (categoryForm.value.id) {
+                await updateItemCategory(categoryForm.value).finally(() => buttonLoading.value = false);
+            } else {
+                await addItemCategory(categoryForm.value).finally(() => buttonLoading.value = false);
+            }
+            proxy?.$modal.msgSuccess(categoryForm.value.id ? '修改成功' : '新增成功');
+            categoryDialog.visible = false;
+            useWmsStore().getItemCategoryList();
+            useWmsStore().getItemCategoryTreeList();
+        }
+    });
+}
+/** 删除按钮操作 */
+const handleDelete = async (row) => {
+    const _ids = row?.itemId || ids.value;
+    await proxy?.$modal.confirm('确认删除商品【' + row?.item.itemName + '】吗?');
+    loading.value = true;
+    await delItem(_ids).finally(()=> loading.value = false);
+    proxy?.$modal.msgSuccess("删除成功");
+    await getList();
+}
+const treeRef = ref(null)
+/** 导出按钮操作 */
+const handleExport = () => {
+    proxy?.download('wms/item/export', {
+        ...queryParams.value
+    }, `item_${new Date().getTime()}.xlsx`)
+}
+/** 下载条形码 */
+const downloadBarcode = (row) => {
+    JSBarcode(barcode.value, row.barcode, {
+        format: "CODE128",
+        displayValue: true
+    })
+    const canvas = barcode.value
+    //创建a标签
+    let a = document.createElement('a')
+    //设置下载文件的名字
+    a.download = row.barcode
+    a.href = canvas.toDataURL("image/png")
+    a.click()
+}
+/** 下载二维码 */
+const downloadQrcode = async (row) => {
+    qrcode.value = await Qrcode.toDataURL(row.barcode)
+    //创建a标签
+    let a = document.createElement('a')
+    //获取二维码的url并赋值为a.href
+    a.href = qrcode.value
+    //设置下载文件的名字
+    a.download = row.barcode
+    //点击事件,相当于下载
+    a.click()
+    //提示信息
+    // this.$message.warn('下载中,请稍后...')
+}
+const getVolumeText = (itemSku) => {
+    if((itemSku.length || itemSku.length === 0) && (itemSku.width || itemSku.width === 0) && (itemSku.height || itemSku.height === 0)) {
+        return itemSku.length + ' * ' + itemSku.width + ' * ' + itemSku.height
+    }
+    return ((itemSku.length || itemSku.length === 0) ? ('长:' + itemSku.length) : '')
+        + ((itemSku.width || itemSku.width === 0) ? (' 宽:' + itemSku.width) : '')
+        + ((itemSku.height || itemSku.height === 0) ? (' 高:' + itemSku.height) : '')
+}
+
+// 物料清单
+let productShow = ref(false)
+let BOMForm = ref({
+    version: ''
+})
+let productList = ref([])
+const handleShowProduct = (row) => {
+    productShow.value = true
+    BOMDataForm.value.itemName = row.item.itemName
+    BOMDataForm.value.itemCode = row.item.itemCode
+    BOMDataForm.value.itemType = row.item.itemType
+    BOMDataForm.value.skuName = row.itemSku.itemName
+    BOMDataForm.value.skuItemId = row.skuId
+    listItem().then(res => {
+        if(res.code == 200) {
+            productList.value = res.data
+        }
+    })
+}
+
+// BOM配置
+let configurateShow = ref(false)
+const configurate = (row, type) => {
+    if(type) {
+        BOMDataForm.value.itemName = row.item.itemName
+        BOMDataForm.value.itemCode = row.item.itemCode
+        BOMDataForm.value.itemType = row.item.itemType
+        BOMDataForm.value.skuName = row.itemSku.itemName
+        BOMDataForm.value.skuItemId = row.skuId
+    }
+    configurateShow.value = true
+    // bomList({
+    //     bomListQueryDto: {
+    //         skuItemId: BOMDataForm.value.skuItemId,
+    //         bomVersionId: BOMDataForm.value.version
+    //     }
+    // }).then(res => {
+    //     if(res.code == 200) {
+    //         BOMDataList.value = res.data
+    //     }
+    // })
+}
+let addShow = ref(false)
+let addTotal = ref(0)
+let addForm = ref({
+    itemName: '',
+    itemCode: '',
+    skuName: '',
+    skuCode: '',
+    pageNum: 1,
+    pageSize: 10
+})
+let materialList = ref([])
+const handleAddUnit = () => {
+    addShow.value = true
+    listItemSkuPage({
+        ...addForm.value
+    }).then(res => {
+        materialList.value = res.rows
+        addTotal.value = res.total
+    })
+}
+const handleSizeChange = (size) => {
+    addForm.value.pageSize = size
+    listItemSkuPage({
+        ...addForm.value
+    }).then(res => {
+        materialList.value = res.rows
+        addTotal.value = res.total
+    })
+}
+const handleCurrentChange = (page) => {
+    addForm.value.pageNum = page
+    listItemSkuPage({
+        ...addForm.value
+    }).then(res => {
+        materialList.value = res.rows
+        addTotal.value = res.total
+    })
+}
+const handleBOMDataCancel = () => {
+    configurateShow.value = false
+    BOMDataList.value = []
+}
+const handleBOMDataConfirm = ()=> {
+    let list = BOMDataList.value.map(item => {
+        return {
+            bomItemSkuId: item.itemSku.itemId,
+            quantity: item.quantity,
+            unit: item.unit
+        }
+    })
+    addBom({
+        version: BOMDataForm.value.version,
+        itemSkuId: BOMDataForm.value.skuItemId,
+        bomItemSkuList: list
+    }).then(res => {
+        if(res.code == 200) {
+            ElMessage({
+                type: 'success',
+                message: res.msg
+            })
+        } else {
+            ElMessage({
+                type: 'error',
+                message: res.msg
+            })
+        }
+        configurateShow.value = false
+    })
+}
+
+const handleSearch = () => {
+    addForm.value.pageNum = 1
+    addForm.value.pageSize = 10
+    listItemSkuPage({
+        ...addForm.value
+    }).then(res => {
+        materialList.value = res.rows
+        addTotal.value = res.total
+    })
+}
+
+let BOMList = ref([])
+const initBOMVersion = () => {
+    BOMVersion({
+        skuId: ''
+    }).then(res => {
+        BOMList.value = res.data
+    })
+}
+
+let BOMDataForm = ref({})
+let BOMDataList = ref([])
+
+let selected = ref([])
+const handleSelectChange = (rows) => {
+    selected.value = rows
+}
+const handleSelectCancel = () => {
+    selected.value = []
+    addShow.value = false
+}
+const handleSelectConfirm = () => {
+    BOMDataList.value = selected.value
+    addShow.value = false
+}
+
+onMounted(() => {
+    nextTick(()=>{
+        getList();
+        initBOMVersion()
+        if (route.query.openDrawer) {
+            handleAdd()
+        }
+    })
+});
+
+</script>
+
+<style scoped lang="scss">
+.custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 14px;
+    padding-right: 8px;
+}
+.pagination{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-top: 10px;
+}
+.btn{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+.btns{
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+.left{
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+.right{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+
+.el-tree-node__content {
+    display: flex;
+    align-items: center;
+    height: 35px;
+    cursor: pointer;
+}
+
+.el-table .my-cell {
+    vertical-align: top
+}
+
+.el-table__empty-text {
+    width: 100%;
+}
+</style>

+ 6 - 0
src/views/wms/order/receipt/edit.vue

@@ -115,6 +115,11 @@
                 <div v-if="row.itemSku.barcode">条码:{{row.itemSku.barcode}}</div>
               </template>
             </el-table-column>
+              <el-table-column label="单位">
+                  <template #default="scope">
+                      {{ scope.row.item.unit }}
+                  </template>
+              </el-table-column>
             <el-table-column label="数量" prop="quantity" width="180">
               <template #default="scope">
                 <el-input-number
@@ -152,6 +157,7 @@
         @handleOkClick="handleOkClick"
         @handleCancelClick="skuSelectShow = false"
         :size="'80%'"
+        :is-need-type="true"
       />
     </div>
     <div class="footer-global">

+ 17 - 1
src/views/wms/order/shipment/edit.vue

@@ -55,7 +55,12 @@
             </el-col>
           </el-row>
           <el-row :gutter="24">
-            <el-col :span="11">
+              <el-col :span="11" v-if="form.optType === '3'">
+                  <el-form-item label="生产任务单">
+                      <el-input v-model="form.taskId" />
+                  </el-form-item>
+              </el-col>
+            <el-col :span="form.optType === '3'?6:11">
               <el-form-item label="备注" prop="remark">
                 <el-input
                   v-model="form.remark"
@@ -128,6 +133,11 @@
                 <div v-if="row.itemSku.barcode">条码:{{row.itemSku.barcode}}</div>
               </template>
             </el-table-column>
+              <el-table-column label="单位">
+                  <template #default="scope">
+                      {{ scope.row.item.itemUnit }}
+                  </template>
+              </el-table-column>
             <el-table-column label="出库数量" prop="quantity" width="180">
               <template #default="scope">
                 <el-input-number
@@ -213,6 +223,7 @@ const initFormData = {
   warehouseId: undefined,
   totalQuantity: 0,
   details: [],
+  taskId: undefined
 }
 const inventorySelectRef = ref(null)
 const selectedInventory = ref([])
@@ -299,6 +310,7 @@ const getParamsBeforeSave = (orderStatus) => {
     bizOrderNo: form.value.bizOrderNo,
     orderStatus,
     remark: form.value.remark,
+    taskId: form.value.taskId,
     totalAmount: form.value.totalAmount,
     totalQuantity: form.value.totalQuantity,
     warehouseId: form.value.warehouseId,
@@ -345,6 +357,10 @@ const doSave = (orderStatus = 0) => {
 }
 
 const doShipment = async () => {
+    if(form.value.orderStatus == '-1') {
+        proxy?.$modal.confirm('该生产出库单相关的生产任务单据已作废,不支持出库')
+        return
+    }
   await proxy?.$modal.confirm('确认出库吗?');
   shipmentForm.value?.validate((valid) => {
     // 校验