浏览代码

销售订单-功能点

jingbb 7 月之前
父节点
当前提交
154aac8e00

+ 18 - 16
src/views/saleCode/salesOrder/SaleOrderForm.data.ts

@@ -24,17 +24,17 @@ export const columns: BasicColumn[] = [
    {
     title: '项目(project)',
     align:"center",
-    dataIndex: 'project'
+    dataIndex: 'projectName'
    },
    {
     title: '客户(customer)',
     align:"center",
-    dataIndex: 'customer'
+    dataIndex: 'customerName'
    },
    {
     title: '优先级(priority)',
     align:"center",
-    dataIndex: 'priority'
+    dataIndex: 'priority_dictText'
    },
    {
     title: '产品分类(production class)',
@@ -89,12 +89,12 @@ export const columns: BasicColumn[] = [
    {
     title: '客户确认(customer confirm)',
     align:"center",
-    dataIndex: 'customerConfirm',
+    dataIndex: 'status',
     customRender:function (t, r, index) {
       if(t.text==1){
-        return '是(yes)'
+        return '已确认'
       }else if(t.text==0){
-        return '否(no)'
+        return '未确认'
       }
     }
    },
@@ -102,13 +102,15 @@ export const columns: BasicColumn[] = [
     title: '基础协议(base protocaol)',
     align:"center",
     dataIndex: 'baseProtocaol',
-    width:'250'
+    width:'250',
+    slots: { customRender: 'viewFile' },
    },
    {
     title: '扫描合同(scan contract)',
     align:"center",
-    dataIndex: 'baseProtocaol',
-    width:'250'
+    dataIndex: 'scanProtocaol',
+    width:'250',
+    slots: { customRender: 'viewFile' },
    },
    {
     title: '订单金额(order money)',
@@ -119,7 +121,7 @@ export const columns: BasicColumn[] = [
    {
     title: '发货金额(delivery money)',
     align:"center",
-    dataIndex: 'deluveryMoney',
+    dataIndex: 'deliveryMoney',
     width:'250'
    },
    {
@@ -131,7 +133,7 @@ export const columns: BasicColumn[] = [
    {
     title: '收款金额(collected money)',
     align:"center",
-    dataIndex: 'invoiceMoney',
+    dataIndex: 'collectedMoney',
     width:'250'
    },
 ];
@@ -301,7 +303,7 @@ export const saleOrderProductColumns: JVxeColumn[] = [
       type: JVxeTypes.normal,
     },
     {
-      title: '含税单价(tax price)',
+      title: '单价(price)',
       key: 'taxPrice',
       type: JVxeTypes.inputNumber,
       width:"200px",
@@ -309,8 +311,8 @@ export const saleOrderProductColumns: JVxeColumn[] = [
       defaultValue:'',
     },
     {
-      title: '含税金额(tax money)',
-      key: 'taxMoney',
+      title: '金额(money)',
+      key: 'taxAmount',
       type: JVxeTypes.inputNumber,
       width:"200px",
       placeholder: '请输入${title}',
@@ -318,7 +320,7 @@ export const saleOrderProductColumns: JVxeColumn[] = [
     },
     {
       title: '折后单价(discounted unit price)',
-      key: 'discountedUnitPrice',
+      key: 'discountedPrice',
       type: JVxeTypes.inputNumber,
       width:"200px",
       placeholder: '请输入${title}',
@@ -326,7 +328,7 @@ export const saleOrderProductColumns: JVxeColumn[] = [
     },
     {
       title: '折后金额(converted amount)',
-      key: 'convertedAmount',
+      key: 'discountedAmount',
       type: JVxeTypes.inputNumber,
       width:"200px",
       placeholder: '请输入${title}',

+ 152 - 27
src/views/saleCode/salesOrder/SaleOrderFormList.vue

@@ -12,8 +12,8 @@
           </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>
+                <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">
@@ -25,26 +25,26 @@
             </a-col>
             <a-col :lg="8">
               <a-form-item name="inquiryCustomer">
-                <template #label><span title="客户(inquiry customer)">询价客户(inquiry customer)</span></template>
-                <a-input placeholder="请输入询价客户(inquiry customer)" v-model:value="queryParam.inquiryCustomer" allow-clear ></a-input>
+                <template #label><span title="客户(customer)">客户(customer)</span></template>
+                <a-input placeholder="请输入询价客户(inquiry customer)" v-model:value="queryParam.customerName" allow-clear ></a-input>
               </a-form-item>
             </a-col>
             <a-col :lg="8">
               <a-form-item name="priority">
                 <template #label><span title="优先级(priority)">优先级(priority)</span></template>
-                <JDictSelectTag v-model:value="queryParam.priority" placeholder="请选择" dictCode="priority"/>
+                <JDictSelectTag v-model:value="queryParam.priority" placeholder="请选择" dictCode="priority" style="width: 100%;"/>
               </a-form-item>
             </a-col>
             <a-col :lg="8">
               <a-form-item name="productionClass" >
                 <template #label><span title="产品分类(production class)">产品分类(production class)</span></template>
-                <JSelectInput   v-model:value="queryParam.productionClass"  placeholder="请选择" :options="classOption" ></JSelectInput>
+                <JSelectInput   v-model:value="queryParam.productionClass"  placeholder="请选择" :options="classOption" style="width: 100%;"></JSelectInput>
               </a-form-item>
             </a-col>
             <a-col :lg="8">
               <a-form-item name="model">
                 <template #label><span title="机型(model)">机型(model)</span></template>
-                <JDictSelectTag v-model:value="queryParam.model" placeholder="请选择" dictCode="model_typer"/>
+                <JDictSelectTag v-model:value="queryParam.model" placeholder="请选择" dictCode="model_typer" style="width: 100%;"/>
               </a-form-item>
             </a-col>
             <a-col :lg="8">
@@ -55,7 +55,7 @@
             </a-col>            
             <a-col :lg="8">
               <a-form-item name="saleDepartment" >
-                <template #label><span title="销售部门(sale department)">销售部门(sale department)</span></template>
+                <template #label><span title="销售部门(sale saleDepartment)">销售部门(sale department)</span></template>
 								<JSelectDept v-model:value="queryParam.saleDepartment" :multiple="false" />
               </a-form-item>
             </a-col>
@@ -66,21 +66,21 @@
               </a-form-item>
             </a-col>
             <a-col :lg="8">
-              <a-form-item name="customerConfirm" :label-col="labelCol1" :wrapper-col="wrapperCol1">
-                <template #label><span title="客户确认(customer confirm)">客户确认(customer confirm)</span></template>
-                <JDictSelectTag v-model:value="queryParam.customerConfirm" placeholder="请选择" dictCode="yes_or_no"/>
+              <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>
             <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"/>
+              <a-form-item name="customerConfirm">
+                <template #label><span title="客户确认(customer confirm)">客户确认(customer confirm)</span></template>
+                <JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="customer_confirm"/>
               </a-form-item>
             </a-col>
             <a-col :lg="8">
               <a-form-item name="close">
                 <template #label><span title="关闭(close)">关闭(close)</span></template>
-                <JDictSelectTag v-model:value="queryParam.close" placeholder="请选择" dictCode="yes_or_no"/>
+                <JDictSelectTag v-model:value="queryParam.close" placeholder="请选择" dictCode="yes_or_no" style="width: 100%;"/>
               </a-form-item>
             </a-col> 
           </template>
@@ -103,20 +103,24 @@
    <BasicTable @register="registerTable" :rowSelection="rowSelection" size="small" >
      <!--插槽:table标题-->
       <template #tableTitle>
-          <a-button type="primary" v-auth="'saleCode:sale_inquiry_form:add'"  @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增(add)</a-button>
-          <a-button  type="primary" v-auth="'saleCode:sale_inquiry_form:exportXls'"  preIcon="ant-design:export-outlined" @click="onExportXls"> 导出(export)</a-button>
-          <a-button  type="primary"  @click="submit" v-auth="'saleCode:sale_inquiry_form:submitBatch'"> 提交(submit)</a-button>
-          <a-button  type="primary"  @click="cancelSubmit" v-auth="'saleCode:sale_inquiry_form:returnSubmitBatch'"> 取消提交(cancelSubmit)</a-button>
+          <a-button type="primary" v-auth="'saleCode:sale_order:add'"  @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增(add)</a-button>
+          <a-button  type="primary" v-auth="'saleCode:sale_order: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-button  type="primary"  @click="close"> 关闭(close)</a-button>
+          <a-button  type="primary"  @click="cancelClose"> 取消关闭(cancel close)</a-button>
+          <a-button  type="primary"  @click="confirm"> 确认(confirm)</a-button>
+          <a-button  type="primary"  @click="cancelConfirm"> 取消确认(cancel confirm)</a-button>
           <a-dropdown v-if="selectedRowKeys.length > 0">
               <template #overlay>
                 <a-menu>
-                  <a-menu-item key="1" @click="batchHandleDelete"  v-auth="'saleCode:sale_inquiry_form:deleteBatch'">
+                  <a-menu-item key="1" @click="batchHandleDelete"  v-auth="'saleCode:sale_order_form:deleteBatch'">
                     <Icon icon="ant-design:delete-outlined"></Icon>
                     删除(delete)
                   </a-menu-item>
                 </a-menu>
               </template>
-              <a-button v-auth="'saleCode:sale_inquiry_form:deleteBatch'">批量操作
+              <a-button v-auth="'saleCode:sale_order:delete'">批量操作
                 <Icon icon="mdi:chevron-down"></Icon>
               </a-button>
         </a-dropdown>
@@ -128,9 +132,16 @@
       <!--字段回显插槽-->
       <template v-slot:bodyCell="{ column, record, index, text }">
       </template>
+      //
+      <template #viewFile="props">
+        <a @click="viewFileDetail(props)">查看(view)</a>
+      </template>
     </BasicTable>
     <!-- 表单区域 -->
     <SaleInquiryFormModal @register="registerModal" @success="handleSuccess"></SaleInquiryFormModal>
+    <ViewFileListModal ref="ViewFileListModalRef"></ViewFileListModal>
+    <SelectSaleOrderModal ref="SelectSaleOrderModalRef" @copyProduct="handleCopyProduct"></SelectSaleOrderModal>
+    <ViewHistoryVersionModal ref="ViewHistoryVersionModallRef" ></ViewHistoryVersionModal>
   </div>
 </template>
 
@@ -141,15 +152,21 @@
   import {useModal} from '/@/components/Modal';
   import SaleInquiryFormModal from './components/SaleOrderFormModal.vue'
   import {columns, superQuerySchema} from './SaleOrderForm.data';
-  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl,batchSubmit,cancelBatchSubmit} from './SaleOrderyForm.api';
+  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl,batchSubmit,cancelBatchSubmit,bacthClose,cancelBatchClose,bacthConfirm,cancelBatchConfirm} from './SaleOrderyForm.api';
   import { cloneDeep } from "lodash-es";
   import { defHttp } from '/@/utils/http/axios';
   import { JDictSelectTag} from '/@/components/Form';
   import JSelectInput from '/@/components/Form/src/jeecg/components/JSelectInput.vue';
   import JSelectUser from '/@/components/Form/src/jeecg/components/JSelectUser.vue';
   import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
+  import ViewFileListModal from './components/ViewFileListModal.vue';
+  import SelectSaleOrderModal from './components/SelectSaleOrderModal.vue';
+  import ViewHistoryVersionModal from './components/ViewHistoryVersionModal.vue';
   import { message } from 'ant-design-vue';
   const formRef = ref();
+  const ViewFileListModalRef = ref();
+  const SelectSaleOrderModalRef = ref()
+  const ViewHistoryVersionModallRef =ref()
   const queryParam = reactive<any>({});
   //注册model
   const [registerModal, {openModal}] = useModal();
@@ -211,6 +228,7 @@
      openModal(true, {
        isUpdate: false,
        showFooter: true,
+       isRevise: false
      });
   }
    /**
@@ -221,8 +239,40 @@
        record,
        isUpdate: true,
        showFooter: true,
+       isRevise: false
+     });
+   }
+
+   //修订
+   function handleRevise(record: Recordable){
+    openModal(true, {
+       record,
+       isUpdate: true,
+       showFooter: true,
+       isRevise: true
      });
    }
+
+   //查看历史版本
+   function viewHistoryList(record){
+    ViewHistoryVersionModallRef.value.getTable(record)
+   }
+   //复制
+   function handleCopy(record: Recordable){
+    SelectSaleOrderModalRef.value.getTable(record)
+   }
+   //下载合同
+   function handleDownContract(){
+
+   }
+   //上传基本协议
+   function handleUploadProtocol(){
+
+   }
+   //上传基础协议
+   function handleExportInvoice(){
+
+   }
   //  产品分类
   function getOptiom(){
         defHttp
@@ -279,8 +329,15 @@
          {
            label: '编辑(edit)',
            onClick: handleEdit.bind(null, record),
-           auth: 'saleCode:sale_inquiry_form:edit'
-         }
+           auth: 'saleCode:sale_order:edit',
+           ifShow: record.submit=='0'
+         },
+         {
+           label: '修订(revise)',
+           onClick: handleRevise.bind(null, record),
+           auth: 'saleCode:sale_order:editHis',
+           ifShow: record.submit=='1'
+         },
        ]
    }
      /**
@@ -291,14 +348,39 @@
          {
            label: '详情(detail)',
            onClick: handleDetail.bind(null, record),
-         }, {
+         }, 
+         {
+           label: '查看历史版本(view history)',
+           onClick: viewHistoryList.bind(null, record),
+           auth: 'saleCode:sale_inquiry_form:delete',
+           ifShow: record.submit=='1'
+         },
+         {
+           label: '复制(copy)',
+           onClick: handleCopy.bind(null, record),
+           auth: 'saleCode:sale_inquiry_form:delete',
+         },
+        //  {
+        //    label: '导出发票(export invoice)',
+        //    onClick: handleExportInvoice.bind(null, record),
+        //    auth: 'saleCode:sale_inquiry_form:delete',
+        //    ifShow: record.submit=='1'
+        //  },
+        //  {
+        //    label: '导出预收款发票(export invoice)',
+        //    onClick: handleDetail.bind(null, record),
+        //    auth: 'saleCode:sale_inquiry_form:delete',
+        //    ifShow: record.submit=='1'
+        //  },
+         {
            label: '删除(delete)',
            popConfirm: {
              title: '是否确认删除',
              confirm: handleDelete.bind(null, record),
              placement: 'topLeft'
            },
-           auth: 'saleCode:sale_inquiry_form:delete'
+           auth: 'saleCode:sale_order:delete',
+           ifShow: record.submit=='0'
          }
        ]
    }
@@ -318,8 +400,51 @@
       cancelBatchSubmit({ids: ids},handleSuccess);
     }
   }
+  function close(){
+      if(selectedRowKeys.value.length==0){
+        message.warning('请选择数据')
+      }else{
+        var ids=selectedRowKeys.value.join(',')
+        bacthClose({ids: ids},handleSuccess);
+      }
+    }
+  function cancelClose(){
+    if(selectedRowKeys.value.length==0){
+      message.warning('请选择数据')
+    }else{
+      var ids=selectedRowKeys.value.join(',')
+      cancelBatchClose({ids: ids},handleSuccess);
+    }
+  }
+  function confirm(){
+      if(selectedRowKeys.value.length==0){
+        message.warning('请选择数据')
+      }else{
+        var ids=selectedRowKeys.value.join(',')
+        bacthConfirm({ids: ids},handleSuccess);
+      }
+  }
+  function cancelConfirm(){
+    if(selectedRowKeys.value.length==0){
+      message.warning('请选择数据')
+    }else{
+      var ids=selectedRowKeys.value.join(',')
+      cancelBatchConfirm({ids: ids},handleSuccess);
+    }
+  }
 
-  
+  function viewFileDetail(props){
+    ViewFileListModalRef.value.getTable(props.column.dataIndex,props.record)
+  }
+  function handleCopyProduct(data,mainId){
+    openModal(true, {
+       data,
+       mainId,
+       isUpdate: false,
+       showFooter: true,
+       isCopy: true,
+     });
+  }
 
   /* ----------------------以下为原生查询需要添加的-------------------------- */
   const toggleSearchStatus = ref<boolean>(false);

+ 99 - 15
src/views/saleCode/salesOrder/SaleOrderyForm.api.ts

@@ -4,18 +4,26 @@ import { useMessage } from "/@/hooks/web/useMessage";
 const { createConfirm } = useMessage();
 
 enum Api {
-  list = '/saleCode/saleInquiryForm/list',
-  save='/saleCode/saleInquiryForm/add',
-  edit='/saleCode/saleInquiryForm/edit',
-  deleteOne = '/saleCode/saleInquiryForm/delete',
-  deleteBatch = '/saleCode/saleInquiryForm/deleteBatch',
-  importExcel = '/saleCode/saleInquiryForm/importExcel',
-  exportXls = '/saleCode/saleInquiryForm/exportXls',
-  queryDataById = '/saleCode/saleInquiryForm/queryById',
-  saleInquiryFormShipList = '/saleCode/saleInquiryForm/querySaleInquiryFormShipByMainId',
-  saleInquiryFormProductList = '/saleCode/saleInquiryForm/querySaleInquiryFormProductByMainId',
-  submitBatch='/saleCode/saleInquiryForm/submitBatch',
-  cancelSubmitBatch='/saleCode/saleInquiryForm/returnSubmitBatch'
+  list = '/saleCode/saleOrder/list',
+  save='/saleCode/saleOrder/add',
+  edit='/saleCode/saleOrder/edit',
+  revise='/saleCode/saleOrder//editHis',
+  deleteOne = '/saleCode/saleOrder/delete',
+  deleteBatch = '/saleCode/saleOrder/deleteBatch',
+  importExcel = '/saleCode/saleOrder/importExcel',
+  exportXls = '/saleCode/saleOrder/exportXls',
+  queryDataById = '/saleCode/saleOrder/queryById',
+  queryVersonHistoryById='/saleCode/saleOrderHis/queryById',
+  saleOrderFormShipList = '/saleCode/saleOrder/querySaleOrderShipByMainId',
+  saleVersonFormShipList = '/saleCode/saleOrderHis/querySaleOrderShipHisByMainId',
+  saleOrderFormProductList = '/saleCode/saleOrder/querySaleOrderProductByMainId',
+  salVersonFormProductList = '/saleCode/saleOrderHis/querySaleOrderProductHisByMainId',
+  submitBatch='/saleCode/saleOrder/submitBatch',
+  cancelSubmitBatch='saleCode/saleOrder/returnSubmitBatch',
+  closeBatch='/saleCode/saleOrder/submitClose',
+  cancelBatchClose = '/saleCode/saleOrder/returnClose',
+  confirmBatch='/saleCode/saleOrder/submitConfirm',
+  cancelBatchConfirm = '/saleCode/saleOrder/returnSubmitConfirm'
 }
 /**
  * 导出api
@@ -32,12 +40,12 @@ export const getImportUrl = Api.importExcel;
  * 查询子表数据
  * @param params
  */
-export const querySaleOrderFormShipFormShippTable = (id) => defHttp.get({url: Api.saleInquiryFormShipList, params:{ id }});
+export const querySaleOrderFormShipFormShippTable = (id) => defHttp.get({url: Api.saleOrderFormShipList, params:{ id }});
 /**
  * 查询子表数据
  * @param params
  */
-export const querySaleOrderFormProductListByMainId = (id) => defHttp.get({url: Api.saleInquiryFormProductList, params:{ id }});
+export const querySaleOrderFormProductListByMainId = (id) => defHttp.get({url: Api.saleOrderFormProductList, params:{ id }});
 
 /**
  * 列表接口
@@ -76,8 +84,9 @@ export const batchDelete = (params, handleSuccess) => {
  * 保存或者更新
  * @param params
  */
-export const saveOrUpdate = (params, isUpdate) => {
+export const saveOrUpdate = (params, isUpdate,isRevise) => {
   let url = isUpdate ? Api.edit : Api.save;
+  url = isRevise?Api.revise:url;
   return defHttp.post({url: url, params});
 }
 
@@ -87,6 +96,21 @@ export const saveOrUpdate = (params, isUpdate) => {
 */
 export const queryDataById = (id) => defHttp.get({url: Api.queryDataById, params:{ id }});
 
+//查询历史版本详情主表
+export const queryVersonHistoryById = (id) => defHttp.get({url: Api.queryVersonHistoryById, params:{ id }});
+
+/**
+ * 查询历史版本船子表数据
+ * @param params
+ */
+export const querysaleVersonFormShipListByMainId = (id) => defHttp.get({url: Api.saleVersonFormShipList, params:{ id }});
+
+/**
+ * 查询历史版本产品子表数据
+ * @param params
+ */
+export const querySaleVersonProductListByMainId = (id) => defHttp.get({url: Api.salVersonFormProductList, params:{ id }});
+
 // 提交
 export const batchSubmit = (params, handleSuccess) => {
   createConfirm({
@@ -116,4 +140,64 @@ export const cancelBatchSubmit = (params, handleSuccess) => {
       });
     }
   });
+}
+// 关闭
+export const bacthClose = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认关闭',
+    content: '是否关闭选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.closeBatch, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+// 取消关闭
+export const cancelBatchClose = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认取消关闭',
+    content: '是否取消关闭选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.cancelBatchClose, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+// 确认
+export const bacthConfirm = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认客户确认',
+    content: '是否客户确认选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.confirmBatch, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
+}
+// 取消确认
+export const cancelBatchConfirm = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认取消客户确认',
+    content: '是否取消客户确认选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.get({url: Api.cancelBatchConfirm, params}, {joinParamsToUrl: true}).then(() => {
+        handleSuccess();
+      });
+    }
+  });
 }

+ 110 - 0
src/views/saleCode/salesOrder/components/FileUploadModal.vue

@@ -0,0 +1,110 @@
+<template>
+    <a-modal
+      :title="title"
+      width="45%"
+      :visible="visible"
+      :maskClosable="false"
+      ref="FileUploadModalRef"
+      switchFullscreen
+      @ok = "handleOk"
+      @cancel="handleCancel">
+        <div>
+          <a-card >
+            <div class="table-page-search-wrapper">
+                <a-form :model="queryParams" :label-col="labelCol" :wrapper-col="wrapperCol">
+                <a-row :gutter="24">
+                    <a-col :xl="24" :lg="24" :md="24">
+                        <a-form-item label="名字(name)">
+                            <a-input placeholder="请输入" v-model:value="queryParams.name"></a-input>
+                        </a-form-item>
+                    </a-col>
+                    <a-col :xl="24" :lg="24" :md="24">
+                        <a-form-item label="附件(attachs)">
+							<JUpload v-model:value="queryParams.attachs"></JUpload>
+						</a-form-item>
+                    </a-col>
+                </a-row>
+            </a-form>
+           </div>
+        </a-card>
+      </div>
+    </a-modal>
+</template>
+<script lang="ts" setup>
+    import {ref,reactive  } from 'vue';
+    import { defHttp } from '/@/utils/http/axios';
+    import { message,Modal  } from 'ant-design-vue';
+    import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
+    import { idText } from 'typescript';
+    const emit = defineEmits([ 'addList']); //定义emit
+    var visible = ref(false)
+    var title = ref('')
+    var executeMethod =ref('')
+    const labelCol = reactive({
+        xs:24,
+        sm:4,
+    });
+    const wrapperCol = reactive({
+        xs: 24,
+        sm: 16,
+    });
+    const FileUploadModalRef = ref();
+    const queryParams = ref({
+        name:'',
+        attachs:'',
+        headId:'',
+        type:''
+    });
+    function handleOk(){
+        let executeUrl = ''
+        if(executeMethod.value=='add'){
+            executeUrl = '/saleCode/saleOrderFiles/add'
+        }else{
+            executeUrl = '/saleCode/saleOrderFiles/edit'
+        }
+        defHttp.post({ url: executeUrl, params: queryParams.value }, { isTransformResponse: false }).then((res) => {
+          if (res.success) {
+            emit('addList');
+            message.warning(res.message);
+            handleCancel()
+          } else {
+            message.warning(res.message);
+          }
+        })
+    }
+    function handleCancel(){
+      visible.value = false
+      Modal.destroyAll();
+    }
+    function getTable(fatherId,fatherTitle,status,id){
+        visible.value = true
+        queryParams.value.headId = fatherId.value
+        title.value = fatherTitle.value=='scanProtocaol'?'扫描合同查看(view scan contract)':'基础协议查看(view basic agreement)'
+        queryParams.value.type = fatherTitle.value=='scanProtocaol'?'1':'2'
+        executeMethod.value = status
+        if(status=='edit'){
+            getForm(id)
+        }
+    }
+    function getForm(id){
+        defHttp.get({ url: '/saleCode/saleOrderFiles/queryById', params: {id:id} }, { isTransformResponse: false }).then((res) => {
+          if (res.success) {
+            queryParams.value = res.result
+          } else {
+            message.warning(res.message);
+          }
+        })
+    }
+    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>

+ 27 - 10
src/views/saleCode/salesOrder/components/SaleOrderFormModal.vue

@@ -1,6 +1,6 @@
 <template>
   <div ref="SaleOrderDetailsRef">
-    <BasicModal v-bind="$attrs" @register="registerModal" :title="title" width="95%" height="10%" @ok="handleSubmit" :getContainer ='()=>$refs.SaleOrderDetailsRef'>
+    <BasicModal v-bind="$attrs" @register="registerModal" :title="title" width="95%"  @ok="handleSubmit" :getContainer ='()=>$refs.SaleOrderDetailsRef'>
       <SlaeOrderFormForm ref="formComponent" :formDisabled="formDisabled" :formBpm="false" @success="submitSuccess"></SlaeOrderFormForm>
     </BasicModal>
   </div>
@@ -27,13 +27,21 @@
       //表单赋值
       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)
+        if(!data.isCopy){
+          isUpdate.value = !!data?.isUpdate;
+          formDisabled.value = !data?.showFooter;
+          title.value = data?.isUpdate ? (unref(formDisabled) ? '详情' : '编辑') : '新增';
+          title.value = data.isRevise?'修订':title.value;
+          if (unref(isUpdate)) {
+            formComponent.value.edit(data.record)
+          }else{
+            formComponent.value.add()
+          }
         }else{
-          formComponent.value.add()
+          isUpdate.value = !!data?.isUpdate;
+          formDisabled.value = !data?.showFooter;
+          title.value = '新增'
+          formComponent.value.copy(data.data,data.mainId)
         }
       });
 
@@ -45,6 +53,14 @@
         emit('success');
         closeModal();
       }
+      function getVersionDetail(record){
+        setModalProps({open: true,showOkBtn:false});
+        title.value ='详情'
+        formDisabled.value = true
+        setTimeout(()=>{
+          formComponent.value.VersionDetail(record)
+        },100)
+      }
 
       return {
         registerModal,
@@ -53,7 +69,8 @@
         formDisabled,
         handleSubmit,
         submitSuccess,
-        SaleOrderDetailsRef
+        SaleOrderDetailsRef,
+        getVersionDetail
       }
     }
   }
@@ -68,9 +85,9 @@
     width: 100%;
   }
   /deep/.ant-modal {
-    width: 520px;
+    // width: 520px;
     padding-bottom: 0;
-    margin-top: -92px;
+    margin-top: -10px;
     height: 100%;
 }
 </style>

+ 296 - 0
src/views/saleCode/salesOrder/components/SelectSaleOrderModal.vue

@@ -0,0 +1,296 @@
+<template>
+  <a-modal
+    title="选择销售订单(select sale order)"
+    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="8" :sm="8">
+                          <a-form-item label="产品分类(production class)">
+                              <a-input placeholder="请输入" v-model:value="queryParams.productionClass"></a-input>
+                          </a-form-item>
+                      </a-col>
+                     
+                      <a-col :md="8" :sm="8">
+                          <a-form-item label="产品英文名(english name)" >
+                              <a-input v-model:value="queryParams.englishName" placeholder="请选择" />
+                          </a-form-item>
+                      </a-col>
+                  <template v-if="toggleSearchStatus">                     
+                      <a-col :md="8" :sm="8">
+                          <a-form-item label="产品编码(product code)" >
+                              <a-input v-model:value="queryParams.productCode" placeholder="请选择" />
+                          </a-form-item>
+                      </a-col>
+                      <a-col :md="8" :sm="8">
+                          <a-form-item label="产品中文名(chinese name)" >
+                              <a-input v-model:value="queryParams.chineseName" placeholder="请选择" />
+                          </a-form-item>
+                      </a-col>
+                  </template>
+                  <a-col :md="8" :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  >
+          <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.id"
+              :data-source="dataSource"
+              bordered
+              size="small"
+              @change="handleTableChange"
+              :pagination="false"
+              :scroll="{ x: 4500, 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';
+  const emit = defineEmits([ 'copyProduct']); //定义emit
+  var visible = ref(false)
+  const columns = [
+      {
+          title: '交期(delivery time)',
+          dataIndex: 'deliveryTime',
+          key: 'deliveryTime',
+          align:"center"
+      },
+      {
+          title: '产品分类(product class)',
+          dataIndex: 'productClass',
+          key: 'productClass',
+          align:"center"
+      },
+      {
+          title: '产品编码(product code)',
+          dataIndex: 'productCode',
+          key: 'productCode',
+          align:"center",
+      },
+      {
+          title: '产品中文名(chinese name)',
+          key: 'chineseName',
+          dataIndex: 'chineseName',
+          align:"center"
+      },
+      {
+          title: '产品英文名(english name)',
+          key: 'englishName',
+          dataIndex: 'englishName',
+          align:"center"
+      },
+      {
+          title: '型号(model)',
+          key: 'model',
+          dataIndex: 'model',
+          align:"center"
+      },
+      {
+          title: '备件号(partno)',
+          key: 'partno',
+          dataIndex: 'partno',
+          align:"center",
+          width:250
+      },
+      {
+          title: '订货号(orderno)',
+          key: 'orderno',
+          dataIndex: 'orderno',
+          align:"center",
+      },
+      {
+          title: '图号(drawingno)',
+          key: 'drawingno',
+          dataIndex: 'drawingno',
+          align:"center",
+      },
+      {
+          title: '厂家(factory)',
+          key: 'factory',
+          dataIndex: 'factory',
+          align:"center",
+      },
+      {
+          title: '质量等级(quality grade)',
+          key: 'qualityGrade',
+          dataIndex: 'qualityGrade',
+          align:"center",
+      },
+      {
+          title: '数量(quantity)',
+          key: 'quantity',
+          dataIndex: 'quantity',
+          align:"center",
+      },
+      {
+          title: '税率(tax rate)',
+          key: 'taxRate',
+          dataIndex: 'taxRate',
+          align:"center",
+      },
+      {
+          title: '折扣(discount)',
+          key: 'discount',
+          dataIndex: 'discount',
+          align:"center",
+      },
+      {
+          title: '单价(price)',
+          key: 'taxPrice',
+          dataIndex: 'taxPrice',
+          align:"center",
+      },
+      {
+          title: '金额(money)',
+          key: 'taxAmount',
+          dataIndex: 'taxAmount',
+          align:"center",
+      },
+      {
+          title: '折后单价(discounted unit price)',
+          key: 'discountedPrice',
+          dataIndex: 'discountedPrice',
+          align:"center",
+      },
+      {
+          title: '折后金额(converted amount)',
+          key: 'discountedAmount',
+          dataIndex: 'discountedAmount',
+          align:"center",
+      },
+  ];
+  const labelCol = ref({
+      xs: { span: 24 },
+      sm: { span: 9 },
+  });
+  const wrapperCol = ref({
+      xs: { span: 24 },
+      sm: { span: 15 },
+  });
+  const dataSource =ref([]);
+  let selectedRowKeys = ref([]);
+  let selectedRows = ref([]);
+  const toggleSearchStatus = ref(false);
+  var mainId = ref('')
+  const queryParams = ref({
+      productionClass:'',
+      englishName:'',
+      productCode:'',
+      chineseName:'',
+      id:'',
+      pageSize:''
+  });
+  function loadData(){
+      let params = getQueryParams();
+      defHttp
+      .get({ url: '/saleCode/saleOrder/querySaleOrderProductByMainId',params}, { isTransformResponse: false })
+      .then((res) => {
+          if (res.success) {
+              dataSource.value = res.result              
+          } else {
+              message.error(res.message);
+          }
+      })
+      .finally(() => {
+          // loading.value = false;
+      });
+  }
+  function getQueryParams(){
+      let params = Object.assign(queryParams.value);
+      params.id = mainId.value
+      params.pageSize = '-1'
+      return filterObj(params);
+  }
+  function handleTableChange(paginations, filters, sorter){
+      loadData()
+  };
+  function searchQuery(){
+      loadData();
+  }
+  function searchReset(){
+      queryParams.value = {
+        productionClass:'',
+        englishName:'',
+        productCode:'',
+        chineseName:'',
+        id:'',
+        pageSize:''
+      }
+      loadData();
+  }
+  function handleToggleSearch(){
+      toggleSearchStatus.value = !toggleSearchStatus.value;
+  }
+  function onSelectChange(keys,rows){
+      selectedRowKeys.value = keys
+      selectedRows.value = rows
+  }
+  function handleOk(){
+    if(selectedRowKeys.value.length==0){
+      message.error('请选择数据')
+    }else{
+      emit('copyProduct',selectedRows.value,mainId)
+      handleCancel()
+    }
+  }
+  function handleCancel(){
+    visible.value = false
+    selectedRowKeys.value = []
+    selectedRows.value=[]
+  }
+  function getTable(record){
+      mainId.value = record.id
+      visible.value = true
+      loadData()
+  }
+  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>

+ 235 - 54
src/views/saleCode/salesOrder/components/SlaeOrderFormForm.vue

@@ -16,28 +16,28 @@
 						</a-col>
 						
 						<a-col :span="12">
-							<a-form-item label="项目(project)" v-bind="validateInfos.project" id="SaleOrderForm-project" name="project">
-								<a-input-search v-model:value="formData.project" placeholder="请输入项目(project)" :disabled="SaleOrderFormShipFormProductTable.dataSource.length!==0"  allow-clear enter-button="Search" ></a-input-search>
+							<a-form-item label="项目(project)" v-bind="validateInfos.projectName" id="SaleOrderForm-projectName" name="projectName">
+								<a-input-search v-model:value="formData.projectName" placeholder="请输入项目(project)" :disabled="SaleOrderFormShipFormProductTable.dataSource.length!==0"  allow-clear enter-button="Search" @search="onSearchProject"></a-input-search>
 							</a-form-item>
 						</a-col>
 						<a-col :span="12">
-							<a-form-item label="客户(customer)" v-bind="validateInfos.customer" id="SaleOrderForm-customer" name="customer">
-                  <a-input   v-model:value="formData.customer"  placeholder="请选择" allow-clear  ></a-input>
+							<a-form-item label="客户(customer)" v-bind="validateInfos.customerName" id="SaleOrderForm-customerName" name="customerName">
+                  <a-input   v-model:value="formData.customerName"  placeholder="请选择" allow-clear  disabled></a-input>
 							</a-form-item>
 						</a-col>
             <a-col :span="12">
 							<a-form-item label="中间人(intermediator)" v-bind="validateInfos.intermediator" id="SaleOrderForm-intermediator" name="intermediator">
-                  <a-input   v-model:value="formData.intermediator"  placeholder="请选择" allow-clear  ></a-input>
+                  <a-input   v-model:value="formData.intermediatorName"  placeholder="请选择" allow-clear  disabled></a-input>
 							</a-form-item>
 						</a-col>
 						<a-col :span="12">
 							<a-form-item label="优先级(priority)" v-bind="validateInfos.priority" id="SaleOrderForm-priority" name="priority">
-                <JDictSelectTag v-model:value="formData.priority" placeholder="请选择" dictCode="priority"/>
+                <JDictSelectTag v-model:value="formData.priority" placeholder="请选择" dictCode="priority" disabled/>
 							</a-form-item>
 						</a-col>
 						<a-col :span="12">
 							<a-form-item label="产品分类(production class)" v-bind="validateInfos.productionClass" id="SaleOrderForm-productionClass" name="productionClass">
-								<a-input v-model:value="formData.productionClass" placeholder="请输入"  allow-clear disabled></a-input>
+								<a-input v-model:value="formData.productionClass" placeholder="请输入"  allow-clear disabled ></a-input>
 							</a-form-item>
 						</a-col>
 						<a-col :span="12">
@@ -50,25 +50,35 @@
 								<a-input v-model:value="formData.maker" placeholder="请输入厂家(maker)"  allow-clear disabled></a-input>
 							</a-form-item>
 						</a-col>
+            <a-col :span="12">
+							<a-form-item label="币种(currency)" v-bind="validateInfos.currency" id="SaleOrderForm-currency" name="currency">
+                <JDictSelectTag v-model:value="formData.currency" placeholder="请选择" dictCode="currency" disabled/>
+							</a-form-item>
+						</a-col>
+						<a-col :span="12">
+							<a-form-item label="汇率(exchange rate)" v-bind="validateInfos.exchangeRate" id="SaleOrderForm-exchangeRate" name="exchangeRate">
+								<a-input v-model:value="formData.exchangeRate" placeholder="请输入厂家(maker)"  allow-clear ></a-input>
+							</a-form-item>
+						</a-col>
 						<a-col :span="12">
-							<a-form-item label="交货条款(delivery term)" v-bind="validateInfos.deliveryTerm" id="SaleOrderForm-deliveryTerm" name="deliveryTerm">
-                <JDictSelectTag v-model:value="formData.deliveryTerm" placeholder="请选择" dictCode="delivery_terms"/>
+							<a-form-item label="交货条款(delivery term)" v-bind="validateInfos.deliveryTerms" id="SaleOrderForm-deliveryTerms" name="deliveryTerms">
+                <JDictSelectTag v-model:value="formData.deliveryTerms" placeholder="请选择" dictCode="delivery_terms"/>
 							</a-form-item>
 						</a-col>
             <a-col :span="12">
 							<a-form-item label="付款条件(payment terms)" v-bind="validateInfos.paymentTerms" id="SaleOrderForm-paymentTerms" name="paymentTerms" :labelCol="formItemLayout.labelCol1" :wrapperCol="formItemLayout.wrapperCol1">
-                <JDictSelectTag v-model:value="formData.paymentTerms" placeholder="请选择" dictCode="payment_terms" />
+                <JDictSelectTag v-model:value="formData.paymentTerms" placeholder="请选择" dictCode="payment_terms" disabled/>
 							</a-form-item>
 						</a-col>
             
             <a-col :span="12">
 							<a-form-item label="交期(delivery time)" v-bind="validateInfos.deliveryTime" id="SaleOrderForm-deliveryTime" name="deliveryTime">
-								<a-date-picker placeholder="请选择交期(delivery time)"  v-model:value="formData.deliveryTime"  value-format="YYYY-MM-DD" format="YYYY-MM-DD" style="width: 100%"  allow-clear />
+								<a-date-picker placeholder="请选择交期(delivery time)"  v-model:value="formData.deliveryTime"  value-format="YYYY-MM-DD" format="YYYY-MM-DD" @change="changeMainDeliveryTime" style="width: 100%"  allow-clear />
 							</a-form-item>
 						</a-col>
             <a-col :span="12">
 							<a-form-item label="发货方式(delivery)" v-bind="validateInfos.delivery" id="SaleOrderForm-delivery" name="delivery">
-                <JDictSelectTag v-model:value="formData.delivery" placeholder="请选择" dictCode="delivery_methods" />
+                <JDictSelectTag v-model:value="formData.delivery" placeholder="请选择" dictCode="delivery_sale_order" />
 							</a-form-item>
 						</a-col>
             <a-col :span="12">
@@ -87,28 +97,28 @@
 							</a-form-item>
 						</a-col>
             <a-col :span="12">
-							<a-form-item label="是否出口(export)" v-bind="validateInfos.export" id="SaleOrderForm-export" name="export">
-                <JDictSelectTag v-model:value="formData.export" placeholder="请选择" dictCode="yes_or_no" />
+							<a-form-item label="是否出口(export)" v-bind="validateInfos.isExport" id="SaleOrderForm-isExport" name="isExport">
+                <JDictSelectTag v-model:value="formData.isExport" placeholder="请选择" dictCode="yes_or_no" />
 							</a-form-item>
 						</a-col>     
             <a-col :span="12">
-							<a-form-item label="包装要求(package requirement)" v-bind="validateInfos.packageRequirement" id="SaleOrderForm-packageRequirement" name="packageRequirement">
-								<a-input v-model:value="formData.packageRequirement" placeholder="请输入包装要求(package requirement)"  allow-clear ></a-input>
+							<a-form-item label="包装要求(package requirement)" v-bind="validateInfos.packagebRequirement" id="SaleOrderForm-packagebRequirement" name="packagebRequirement">
+								<a-input v-model:value="formData.packagebRequirement" placeholder="请输入包装要求(package requirement)"  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="请输入包装要求(package requirement)"  allow-clear ></a-input>
+								<a-input v-model:value="formData.saleDepartment" placeholder="请输入"  allow-clear disabled></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="请输入业务员(salesman)"  allow-clear ></a-input>
+								<a-input v-model:value="formData.salesman" placeholder="请输入业务员(salesman)"  allow-clear disabled ></a-input>
 							</a-form-item>
 						</a-col> 
             <a-col :span="12">
-							<a-form-item label="客户订单号(custormer order number)" v-bind="validateInfos.custormerOrderNumber" id="SaleOrderForm-custormerOrderNumber" name="custormerOrderNumber">
-								<a-input v-model:value="formData.custormerOrderNumber" placeholder="请输入客户订单号(custormer order number)"  allow-clear ></a-input>
+							<a-form-item label="客户订单号(custormer order number)" v-bind="validateInfos.customerOrder" id="SaleOrderForm-customerOrder" name="customerOrder">
+								<a-input v-model:value="formData.customerOrder" placeholder="请输入客户订单号(custormer order number)"  allow-clear ></a-input>
 							</a-form-item>
 						</a-col> 
             <a-col :span="12">
@@ -117,8 +127,8 @@
 							</a-form-item>
 						</a-col>     
             <a-col :span="12">
-							<a-form-item label="折后金额(converted amount)" v-bind="validateInfos.doubleDiscconvertedAmountount" id="SaleOrderForm-convertedAmount" name="convertedAmount">
-								<a-input v-model:value="formData.convertedAmount" placeholder="请输入折后金额(converted amount)"  allow-clear ></a-input>
+							<a-form-item label="折后金额(converted amount)" v-bind="validateInfos.convertedAmount" id="SaleOrderForm-convertedAmount" name="convertedAmount">
+								<a-input v-model:value="formData.convertedAmount" placeholder="请输入折后金额(converted amount)"  allow-clear disabled></a-input>
 							</a-form-item>
 						</a-col>     
             <a-col :span="12">
@@ -153,7 +163,7 @@
         <j-vxe-table
           :keep-source="true"
           resizable
-          ref="SaleOrderFormShipFormTableRef"
+          ref="SaleOrderFormShipFormShipTableRef"
           :loading="SaleOrderFormShipFormShipTable.loading"
           :columns="SaleOrderFormShipFormShipTable.columns"
           :dataSource="SaleOrderFormShipFormShipTable.dataSource"
@@ -163,14 +173,14 @@
           :rowSelection="true"
           >
             <template #action="props" >
-              <a  >查看配件信息(view accessory information)</a>
+              <a  @click="viewAccessory(props)">查看配件信息(view accessory information)</a>
             </template>
           </j-vxe-table>
       </a-tab-pane>
       <a-tab-pane tab="销售订单 - 产品明细(product details)" key="SaleOrderFormShipFormProduct" :forceRender="true">
-        <a-button type="primary" style="margin-right: 1%;margin-bottom: 1%;"> 选择产品(select product)</a-button>
-        <a-button type="primary"  style="margin-right: 1%;margin-bottom: 1%;"> 选择合同(select contract)</a-button>
-        <a-button type="primary"  style="margin-right: 1%;margin-bottom: 1%;"> 选择报价单(select quotation)</a-button>
+        <a-button type="primary" style="margin-right: 1%;margin-bottom: 1%;" @click="selectProductList"> 选择产品(select product)</a-button>
+        <a-button type="primary"  style="margin-right: 1%;margin-bottom: 1%;" @click ="selectContractList"> 选择合同(select contract)</a-button>
+        <a-button type="primary"  style="margin-right: 1%;margin-bottom: 1%;" @click ="selectQuotationList"> 选择报价单(select quotation)</a-button>
         <j-vxe-table
           :keep-source="true"
           resizable
@@ -184,18 +194,19 @@
           :rowSelection="true"
           asyncRemove
           >
-          <template #action="props">
-                <a-popconfirm title="确定删除吗?">
-                  <a>删除(delete)</a>
-                </a-popconfirm>
+            <template #action="props">
+              <a-popconfirm title="确定删除吗?" @confirm="handleDelete(props)">
+                <a>删除(delete)</a>
+              </a-popconfirm>
             </template>
           </j-vxe-table>
       </a-tab-pane>
     </a-tabs>
-    <!-- <BaseShipArchiveAccessoriesList ref="BaseShipArchiveAccessoriesListRef"></BaseShipArchiveAccessoriesList>
-    <SelectPrpductModal ref="SelectPrpductModalRef" @selectProduct="addProduct"></SelectPrpductModal>
+    <SelectPrpductModal ref="SelectPrpductModalRef" @selectProduct ='addProduct'></SelectPrpductModal>
+    <SelectContractModal ref="SelectContractModalRef" @selectContract="addContract"></SelectContractModal>
+    <SelectQuotationModal ref="SelectQuotationModalRef" @selectQuotation="addQuotation"></SelectQuotationModal>
     <SelectProjectModal ref="SelectProjectModalRef" @selectProject="addProject"></SelectProjectModal>
-    <SelectSupplierInquiryModal ref="SelectSupplierInquiryModalRef" @selectCustomerInquiry="addProductFromCustomer"></SelectSupplierInquiryModal> -->
+    <BaseShipArchiveAccessoriesModal ref="BaseShipArchiveAccessoriesModalRef"></BaseShipArchiveAccessoriesModal>
   </a-spin>
 </template>
 
@@ -203,13 +214,14 @@
   import { defineComponent, ref, reactive, computed, toRaw} from 'vue';
   import { defHttp } from '/@/utils/http/axios';
   import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
-  import { querySaleOrderFormShipFormShippTable, querySaleOrderFormProductListByMainId, queryDataById, saveOrUpdate } from '../SaleOrderyForm.api';
+  import { querySaleOrderFormShipFormShippTable, querySaleOrderFormProductListByMainId, queryDataById, saveOrUpdate,queryVersonHistoryById,querysaleVersonFormShipListByMainId, querySaleVersonProductListByMainId} from '../SaleOrderyForm.api';
   import { JVxeTable } from '/@/components/jeecg/JVxeTable';
   import {saleOrderShipColumns, saleOrderProductColumns} from '../SaleOrderForm.data';
-  // import BaseShipArchiveAccessoriesList from './BaseShipArchiveAccessoriesModal.vue';
-  // import SelectPrpductModal from './SelectPrpductModal.vue';
-  // import SelectProjectModal from './SelectProjectModal.vue';
-  // import SelectSupplierInquiryModal from './SelectSupplierInquiryModal.vue';
+  import SelectPrpductModal from '../../../publicComponents/SelectPrpductModal.vue';
+  import SelectContractModal from '../../../publicComponents/SelectContractModal.vue';
+  import SelectQuotationModal from '../../../publicComponents/SelectQuotationModal.vue';
+  import SelectProjectModal from '../../../publicComponents/SelectProjectModal.vue';
+  import BaseShipArchiveAccessoriesModal from '../../../publicComponents/BaseShipArchiveAccessoriesModal.vue';
   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';
@@ -222,13 +234,14 @@
     components:{
       JVxeTable,
 			JFormContainer,
-      // BaseShipArchiveAccessoriesList,
-      // SelectPrpductModal,
+      SelectPrpductModal,
+      SelectContractModal,
       JUpload,
-      // SelectProjectModal,
       JDictSelectTag,
       JSelectInput,
-      // SelectSupplierInquiryModal
+      SelectQuotationModal,
+      SelectProjectModal,
+      BaseShipArchiveAccessoriesModal
     },
     props:{
       formDisabled:{
@@ -243,6 +256,11 @@
       const loading = ref(false);
       const formRef = ref();
       const SaleOrderFormShipFormShipTableRef = ref();
+      const SelectPrpductModalRef = ref()
+      const SelectContractModalRef = ref()
+      const SelectQuotationModalRef = ref()
+      const SelectProjectModalRef = ref()
+      const BaseShipArchiveAccessoriesModalRef = ref();
       const SaleOrderFormShipFormShipTable = reactive<Record<string, any>>({
         loading: false,
         columns: saleOrderShipColumns,
@@ -261,31 +279,39 @@
         delFlag: undefined,
         billCode:'',
         billDate: moment(new Date()).format('YYYY-MM-DD'),   
-        project: '',   
+        project: '', 
+        projectName:'',  
         customer:"",
-        intermediator: '',           
+        customerName:'',
+        intermediator: '',        
+        intermediatorName:'',   
         priority: '',   
         productionClass: '',   
         model: '',   
         maker: '',
-        deliveryTerm:'',
+        deliveryTerms:'',
         paymentTerms:'',
         delivery:'',
         deliveryTime: '',  
         deliveryAddress:'', 
         invoiceHeader:'', 
         warrantyPeriod: '',   
-        export:'',
-        packageRequirement:'',
+        isExport:'',
+        packagebRequirement:'',
         saleDepartment:'',
         salesman:'',
-        custormerOrderNumber:'',
+        customerOrder:'',
         doubleDiscount:'',
         convertedAmount:'',
         warrantyTerms:'',
         advanceRatio:'',
         notes:'',
-        attachs:''
+        attachs:'',
+        sourceCode:'',
+        sourceCode2:'',
+        currency:'',
+        exchangeRate:'',
+        submit:''
       });
 
       //表单验证
@@ -318,6 +344,16 @@
         SaleOrderFormShipFormProductTable.dataSource = [];
         activeKey.value = 'SaleOrderFormShipFormShip'
       }
+      async function copy(data,id){
+        //主表数据
+        await queryMainData(id);
+        formData.id = ''
+        formData.billCode = ''
+        //子表数据
+        const SaleOrderFormShipFormShipDataList = await querySaleOrderFormShipFormShippTable(id);
+        SaleOrderFormShipFormShipTable.dataSource = [...SaleOrderFormShipFormShipDataList];
+        SaleOrderFormShipFormProductTable.dataSource = [...data];
+      }
 
       async function edit(row) {
         //主表数据
@@ -341,10 +377,32 @@
         //赋值
         Object.assign(formData,tmpData);
       }
+      //查看版本详情
+      async function VersionDetail(record){
+         //主表数据
+        await queryVersonHistoryData(record.id);
+         //子表数据
+        const SaleOrderFormShipFormShipDataList = await querysaleVersonFormShipListByMainId(record.id);
+        SaleOrderFormShipFormShipTable.dataSource = [...SaleOrderFormShipFormShipDataList];
+        const SaleOrderFormShipFormProductDataList = await querySaleVersonProductListByMainId(record.id);
+        SaleOrderFormShipFormProductTable.dataSource = [...SaleOrderFormShipFormProductDataList];
+      }
+      async function queryVersonHistoryData(id){
+        const row = await queryVersonHistoryById(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, {
-        'purPurchaseQuotationShip': SaleOrderFormShipFormShipTableRef,
-        'purPurchaseQuotationProduct': SaleOrderFormShipFormProductTableRef,
+        'saleOrderShip': SaleOrderFormShipFormShipTableRef,
+        'saleOrderProduct': SaleOrderFormShipFormProductTableRef,
       });
 
       async function getFormData() {
@@ -369,7 +427,8 @@
         const values = Object.assign({}, dbData, mainData, subData);
         console.log('表单提交数据', values)
         const isUpdate = values.id ? true : false
-        await saveOrUpdate(values, isUpdate);
+        const isRevise = values.submit=='1' ? true : false
+        await saveOrUpdate(values, isUpdate,isRevise);
         //关闭弹窗
         emit('success');
       }
@@ -381,7 +440,111 @@
           });
         }
       }
-
+      function selectProductList(){
+        SelectPrpductModalRef.value.getTable()
+      }
+      function selectContractList(){
+        SelectContractModalRef.value.getTable(formData)
+      }
+      function selectQuotationList(){
+        SelectQuotationModalRef.value.getTable(formData)
+      }
+      function onSearchProject(){
+        SelectProjectModalRef.value.getTable()
+      }
+      function addProduct(data){
+        var arrProduct = data.concat(SaleOrderFormShipFormProductTable.dataSource)
+        arrProduct.map(item=>{
+          item.productClass = item.classId_dictText
+          item.productCode = item.code
+          item.deliveryTime = formData.deliveryTime
+        })
+        SaleOrderFormShipFormProductTable.dataSource=arrProduct  
+      }
+      function addQuotation(data){
+        var arrProduct = data.concat(SaleOrderFormShipFormProductTable.dataSource)
+        arrProduct.map(item=>{
+          item.model = item.childModel
+          item.deliveryTime = formData.deliveryTime
+          item.sourceId = item.childId
+        })
+        SaleOrderFormShipFormProductTable.dataSource=arrProduct  
+        formData.sourceCode =data[0].billCode
+        if(!formData.sourceCode2&&formData.sourceCode2==''){
+          formData.project = data[0].quotationProject
+          formData.projectName = data[0].quotationProjectName
+          formData.customer =data[0].quotationCustomer
+          formData.customerName =data[0].quotationCustomerName
+          formData.priority =data[0].priority
+          formData.productionClass =data[0].productionClass
+          formData.model =data[0].headModel
+          formData.maker =data[0].maker
+          formData.currency =data[0].currency
+          formData.paymentTerms =data[0].paymentTerms
+          formData.intermediator =data[0].intermediator
+          formData.intermediatorName =data[0].intermediatorName
+          getShipList(data[0].headId)
+        }
+      }
+      function addContract(data){
+          var arrProduct = data.concat(SaleOrderFormShipFormProductTable.dataSource)
+          arrProduct.map(item=>{
+            item.model = item.childModel
+            item.deliveryTime = formData.deliveryTime
+            item.sourceId = item.childId
+          })
+          SaleOrderFormShipFormProductTable.dataSource=arrProduct  
+          formData.sourceCode2 =data[0].billCode
+          if(!formData.sourceCode&&formData.sourceCode==''){
+            formData.project = data[0].quotationProject
+            formData.projectName = data[0].quotationProjectName
+            formData.customer =data[0].quotationCustomer
+            formData.customerName =data[0].quotationCustomerName
+            formData.priority =data[0].priority
+            formData.productionClass =data[0].productionClass
+            formData.model =data[0].headModel
+            formData.maker =data[0].maker
+            formData.currency =data[0].currency
+            formData.paymentTerms =data[0].paymentTerms
+            formData.intermediator =data[0].intermediator
+            formData.intermediatorName =data[0].intermediatorName
+            getShipList(data[0].headId)
+          }
+          
+      }
+      function getShipList(id){
+        let params = {id:id}
+          defHttp.get({url:'/saleCode/saleQuotation/querySaleQuotationShipByMainId',params}, { isTransformResponse: false }).then(res=>{
+            if(res){
+              SaleOrderFormShipFormShipTable.dataSource = res.result
+            }
+          })
+      }
+      function addProject(data){
+        formData.project = data[0].id
+        formData.projectName = data[0].name
+        formData.customer =data[0].customerId
+        formData.customerName =data[0].customerId_dictText
+      }
+      function changeMainDeliveryTime(prop){
+        if(SaleOrderFormShipFormProductTable.dataSource.length>0){
+            var newArr = [...SaleOrderFormShipFormProductTable.dataSource]
+            newArr.map(item=>{
+              item.deliveryTime = prop
+            })
+            SaleOrderFormShipFormProductTable.dataSource = newArr
+         }
+      }
+       //查看配件信息
+       function viewAccessory(prop){
+        BaseShipArchiveAccessoriesModalRef.value.getTable(prop.row)
+      }
+      //产品明细-删除行
+      function handleDelete(prop) {
+        var newArray = [...SaleOrderFormShipFormProductTable.dataSource]
+        newArray.splice(prop.rowIndex, 1)
+        SaleOrderFormShipFormProductTable.dataSource = newArray  
+      }
       /**
        * 值改变事件触发-树控件回调
        * @param key
@@ -408,7 +571,25 @@
         submitForm,
         add,
         edit,
+        copy,
         formRef,
+        selectProductList,
+        SelectPrpductModalRef,
+        addProduct,
+        SelectContractModalRef,
+        selectContractList,
+        addContract,
+        SelectQuotationModalRef,
+        selectQuotationList,
+        addQuotation,
+        onSearchProject,
+        SelectProjectModalRef,
+        addProject,
+        changeMainDeliveryTime,
+        handleDelete,
+        BaseShipArchiveAccessoriesModalRef,
+        viewAccessory,
+        VersionDetail
       }
     }
   });

+ 128 - 0
src/views/saleCode/salesOrder/components/ViewFileListModal.vue

@@ -0,0 +1,128 @@
+<template>
+    <div ref="viewFileDetailRef">
+        <a-modal
+            :title="title"
+            width="60%"
+            :visible="visible"
+            :maskClosable="false"
+            :getContainer ='()=>$refs.viewFileDetailRef'
+            switchFullscreen
+            :footer="false"
+            @cancel="handleCancel">
+                <div>
+                    <a-button type="primary"  @click="handleAdd" preIcon="ant-design:plus-outlined" style="margin-bottom: 1%;"> 新增(add)</a-button>
+                    <a-table
+                        :columns="columns"
+                        :row-key="record => record.id"
+                        :data-source="dataSource"
+                        bordered
+                        size="small"
+                        height="500"
+                        :pagination="false"
+                        :scroll="{ x: 1000, y: 500 }"
+                    > 
+                        <template #operation="{ text, record,index }">
+                            <a @click="handleEdit(record)">编辑(edit)</a>
+                            <a-divider type="vertical"/>
+                            <a-popconfirm title="确定删除吗?" @confirm="handleDelete(record)">
+                            <a>删除(delete)</a>
+                            </a-popconfirm>
+                        </template>
+                    </a-table>
+                </div>
+        </a-modal>
+        <FileUploadModal ref="FileUploadModalRef" @addList="loadData"></FileUploadModal>
+    </div>
+  </template>
+  
+  <script lang="ts" setup>
+      import {ref} from 'vue';
+      import {defHttp} from '/@/utils/http/axios';
+      import FileUploadModal from './FileUploadModal.vue';
+    import { message} from 'ant-design-vue';
+      var visible = ref(false);
+      var title = ref('')
+      var fatherId = ref('')
+      var fatherTitle = ref('')
+      var FileUploadModalRef = ref()
+      var params=ref({
+        headId:'',
+        type:'',
+        pageSize:'-1',
+      })
+      var columns = ref([
+            {
+            title: '上传时间(upload time)',
+            align:"center",
+            dataIndex: 'createTime',
+            key: 'createTime'
+          },
+          {
+            title: '名称(name)',
+            align:"center",
+            dataIndex: 'name',
+            key: 'name'
+          },
+          {
+            title: '操作(operation)',
+            align:"center",
+            dataIndex: 'operation',
+            key: 'operation',
+            slots: { customRender: 'operation' },
+          },
+      ])
+      var dataSource=ref([])
+      function loadData(){
+        defHttp.get({url:"/saleCode/saleOrderFiles/list",params:params.value}).then(res=>{
+          if(res){
+            dataSource.value = res.records
+          }
+        })
+      }
+      function getTable(dataIndex,record){
+          visible.value = true
+          title.value = dataIndex=='scanProtocaol'?'扫描合同查看(view scan contract)':'基础协议查看(view basic agreement)'
+          fatherId.value = record.id
+          fatherTitle.value = dataIndex
+          params.value.headId=record.id
+          params.value.type = dataIndex=='scanProtocaol'?'1':'2'
+          loadData()
+      }
+      function handleCancel(){
+        visible.value = false;
+      }
+      function handleAdd(){
+        FileUploadModalRef.value.getTable(fatherId,fatherTitle,'add')
+      }
+      function handleEdit(record){
+        FileUploadModalRef.value.getTable(fatherId,fatherTitle,'edit',record.id)
+      }
+      function handleDelete(record){
+        let params = {id:record.id}
+        defHttp.delete({ url: '/saleCode/saleOrderFiles/delete', params},{joinParamsToUrl: true,isTransformResponse: false}).then((res) => {
+          if (res) {
+            loadData()
+          } else {
+            message.warning(res.message);
+          }
+        })
+     }
+      defineExpose({
+        getTable
+      });
+    </script>
+  
+  <style lang="less" scoped>
+      /** 时间和数字输入框样式 */
+    :deep(.ant-input-number) {
+      width: 100%;
+    }
+  
+    :deep(.ant-calendar-picker) {
+      width: 100%;
+    }
+    /deep/.ant-modal-body{
+      padding: 14px !important;
+    }
+  </style>
+  

+ 163 - 0
src/views/saleCode/salesOrder/components/ViewHistoryVersionModal.vue

@@ -0,0 +1,163 @@
+<template>
+  <a-modal
+    title="历史版本查看(view historical version)"
+    width="55%"
+    :visible="visible"
+    :maskClosable="false"
+    switchFullscreen
+    @cancel="handleCancel">
+      <template #footer>
+        <a-button  @click="handleCancel" >关闭(close)</a-button>
+      </template>
+      <div>
+        <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.id"
+                :data-source="dataSource"
+                bordered
+                size="small"
+                @change="handleTableChange"
+                :pagination="pagination"
+                :scroll="{ x: 1000, y: 300 }"
+                :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
+            >
+                <template #bodyCell="{ column, record }">
+                    <template v-if="column.key === 'operation'">
+                        <span>
+                            <a @click="viewDetail(record)">查看(view)</a>
+                        </span>
+                    </template>
+                </template>
+            </a-table>
+        </a-card>
+      </div>
+      <SaleOrderFormModal  ref="SaleOrderFormModalRef"></SaleOrderFormModal>
+  </a-modal>
+</template>
+<script lang="ts" setup>
+  import {ref } from 'vue';
+  import { defHttp } from '/@/utils/http/axios';
+  import { message } from 'ant-design-vue';
+  import { filterObj } from '/@/utils/common/compUtils';
+  import SaleOrderFormModal from './SaleOrderFormModal.vue';
+  const emit = defineEmits([ 'selectProduct']); //定义emit
+  var visible = ref(false)
+  var SaleOrderFormModalRef = ref()
+  const columns = [
+      {
+          title: '版本号(version)',
+          dataIndex: 'version',
+          key: 'version',
+          align:"center"
+      },
+      {
+          title: '创建时间(create time)',
+          dataIndex: 'createTime',
+          key: 'createTime',
+          align:"center"
+      },
+      {
+          title: '创建人(create by)',
+          dataIndex: 'createBy',
+          key: 'price',
+          align:"createBy",
+          width:200
+      },
+      {
+            title: '操作(operation)',
+            key: 'operation',
+            dataIndex: 'operation',
+            align:"center",
+            fixed: 'right',
+      },
+  ];
+  const dataSource =ref([]);
+  let selectedRowKeys = ref([]);
+  let selectedRows = ref([]);
+  var Father = ref({})
+  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/saleOrderHis/list',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 = {}
+        params.pageNo = pagination.value.current;
+        params.hisId = Father.value.id;
+        params.pageSize = pagination.value.pageSize;
+        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 onSelectChange(keys,rows){
+      selectedRowKeys.value = keys
+      selectedRows.value = rows
+  }
+  function handleCancel(){
+    visible.value = false
+    selectedRowKeys.value = []
+    selectedRows.value=[]
+  }
+  function getTable(record){
+      visible.value = true
+      Father.value = record
+      loadData()
+  }
+  function viewDetail(record){
+    SaleOrderFormModalRef.value.getVersionDetail(record)
+  }
+  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>