Browse Source

其他入库-第一版页面

jingbb 4 months ago
parent
commit
f19c92dfb8

+ 431 - 0
src/views/inventiry/otherOut/components/SelectStaningStockModal.vue

@@ -0,0 +1,431 @@
+<template>
+    <a-modal
+      title="选择现存量(Select staning stock)"
+      width="95%"
+      :visible="visible"
+      :maskClosable="false"
+      switchFullscreen
+      @ok = "handleOk"
+      @cancel="handleCancel">
+        <div>
+          <a-card  :body-style="{ padding: '10px' }" :bordered="false" style="margin: 10px;">
+            <div class="table-page-search-wrapper">
+                <a-form :model="queryParams" :label-col="labelCol" :wrapper-col="wrapperCol" @keyup.enter.native="searchQuery">
+                <a-row :gutter="24">
+                    <a-col :md="6" :sm="8">
+                        <a-form-item label="仓库(warehouse)">
+                            <a-input placeholder="请输入" v-model:value="queryParams.warehouse"></a-input>
+                        </a-form-item>
+                    </a-col>
+                    <a-col :md="6" :sm="8">
+                        <a-form-item label="货位(goods allocation)">
+                            <a-input placeholder="请输入" v-model:value="queryParams.goodsAllocation"></a-input>
+                        </a-form-item>
+                    </a-col> 
+                    <template v-if="toggleSearchStatus">
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="项目(project)">
+                                <ApiSelect
+                                    :api="projectListList"
+                                    showSearch
+                                    v-model:value="queryParams.project"
+                                    optionFilterProp="label"
+                                    resultField="records"
+                                    labelField="name"
+                                    valueField="id"
+                                    :disabled="fatherProject!==''"
+                                    />
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="供应商(supplier)">
+                                <a-input placeholder="请输入" v-model:value="queryParams.supplierName"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="客户(customer)">
+                                <a-input placeholder="请输入" v-model:value="queryParams.customerName"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="产品分类(production class)" :label-col="labelCol1" :wrapper-col="wrapperCol1">
+                                <!-- <a-input placeholder="请输入" v-model:value="queryParams.classId"></a-input> -->
+                                <JSelectInput   v-model:value="queryParams.productionClass"  placeholder="请选择" :options="classOption" ></JSelectInput>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="优先级(priority)" >
+                                <JDictSelectTag v-model:value="queryParams.priority" placeholder="请选择" dictCode="priority"/>
+                            </a-form-item>
+                        </a-col>
+                       
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="机型(model)">
+                                <a-input placeholder="请输入" v-model:value="queryParams.headModel"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="产品编码(product code)">
+                                <a-input placeholder="请输入" v-model:value="queryParams.productCode"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="6" :sm="8">
+                            <a-form-item label="批号(batch code)">
+                                <a-input placeholder="请输入" v-model:value="queryParams.batchCode"></a-input>
+                            </a-form-item>
+                        </a-col>                        
+                    </template>
+                    <a-col :md="6" :sm="8">
+                        <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+                            <a-button type="primary" @click="searchQuery" >查询(search)</a-button>
+                            <a-button type="primary" @click="searchReset"  style="margin-left: 8px">重置(reset)</a-button>
+                            <a @click="handleToggleSearch" style="margin-left: 8px">
+                            {{ toggleSearchStatus ? '收起' : '展开' }}
+                            <a-icon :type="toggleSearchStatus ? 'up' : 'down'" />
+                            </a>
+                        </span>
+                    </a-col>
+                </a-row>
+            </a-form>
+           </div>
+        </a-card>
+
+        <a-card  :body-style="{ padding: '10px' }" :bordered="false" style="margin: 10px;">
+            <a-alert type="info" show-icon class="alert" style="margin-bottom: 8px">
+            <template #message>
+                <template v-if="selectedRowKeys.length > 0">
+                <span>已选中 {{ selectedRowKeys.length }} 条记录</span>
+                <a-divider type="vertical" />
+                <a @click="selectedRowKeys = []">清空</a>
+                </template>
+                <template v-else>
+                <span>未选中任何数据</span>
+                </template>
+            </template>
+            </a-alert>
+            <a-table
+                :columns="columns"
+                :row-key="record => record.childId"
+                :data-source="dataSource"
+                bordered
+                size="small"
+                @change="handleTableChange"
+                :pagination="pagination"
+                :scroll="{ x: 3500, y: 300 }"
+                :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
+            >
+            </a-table>
+        </a-card>
+      </div>
+    </a-modal>
+</template>
+<script lang="ts" setup>
+    import {ref, reactive } from 'vue';
+    import { defHttp} from '/@/utils/http/axios';
+    import { message } from 'ant-design-vue';
+    import { filterObj, getFileAccessHttpUrl } from '/@/utils/common/compUtils';
+    import { JDictSelectTag} from '/@/components/Form';
+     import {  ApiSelect, } from '/@/components/Form/index';
+    import JSelectInput from '/@/components/Form/src/jeecg/components/JSelectInput.vue';
+    const emit = defineEmits([ 'SelectStaningStock']); //定义emit
+    let classOption = ref([])
+    var visible = ref(false)
+    var fatherProject = ref('')
+    const columns = [
+        {
+            title: '仓库(warehouse)',
+            dataIndex: 'billCode',
+            key: 'billCode',
+            align:"center",
+            width:250,
+            
+        },
+        {
+            title: '货位(goods allocation)',
+            dataIndex: 'goodsAllocation',
+            key: 'goodsAllocation',
+            align:"center"
+        },
+        {
+            title: '项目(project)',
+            dataIndex: 'projectName',
+            key: 'projectName',
+            align:"center",
+            width:250,
+            ellipsis: true,
+        },
+        {
+            title: '供应商(customer)',
+            dataIndex: 'customerName',
+            key: 'customerName',
+            align:"center",
+            width:250,
+            ellipsis: true,
+        },
+        {
+            title: '客户(custormer)',
+            dataIndex: 'customerName',
+            key: 'customerName',
+            align:"center",
+            ellipsis: true,
+        },
+        {
+            title: '产品分类(production class)',
+            dataIndex: 'productClass',
+            key: 'productClass',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '机型(model)',
+            dataIndex: 'headModel',
+            key: 'headModel',
+            align:"center"
+        },
+        {
+            title: '产品编码(product code)',
+            dataIndex: 'productCode',
+            key: 'productCode',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '产品英文名(English name)',
+            key: 'englishName',
+            dataIndex: 'englishName',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '产品中文名(chinese name)',
+            key: 'chineseName',
+            dataIndex: 'chineseName',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '型号(childModel)',
+            key: 'childModel',
+            dataIndex: 'childModel',
+            align:"center"
+        },
+        {
+            title: '厂家(factory)',
+            key: 'factory',
+            dataIndex: 'factory',
+            align:"center",
+            width:250
+        },
+        {
+            title: '质量等级(quantity grade)',
+            key: 'quantityGrade',
+            dataIndex: 'quantityGrade',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '数量(quantity)',
+            key: 'quantity',
+            dataIndex: 'quantity',
+            align:"center",
+            width:250,
+        },
+        {
+            title: '批号(batch code)',
+            key: 'batchCode',
+            dataIndex: 'batchCode',
+            align:"center",
+            width:250,
+        },
+    ];
+    const labelCol = ref({
+    xs: { span: 24 },
+    sm: { span: 9 },
+    });
+    const wrapperCol = ref({
+        xs: { span: 24 },
+        sm: { span: 15 },
+    });
+    const labelCol1 = ref({
+    xs: { span: 24 },
+    sm: { span: 12 },
+    });
+    const wrapperCol1 = ref({
+        xs: { span: 24 },
+        sm: { span: 12 },
+    });
+    const dataSource =ref([]);
+    let selectedRowKeys = ref([]);
+    let selectedRows = ref([]);
+    const toggleSearchStatus = ref(false);
+    const queryParams = ref({
+        warehouse:'',
+        goodsAllocation:"",
+        project:'',
+        projectName:'',
+        productionClass:'',
+        supplierName:'',
+        supplier:'',
+        priority:'',
+        customerName:'',
+        customer:'',
+        headModel:'',
+        batchCode:'',
+        productCode:'',
+    });
+    let pagination = ref({
+      current: 1,
+      pageSize: 10,
+      total: '', // 假设总共有100条数据
+      showSizeChanger: true,
+      showQuickJumper: true,
+      showTotal: (total, range) => {
+          return range[0] + "-" + range[1] + " 共" + total + "条"
+      },
+      size:'small'
+    });
+    function loadData(){
+        let params = getQueryParams();
+        defHttp.get({ url: '/saleCode/saleQuotation/saleQuotationDetailsAlert',params}, { isTransformResponse: false })
+        .then((res) => {
+            if (res.success) {
+                dataSource.value = res.result.records;
+                pagination.value.total = res.result.total;
+                pagination.value.current = res.result.current;
+                pagination.value.pageSize = res.result.size;                
+            } else {
+                message.error(res.message);
+            }
+        })
+        .finally(() => {
+            // loading.value = false;
+        });
+    }
+    function getQueryParams(){
+        let params = Object.assign(queryParams.value);
+        params.pageNo = pagination.value.current;
+        params.pageSize = pagination.value.pageSize;
+        if(fatherProject.value&&fatherProject.value!==''){
+            queryParams.value.project = fatherProject.value
+        }else {
+            queryParams.value.project = params.project
+        }
+        return filterObj(params);
+    }
+    function handleTableChange(paginations, filters, sorter){
+        pagination.value.total = paginations.total;
+        pagination.value.current = paginations.current;
+        pagination.value.pageSize = paginations.pageSize;
+        loadData()
+    };
+    function projectListList(){
+        let params = {pageSize:-1}
+        return defHttp.get({url:'/baseCode/baseProjectArchive/list',params});
+    }
+    function getOptiom(){
+    defHttp
+        .get({ url: 'baseCode/baseProductClass/list'}, { isTransformResponse: false })
+        .then((res) => {
+            if (res.success) {
+              classOption.value = []
+              res.result.records.forEach(element => {
+                  var obj = {
+                    label: element.name?element.name:'无名称请维护',
+                    value: element.name?element.name:''
+                  };
+                  classOption.value.push( obj)
+              });    
+            }
+        })
+        .finally(() => {
+            // loading.value = false;
+        });
+  }
+    function searchQuery(){
+        loadData();
+    }
+    function searchReset(){
+        queryParams.value = {
+            warehouse:'',
+            goodsAllocation:"",
+            project:'',
+            projectName:'',
+            productionClass:'',
+            supplierName:'',
+            supplier:'',
+            priority:'',
+            customerName:'',
+            customer:'',
+            headModel:'',
+            batchCode:'',
+            productCode:'',
+        }
+        pagination.value.current =1;
+        pagination.value.pageSize = 10; 
+        loadData();
+    }
+    function handleToggleSearch(){
+        toggleSearchStatus.value = !toggleSearchStatus.value;
+    }
+    function onSelectChange(keys,rows){
+        selectedRowKeys.value = keys
+        selectedRows.value = rows
+    }
+    function handleOk(){
+        var arr = []
+        selectedRows.value.map(item=>arr.push(item.billCode))
+        if(selectedRowKeys.value.length==0){
+            message.error('请勾选数据');
+        }else{
+            emit('SelectStaningStock', selectedRows.value)
+            handleCancel()
+        }
+    }
+    function handleCancel(){
+        visible.value = false
+        selectedRowKeys.value = []
+        selectedRows.value=[]
+        queryParams.value = {
+            warehouse:'',
+            goodsAllocation:"",
+            project:'',
+            projectName:'',
+            productionClass:'',
+            supplierName:'',
+            supplier:'',
+            priority:'',
+            customerName:'',
+            customer:'',
+            headModel:'',
+            batchCode:'',
+            productCode:'',
+        }
+    }
+    function getTable(formData){
+        visible.value = true
+        if(formData.projectName&&formData.projectName!==''){
+            fatherProject.value = formData.project
+        }else{
+            fatherProject.value = ''
+        }
+        // if(formData.sourceCode&&formData.sourceCode!==''){
+        //     fatherSourceCode.value = formData.sourceCode
+        // }else{
+        //     fatherSourceCode.value = ''
+        // }
+        loadData()
+        getOptiom()
+    }
+    defineExpose({
+      getTable
+    });
+</script>
+<style scoped lang="less">
+/deep/.ant-form-item{
+    margin-bottom: 8px !important;
+}
+// /deep/.ant-table-wrapper .ant-table-thead > tr > th, .ant-table-wrapper .ant-table-thead > tr > td{
+//     padding: 8px !important;
+// }
+
+</style>

+ 327 - 0
src/views/inventiry/otherOut/components/otherOutForm.vue

@@ -0,0 +1,327 @@
+<template>
+  <a-spin :spinning="loading">
+    <JFormContainer :disabled="disabled">
+      <template #detail>
+        <a-form v-bind="formItemLayout" name="SaleOrderForm" ref="formRef">
+          <a-row>
+            <a-col :span="12">
+							<a-form-item label="出库单号(bill code)" v-bind="validateInfos.billCode" id="SaleOrderForm-billCode" name="billCode">
+								<a-input v-model:value="formData.billCode" placeholder="出库单号(bill code)" disabled></a-input>
+							</a-form-item>
+						</a-col>
+						<a-col :span="12">
+							<a-form-item label="出库日期(bill date)" v-bind="validateInfos.billDate"  id="SaleOrderForm-billDate" name="billDate">
+								<a-date-picker placeholder="请选择出库日期(bill date)"  v-model:value="formData.billDate"  value-format="YYYY-MM-DD"  style="width: 100%"  allow-clear />
+							</a-form-item>
+						</a-col>		
+						<a-col :span="12">
+							<a-form-item label="项目(project)" v-bind="validateInfos.projectName" id="SaleOrderForm-projectName" name="projectName">
+								<a-input v-model:value="formData.projectName" placeholder="请输入项目(project)" disabled allow-clear ></a-input>
+							</a-form-item>
+						</a-col>
+						<a-col :span="12">
+							<a-form-item label="客户(customer)" v-bind="validateInfos.customerName"  id="SaleOrderForm-customerName" name="customerName">
+								<a-input v-model:value="formData.customerName" placeholder="请输入" disabled allow-clear ></a-input>
+							</a-form-item>
+						</a-col>
+            <a-col :span="12">
+							<a-form-item label="销售部门(sale department)" v-bind="validateInfos.saleDepartment"  id="SaleOrderForm-saleDepartment" name="saleDepartment">
+								<a-input v-model:value="formData.saleDepartment" placeholder="请输入" disabled allow-clear ></a-input>
+							</a-form-item>
+						</a-col>
+            <a-col :span="12">
+							<a-form-item label="业务员(salesman)" v-bind="validateInfos.salesman"  id="SaleOrderForm-salesman" name="salesman">
+								<a-input v-model:value="formData.salesman" placeholder="请输入" disabled allow-clear ></a-input>
+							</a-form-item>
+						</a-col>
+            <a-col :span="12">
+							<a-form-item label="货位(goods allocation)" v-bind="validateInfos.goodsAllocation" id="SaleOrderForm-goodsAllocation" name="goodsAllocation">
+								<JDictSelectTag v-model:value="formData.goodsAllocation" placeholder="请选择" dictCode="goods_allocation"/>
+							</a-form-item>
+						</a-col>
+            <a-col :span="12">
+							<a-form-item label="仓库(warehouse)" v-bind="validateInfos.warehouse" id="SaleOrderForm-warehouse" name="warehouse">
+                <JDictSelectTag v-model:value="formData.warehouse" placeholder="请选择" dictCode="warehouse"/>
+							</a-form-item>
+						</a-col>
+            <a-col :span="12">
+							<a-form-item label="备注(notes)" v-bind="validateInfos.notes" id="SaleOrderForm-notes" name="notes">
+								<a-input v-model:value="formData.notes"></a-input>
+							</a-form-item>
+						</a-col>   
+          </a-row>
+        </a-form>
+      </template>
+    </JFormContainer>
+
+		<!-- 子表单区域 -->
+    <a-tabs v-model:activeKey="activeKey" animated  style=" padding: 24px;padding-top: 0px;">
+      <a-tab-pane tab="其他出库 - 出库明细(stock out details)" key="otherOut" :forceRender="true">
+        <a-button type="primary" style="margin-right: 1%;margin-bottom: 1%;" @click="selectStandingStock"> 选择现存量(select standing stock)</a-button>
+        <j-vxe-table
+          :keep-source="true"
+          resizable
+          ref="otherOutTableRef"
+          :loading="otherOutTable.loading"
+          :columns="otherOutTable.columns"
+          :dataSource="otherOutTable.dataSource"
+          :height="340"
+          :disabled="disabled"
+          :rowNumber="true"
+          :rowSelection="true"
+          asyncRemove
+          >
+            <template #action="props">
+              <a-popconfirm title="确定删除吗?" @confirm="handleDelete(props)">
+                <a>删除(delete)</a>
+              </a-popconfirm>
+              <!-- 逻辑不通暂时取消次功能 -->
+              <!-- <a>复制(copy)</a> -->
+            </template>
+          </j-vxe-table>
+      </a-tab-pane>     
+    </a-tabs>
+    <SelectStaningStockModal ref="SelectStaningStockModalRef"></SelectStaningStockModal>
+  </a-spin>
+</template>
+
+<script lang="ts">
+  import { defineComponent, ref, reactive, computed, toRaw} from 'vue';
+  import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
+  import { queryOtherOutByMainId, queryDataById, saveOrUpdate} from '../otherOutForm.api';
+  import {otherOutDetailColumns} from '../otherOutForm.data';
+  import {SelectStaningStockModal} from './SelectStaningStockModal';
+  import { JVxeTable } from '/@/components/jeecg/JVxeTable';
+  import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
+  import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
+  import { JDictSelectTag} from '/@/components/Form';
+  import { Form, message } from 'ant-design-vue';
+  import moment from 'moment';
+  const useForm = Form.useForm;
+  export default defineComponent({
+    name: "otherOutForm",
+    components:{
+      JVxeTable,
+			JFormContainer,
+      JUpload,
+      JDictSelectTag,
+      SelectStaningStockModal
+    },
+    props:{
+      formDisabled:{
+        type: Boolean,
+        default: false
+      },
+      formData: { type: Object, default: ()=>{} },
+      formBpm: { type: Boolean, default: true }
+    },
+    emits:['success'],
+    setup(props, {emit}) {
+      const loading = ref(false);
+      const formRef = ref();
+      const otherOutTableRef = ref();
+      const otherOutTable = reactive<Record<string, any>>({
+        loading: false,
+        columns: otherOutDetailColumns,
+        dataSource: []
+      });
+      const activeKey = ref('otherOut');
+      const SelectStaningStockModalRef = ref()
+      const formData = reactive<Record<string, any>>({
+        id: '',
+        status: undefined,
+        delFlag: undefined,
+        sourceCode:'',
+        billCode:'',
+        billDate: moment(new Date()).format('YYYY-MM-DD'),   
+        project: '', 
+        projectName:'',  
+        customer:"",
+        customerName:'',
+        saleDepartment: '',   
+        productionClass: '',   
+        salesman:'',   
+        goodsAllocation:'',
+        warehouse:'',
+        notes:'',
+      });
+      //表单验证
+      const validatorRules = reactive({
+      });
+      const {resetFields, validate, validateInfos} = useForm(formData, validatorRules, {immediate: false});
+      const dbData = {};
+      const formItemLayout = {
+        labelCol: {xs: {span: 24}, sm: {span: 5}},
+        wrapperCol: {xs: {span: 24}, sm: {span: 16}},
+        labelCol1: {xs: {span: 24}, sm: {span: 7}},
+        wrapperCol1: {xs: {span: 24}, sm: {span: 15}},
+      };
+
+      // 表单禁用
+      const disabled = computed(()=>{
+        if(props.formBpm === true){
+          if(props.formData.disabled === false){
+            return false;
+          }else{
+            return true;
+          }
+        }
+        return props.formDisabled;
+      });
+
+      
+
+      function add() {
+        resetFields();
+        otherOutTable.dataSource = [];
+        activeKey.value = 'otherOut'
+      }
+      async function edit(row) {
+        //主表数据
+        await queryMainData(row.id);
+        const otherOutDataList = await queryOtherOutByMainId(row['id']);
+        otherOutTable.dataSource = [...otherOutDataList];
+      }
+
+      async function queryMainData(id) {
+        const row = await queryDataById(id);
+        resetFields();
+        const tmpData = {};
+        Object.keys(formData).forEach((key) => {
+          if(row.hasOwnProperty(key)){
+            tmpData[key] = row[key]
+          }
+        })
+        //赋值
+        Object.assign(formData,tmpData);
+      }
+     
+      const {getSubFormAndTableData, transformData} = useValidateAntFormAndTable(activeKey, {
+        'storePurchaseInDetails': otherOutTableRef,
+      });
+
+      async function getFormData() {
+        try {
+          // 触发表单验证
+          await validate();
+        } catch ({ errorFields }) {
+          if (errorFields) {
+            const firstField = errorFields[0];
+            if (firstField) {
+              formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
+            }
+          }
+          return Promise.reject(errorFields);
+        }
+        return transformData(toRaw(formData))
+      }
+
+      async function submitForm() {
+        if( formData.sourceCode==''){
+          message.error('请添加出库明细!');
+        }else{
+          const mainData = await getFormData();
+          const subData = await getSubFormAndTableData();
+          const values = Object.assign({}, dbData, mainData, subData);
+          console.log('表单提交数据', values)
+          const isUpdate = values.id ? true : false
+          await saveOrUpdate(values, isUpdate);
+          //关闭弹窗
+          emit('success');
+        }
+      }
+      
+      function setFieldsValue(values) {
+        if(values){
+          Object.keys(values).map(k=>{
+            formData[k] = values[k];
+          });
+        }
+      }
+
+      //产品明细-删除行
+      function handleDelete(prop) {
+        var newArray = [...otherOutTable.dataSource]
+        newArray.splice(prop.rowIndex, 1)
+        otherOutTable.dataSource = newArray      
+        if(otherOutTable.dataSource.length==0){
+          formData.sourceCode=''
+        }
+      }
+      function addotherOutList(data){
+        formData.project = data[0].project
+        formData.projectName = data[0].projectName
+        formData.supplier = data[0].supplier
+        formData.supplierName = data[0].supplierName
+        formData.delivery = data[0].delivery
+        formData.productionClass = data[0].productionClass
+        formData.model = data[0].model
+        formData.maker = data[0].maker
+        formData.sourceCode = data[0].billCode
+        formData.arrivalDetails = data[0].arrivalDetails
+        var arr = data.concat(otherOutTable.dataSource)
+        arr.map(item=>{
+          item.model = item.childModel
+          item.sourceId = item.childId
+          item.arrivalQuantity = item.quantity
+        })
+        otherOutTable.dataSource=arr  
+      }
+      /**
+       * 值改变事件触发-树控件回调
+       * @param key
+       * @param value
+       */
+      function handleFormChange(key, value) {
+        formData[key] = value;
+      }
+      function selectStandingStock(){
+        SelectStaningStockModalRef.value.getTable(formData)
+
+      }
+
+      return {
+        otherOutTableRef,
+        otherOutTable,
+        validatorRules,
+        validateInfos,
+        activeKey,
+        loading,
+        formData,
+        setFieldsValue,
+        handleFormChange,
+        formItemLayout,
+        disabled,
+        getFormData,
+        submitForm,
+        add,
+        edit,
+        formRef,
+        handleDelete,
+        SelectStaningStockModalRef,
+        selectStandingStock
+      }
+    }
+  });
+</script>
+<style lang="less" scoped>
+  /** 时间和数字输入框样式 */
+  :deep(.ant-input-number) {
+    width: 100%;
+  }
+
+  :deep(.ant-calendar-picker) {
+    width: 100%;
+  }
+  /deep/.vxe-table--body-wrapper{
+    height: 100% !important;
+  }
+  /deep/.ant-modal-body{
+    padding: 24px !important;
+  }
+  
+  /deep/.ant-form-item{
+    margin-bottom: 8px !important;
+  }
+      
+</style>

+ 76 - 0
src/views/inventiry/otherOut/components/otherOutFormModal.vue

@@ -0,0 +1,76 @@
+<template>
+  <div ref="OtherOutDetailsRef">
+    <BasicModal v-bind="$attrs" @register="registerModal" :title="title" width="95%"  @ok="handleSubmit" :getContainer ='()=>$refs.OtherOutDetailsRef'>
+      <otherOutForm ref="formComponent" :formDisabled="formDisabled" :formBpm="false" @success="submitSuccess"></otherOutForm>
+    </BasicModal>
+  </div>
+</template>
+
+<script lang="ts">
+  import { ref, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import otherOutForm from './otherOutForm.vue';
+
+  export default {
+    name: "otherOutFormModal",
+    components:{
+      BasicModal,
+      otherOutForm
+    },
+    emits:['register','success'],
+    setup(_p, {emit}){
+      const formComponent = ref()
+      const isUpdate = ref(true);
+      const formDisabled = ref(false);
+      const title = ref('')
+      var OtherOutDetailsRef = ref()
+      //表单赋值
+      const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
+        setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
+          isUpdate.value = !!data?.isUpdate;
+          formDisabled.value = !data?.showFooter;
+          title.value = data?.isUpdate ? (unref(formDisabled) ? '详情' : '编辑') : '新增';
+          if (unref(isUpdate)) {
+            formComponent.value.edit(data.record)
+          }else{
+            formComponent.value.add()
+          }
+      });
+
+      function handleSubmit() {
+        formComponent.value.submitForm();
+      }
+
+      function submitSuccess(){
+        emit('success');
+        closeModal();
+      }
+
+      return {
+        registerModal,
+        title,
+        formComponent,
+        formDisabled,
+        handleSubmit,
+        submitSuccess,
+        OtherOutDetailsRef,
+      }
+    }
+  }
+</script>
+<style lang="less" scoped>
+	/** 时间和数字输入框样式 */
+  :deep(.ant-input-number) {
+    width: 100%;
+  }
+
+  :deep(.ant-calendar-picker) {
+    width: 100%;
+  }
+  /deep/.ant-modal {
+    // width: 520px;
+    padding-bottom: 0;
+    margin-top: -10px;
+    height: 100%;
+}
+</style>

+ 121 - 0
src/views/inventiry/otherOut/otherOutForm.api.ts

@@ -0,0 +1,121 @@
+import {defHttp} from '/@/utils/http/axios';
+import { useMessage } from "/@/hooks/web/useMessage";
+
+const { createConfirm } = useMessage();
+
+enum Api {
+  list = '/storeCode/storePurchaseIn/list',
+  save='/storeCode/storePurchaseIn/add',
+  edit='/storeCode/storePurchaseIn/edit',
+  deleteOne = '/storeCode/storePurchaseIn/delete',
+  deleteBatch = '/storeCode/storePurchaseIn/deleteBatch',
+  importExcel = '/storeCode/storePurchaseIn/importExcel',
+  exportXls = '/storeCode/storePurchaseIn/exportXls',
+  queryDataById = '/storeCode/storePurchaseIn/queryById',
+  stockOutFormProductList = '/storeCode/storePurchaseIn/queryStorePurchaseInDetailsByMainId',
+  submitBatch='/storeCode/storePurchaseIn/submitBatch',
+  cancelSubmitBatch='/storeCode/storePurchaseIn/returnSubmitBatch',
+  classList='baseCode/baseProductClass/list'
+}
+/**
+ * 导出api
+ * @param params
+ */
+export const getExportUrl = Api.exportXls;
+
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+/**
+ * 查询子表数据
+ * @param params
+ */
+export const queryOtherOutByMainId = (id) => defHttp.get({url: Api.stockOutFormProductList, params:{ id }});
+
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) =>
+  defHttp.get({url: Api.list, params});
+
+/**
+ * 分类列表接口
+ * @param params
+ */
+export const ClassList = (params) =>
+  defHttp.get({url: Api.classList, params});
+
+
+/**
+ * 删除单个
+ */
+export const deleteOne = (params,handleSuccess) => {
+  return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
+    handleSuccess();
+  });
+}
+/**
+ * 批量删除
+ * @param params
+ */
+export const batchDelete = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+/**
+ * 保存或者更新
+ * @param params
+ */
+export const saveOrUpdate = (params, isUpdate) => {
+  let url = isUpdate ? Api.edit : Api.save;
+  return defHttp.post({url: url, params});
+}
+
+/**
+* 根据id查询数据
+* @param params
+*/
+export const queryDataById = (id) => defHttp.get({url: Api.queryDataById, params:{ id }});
+
+// 提交
+export const batchSubmit = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认提交',
+    content: '是否提交选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.submitBatch, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+// 取消提交
+export const cancelBatchSubmit = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认取消提交',
+    content: '是否取消提交选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.cancelSubmitBatch, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}

+ 172 - 0
src/views/inventiry/otherOut/otherOutForm.data.ts

@@ -0,0 +1,172 @@
+import {BasicColumn} from '/@/components/Table';
+import {FormSchema} from '/@/components/Table';
+import { rules} from '/@/utils/helper/validator';
+import { render } from '/@/utils/common/renderUtils';
+import {JVxeTypes,JVxeColumn} from '/@/components/jeecg/JVxeTable/types'
+import { getWeekMonthQuarterYear } from '/@/utils';
+//列表数据
+export const columns: BasicColumn[] = [
+   {
+    title: '出库单号(bill code)',
+    align:"center",
+    dataIndex: 'billCode'
+   },   
+   {
+    title: '出库日期(bill date)',
+    align:"center",
+    dataIndex: 'billDate',
+    customRender:({text}) =>{
+      text = !text ? "" : (text.length > 10 ? text.substr(0,10) : text);
+      return text;
+    },
+   },
+  
+   {
+    title: '项目(project)',
+    align:"center",
+    dataIndex: 'projectName'
+   },
+   {
+    title: '客户(customer)',
+    align:"center",
+    dataIndex: 'customerName'
+   },
+   {
+    title: '仓库(warehouse)',
+    align:"center",
+    dataIndex: 'warehouse'
+   },
+   {
+    title: '货位(goods allocation)',
+    align:"center",
+    dataIndex: 'goodsAllocation',
+    width:'250'
+   },
+   {
+    title: '提交(submit)',
+    align:"center",
+    dataIndex: 'submit_dictText',
+   },
+];
+export const otherOutDetailColumns: JVxeColumn[] = [
+    {
+      title: '产品分类(product class)',
+      key: 'productClass',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '产品编码(product code)',
+      key: 'productCode',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '产品中文名(chineseName)',
+      key: 'chineseName',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '产品英文名(englishName)',
+      key: 'englishName',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '型号(model)',
+      key: 'model',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '备件号(partno)',
+      key: 'partno',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '订货号(orderno)',
+      key: 'orderno',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '图号(drawingno)',
+      key: 'drawingno',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '厂家(factory)',
+      key: 'factory',
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+      type: JVxeTypes.normal,
+    },
+    {
+      title: '质量等级(quality grade)',
+      key: 'qualityGrade',
+      type: JVxeTypes.normal,
+      placeholder: '请输入${title}',
+      width:"200px",
+      defaultValue:'',
+    },
+    {
+      title: '出库数量(stock out quantity)',
+      key: 'stockOutQuantity',
+      type: JVxeTypes.inputNumber,
+      placeholder: '请输入${title}',
+      defaultValue:'',  
+      width:"200px",
+    },
+    {
+      title: '库存选择(inventory selsection)',
+      key: 'inventorySelsection',
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+      type: JVxeTypes.slot,
+      // slot 的名称,对应 v-slot 冒号后面和等号前面的内容
+      slotName: 'inventorySelsection',
+      
+    },
+    {
+      title: '备注(notes)',
+      key: 'notes',
+      type: JVxeTypes.input,
+      width:"200px",
+      placeholder: '请输入${title}',
+      defaultValue:'',
+    },
+    {
+      title: '操作(operation)',
+      key: 'action',
+      width:"200px",
+      // 固定在右侧
+      fixed: 'right',
+      // 对齐方式为居中
+      align: 'center',
+      // 组件类型定义为【插槽】
+      type: JVxeTypes.slot,
+      // slot 的名称,对应 v-slot 冒号后面和等号前面的内容
+      slotName: 'action',
+    },
+  ]

+ 346 - 0
src/views/inventiry/otherOut/otherOutList.vue

@@ -0,0 +1,346 @@
+<template>
+    <div class="p-2">
+      <!--查询区域-->
+      <div class="jeecg-basic-table-form-container">
+        <a-form ref="formRef" @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
+          <a-row :gutter="24">
+            <a-col :lg="8">
+                <a-form-item name="billDate">
+                  <template #label><span title="出库日期(bill date)">入库日期(bill date)</span></template>
+                  <a-range-picker value-format="YYYY-MM-DD"  v-model:value="queryParam.billDate" class="query-group-cust"/>
+                </a-form-item>
+            </a-col> 
+            <a-col :lg="8">
+                <a-form-item name="billCode">
+                  <template #label><span title="出库单号(bill code)">入库单号(bill code)</span></template>
+                  <a-input placeholder="请输入入库单号(bill code)" v-model:value="queryParam.billCode" allow-clear ></a-input>
+                </a-form-item>
+            </a-col>          
+            <template v-if="toggleSearchStatus">
+              <a-col :lg="8">
+                <a-form-item name="project">
+                  <template #label><span title="项目(project)">项目(project)</span></template>
+                  <a-input v-model:value="queryParam.project" placeholder="请选择"/>
+                </a-form-item>
+              </a-col>
+              <a-col :lg="8">
+                <a-form-item name="customer">
+                  <template #label><span title="客户(customer)">客户(customer)</span></template>
+                  <a-input placeholder="请输入客户(customer)" v-model:value="queryParam.customer" allow-clear ></a-input>
+                </a-form-item>
+              </a-col>
+              <a-col :lg="8">
+                <a-form-item name="warehouse">
+                  <template #label><span title="仓库(warehouse)">仓库(warehouse)</span></template>
+                  <a-input placeholder="请输" v-model:value="queryParam.warehouse" allow-clear ></a-input>
+                </a-form-item>
+              </a-col>
+              <a-col :lg="8">
+                <a-form-item name="goodsAllocation">
+                  <template #label><span title="货位(goods allocation)">货位(goods allocation)</span></template>
+                  <a-input placeholder="请输" v-model:value="queryParam.goodsAllocation" allow-clear ></a-input>
+                </a-form-item>
+              </a-col>          
+              <a-col :lg="8">
+                <a-form-item name="productCode">
+                  <template #label><span title="产品编号(productCode)">产品编号(productCode)</span></template>
+                  <a-input placeholder="请输入产品编号(productCode)" v-model:value="queryParam.productCode" allow-clear ></a-input>
+                </a-form-item>
+              </a-col> 
+             
+              <a-col :lg="8">
+                <a-form-item name="submit">
+                  <template #label><span title="提交(submit)">提交(submit)</span></template>
+                  <JDictSelectTag v-model:value="queryParam.submit" placeholder="请选择" dictCode="yes_or_no" style="width: 100%;"/>
+                </a-form-item>
+              </a-col>
+            </template>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+                <a-col :lg="6">
+                  <a-button type="primary" preIcon="ant-design:search-outlined" @click="reload">查询</a-button>
+                  <a-button preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
+                  <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
+                    {{ toggleSearchStatus ? '收起' : '展开' }}
+                    <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
+                  </a>
+                </a-col>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+      <!--引用表格-->
+     <BasicTable @register="registerTable" :rowSelection="rowSelection" size="small" >
+       <!--插槽:table标题-->
+        <template #tableTitle>
+            <a-button type="primary" v-auth="'storeCode:store_purchase_other:add'"  @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增(add)</a-button>
+            <a-button  type="primary" v-auth="'storeCode:store_purchase_other:exportXls'"  preIcon="ant-design:export-outlined" @click="onExportXls"> 导出(export)</a-button>
+            <a-button  type="primary"  @click="submit" > 提交(submit)</a-button>
+            <a-button  type="primary"  @click="cancelSubmit"> 取消提交(cancelSubmit)</a-button>
+            <a-dropdown v-if="selectedRowKeys.length > 0">
+                <template #overlay>
+                  <a-menu>
+                    <a-menu-item key="1" @click="batchHandleDelete"  v-auth="'storeCode:store_purchase_other:deleteBatch'">
+                      <Icon icon="ant-design:delete-outlined"></Icon>
+                      删除(delete)
+                    </a-menu-item>
+                  </a-menu>
+                </template>
+                <a-button v-auth="'saleCode:sale_order:delete'">批量操作
+                  <Icon icon="mdi:chevron-down"></Icon>
+                </a-button>
+          </a-dropdown>
+        </template>
+         <!--操作栏-->
+        <template #action="{ record }">
+          <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
+        </template>
+        <!--字段回显插槽-->
+        <template v-slot:bodyCell="{ column, record, index, text }">
+        </template>
+      </BasicTable>
+      <!-- 表单区域 -->
+      <otherOutFormModal @register="registerModal" @success="handleSuccess"></otherOutFormModal>
+    </div>
+  </template>
+  
+  <script lang="ts" name="saleCode-saleInquiryForm" setup>
+    import {ref, reactive, computed, unref,onMounted} from 'vue';
+    import {BasicTable, useTable, TableAction} from '/@/components/Table';
+    import { useListPage } from '/@/hooks/system/useListPage'
+    import {useModal} from '/@/components/Modal';
+    import otherOutFormModal from './components/otherOutFormModal.vue'
+    import {columns} from './otherOutForm.data';
+    import {list, deleteOne, batchDelete, getImportUrl,getExportUrl,batchSubmit,cancelBatchSubmit} from './otherOutForm.api';
+    import { cloneDeep } from "lodash-es";
+    import { JDictSelectTag} from '/@/components/Form';
+    import { message } from 'ant-design-vue';
+    const formRef = ref();
+    const queryParam = reactive<any>({});
+    //注册model
+    const [registerModal, {openModal}] = useModal();
+     //注册table数据
+    const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
+        tableProps:{
+             title: '其他出库',
+             api: list,
+             columns,
+             canResize:false,
+             useSearchForm: false,
+             actionColumn: {
+                 width: 200,
+                 fixed:'right'
+             },
+             scroll:{
+              x:'2500px'
+             },
+             beforeFetch: async (params) => {
+               let rangerQuery = await setRangeQuery();
+               return Object.assign(params, rangerQuery);
+             },
+          },
+          exportConfig: {
+              name:"其他出库",
+              url: getExportUrl,
+              params: queryParam,
+          },
+          importConfig: {
+              url: getImportUrl,
+              success: handleSuccess
+          },
+      })
+  
+    const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
+  
+    /**
+     * 高级查询事件
+     */
+    function handleSuperQuery(params) {
+      Object.keys(params).map((k) => {
+        queryParam[k] = params[k];
+      });
+      reload();
+    }
+  
+     /**
+      * 新增事件
+      */
+    function handleAdd() {
+       openModal(true, {
+         isUpdate: false,
+         showFooter: true,
+       });
+    }
+     /**
+      * 编辑事件
+      */
+    function handleEdit(record: Recordable) {
+       openModal(true, {
+         record,
+         isUpdate: true,
+         showFooter: true,
+       });
+     }     /**
+      * 详情
+     */
+    function handleDetail(record: Recordable) {
+       openModal(true, {
+         record,
+         isUpdate: true,
+         showFooter: false,
+       });
+     }
+     /**
+      * 删除事件
+      */
+    async function handleDelete(record) {
+       await deleteOne({id: record.id}, handleSuccess);
+     }
+     /**
+      * 批量删除事件
+      */
+    async function batchHandleDelete() {
+       await batchDelete({ids: selectedRowKeys.value},handleSuccess);
+     }
+     /**
+      * 成功回调
+      */
+    function handleSuccess() {
+        (selectedRowKeys.value = []) && reload();
+     }
+     /**
+        * 操作栏
+        */
+    function getTableAction(record){
+         return [
+           {
+             label: '编辑(edit)',
+             onClick: handleEdit.bind(null, record),
+             auth: 'storeCode:store_purchase_other:edit',
+             ifShow: record.submit=='0'||!record.submit
+           },
+           {
+             label: '详情(detail)',
+             onClick: handleDetail.bind(null, record),
+             ifShow: record.submit=='1'
+           },
+         ]
+     }
+       /**
+          * 下拉操作栏
+          */
+    function getDropDownAction(record){
+         return [
+           {
+             label: '详情(detail)',
+             onClick: handleDetail.bind(null, record),
+             ifShow: record.submit=='0'||!record.submit
+           },
+           {
+             label: '删除(delete)',
+             popConfirm: {
+               title: '是否确认删除',
+               confirm: handleDelete.bind(null, record),
+               placement: 'topLeft'
+             },
+             auth: 'storeCode:store_purchase_other:delete',
+             ifShow: record.submit=='0'||!record.submit
+           }
+         ]
+     }
+    function submit(){
+      if(selectedRowKeys.value.length==0){
+        message.warning('请选择数据')
+      }else{
+        var ids=selectedRowKeys.value.join(',')
+        batchSubmit({ids: ids},handleSuccess);
+      }
+    }
+    function cancelSubmit(){
+      if(selectedRowKeys.value.length==0){
+        message.warning('请选择数据')
+      }else{
+        var ids=selectedRowKeys.value.join(',')
+        cancelBatchSubmit({ids: ids},handleSuccess);
+      }
+    }
+  
+    /* ----------------------以下为原生查询需要添加的-------------------------- */
+    const toggleSearchStatus = ref<boolean>(false);
+    const labelCol = reactive({
+      xs:24,
+      sm:8,
+    });
+    const wrapperCol = reactive({
+      xs: 24,
+      sm: 16,
+    });
+    const labelCol1 = reactive({
+      xs:24,
+      sm:12,
+    });
+    const wrapperCol1 = reactive({
+      xs: 24,
+      sm: 12,
+    });
+    /**
+     * 重置
+     */
+    function searchReset() {
+      formRef.value.resetFields();
+      selectedRowKeys.value = [];
+      //刷新数据
+      reload();
+    }
+  
+    
+    let rangeField = 'billDate,'
+    
+    /**
+     * 设置范围查询条件
+     */
+    async function setRangeQuery(){
+      let queryParamClone = cloneDeep(queryParam);
+      if (rangeField) {
+        let fieldsValue = rangeField.split(',');
+        fieldsValue.forEach(item => {
+          if (queryParamClone[item]) {
+            let range = queryParamClone[item];
+            queryParamClone[item+'_begin'] = range[0];
+            queryParamClone[item+'_end'] = range[1];
+            delete queryParamClone[item];
+          } else {
+            queryParamClone[item+'_begin'] = '';
+            queryParamClone[item+'_end'] = '';
+          }
+        })
+      }
+      return queryParamClone;
+    }
+  </script>
+  <style lang="less" scoped>
+    .jeecg-basic-table-form-container {
+      padding: 0;
+      .table-page-search-submitButtons {
+        display: block;
+        margin-bottom: 8px;
+        white-space: nowrap;
+      }
+      .query-group-cust{
+        min-width: 100px !important;
+      }
+      .query-group-split-cust{
+        width: 30px;
+        display: inline-block;
+        text-align: center
+      }
+      .ant-form-item:not(.ant-form-item-with-help){
+        margin-bottom: 8px;
+        height: 32px;
+      }
+      :deep(.ant-picker),:deep(.ant-input-number){
+        width: 100%;
+      }
+    }
+  </style>