Browse Source

代码合并,冲突处理

廖泽勇 18 hours ago
parent
commit
47dacaf0f9

+ 9 - 0
jshERP-web/src/api/api.js

@@ -59,6 +59,9 @@ const getMaterialBySelect = (params) => getAction('/material/findBySelect', para
 const getSerialMaterialBySelect = (params) => getAction('/material/getMaterialEnableSerialNumberList', params)
 const getMaterialByParam = (params) => getAction('/material/getMaterialByParam', params)
 const getMaterialByBarCode = (params) => getAction('/material/getMaterialByBarCode', params)
+const getMaterialByBatchNumber = (params) => getAction('/material/getMaterialByBatchNumber', params)
+const getMaterialById = (params) => getAction('/material/getMaterialById', params)
+
 const getMaxBarCode = (params) => getAction('/material/getMaxBarCode', params)
 const checkMaterialBarCode = (params) => getAction('/materialsExtend/checkIsBarCodeExist', params)
 const batchUpdateMaterial = (params) => postAction('/material/batchUpdate', params)
@@ -96,6 +99,9 @@ const updateBtnStrByRoleId = (params) => postAction('/userBusiness/updateBtnStr'
 const addUnit = (params) => postAction('/unit/add', params)
 const editUnit = (params) => putAction('/unit/update', params)
 const checkUnit = (params) => getAction('/unit/checkIsNameExist', params)
+// 根据id获取信息
+const getUnitInfo = (params) => getAction('/unit/info', params)
+
 //供应商|客户|会员
 const addSupplier = (params) => postAction('/supplier/add', params)
 const editSupplier = (params) => putAction('/supplier/update', params)
@@ -160,6 +166,7 @@ export {
   getSerialMaterialBySelect,
   getMaterialByParam,
   getMaterialByBarCode,
+  getMaterialByBatchNumber,
   getMaxBarCode,
   checkMaterialBarCode,
   batchUpdateMaterial,
@@ -203,4 +210,6 @@ export {
   findStockByDepotAndBarCode,
   getBatchNumberList,
   findFinancialDetailByNumber,
+  getMaterialById,
+  getUnitInfo,
 }

+ 81 - 60
jshERP-web/src/components/jeecg/JEditableTable.vue

@@ -252,6 +252,7 @@
                             @change="(v) => handleChangeSelectCommon(v, id, row, col)"
                             @search="(v) => handleSearchSelect(v, id, row, col)"
                             @blur="(v) => handleBlurSearch(v, id, row, col)"
+                            @focus="(v) => handleFocusSearch(v, id, row, col)"
                             allowClear
                           >
                             <div slot="dropdownRender" slot-scope="menu">
@@ -348,47 +349,52 @@
                       </a-tooltip>
                     </template>
 
-                    <div v-else-if="col.type === formTypes.upload" :key="i">
-                      <template v-if="uploadValues[id] != null" v-for="(file, fileKey) of [uploadValues[id] || {}]">
-                        <a-input :key="fileKey" :readOnly="true" :value="file.name">
-                          <template slot="addonBefore" style="width: 30px">
-                            <a-tooltip
-                              v-if="file.status === 'uploading'"
-                              :title="`上传中(${Math.floor(file.percent)}%)`"
-                            >
-                              <a-icon type="loading" />
-                            </a-tooltip>
-                            <a-tooltip v-else-if="file.status === 'done'" title="上传完成">
-                              <a-icon type="check-circle" style="color: #00db00" />
-                            </a-tooltip>
-                            <a-tooltip v-else title="上传失败">
-                              <a-icon type="exclamation-circle" style="color: red" />
-                            </a-tooltip>
-                          </template>
-
-                          <template
-                            v-if="col.allowDownload !== false || col.allowRemove !== false"
-                            slot="addonAfter"
-                            style="width: 30px"
-                          >
-                            <a-dropdown
-                              :trigger="['click']"
-                              placement="bottomRight"
-                              :getPopupContainer="getParentContainer"
-                            >
-                              <a-tooltip title="操作" :getPopupContainer="getParentContainer">
-                                <a-icon v-if="file.status !== 'uploading'" type="setting" style="cursor: pointer" />
+                    <div v-else-if="col.type === formTypes.upload" :key="i + 1">
+                      <template v-if="uploadValues[id] != null">
+                        <a-input
+                          v-for="(file, fileKey) of [uploadValues[id] || {}]"
+                          :key="fileKey"
+                          :readOnly="true"
+                          :value="file.name"
+                        >
+                          <template slot="addonBefore">
+                            <div style="width: 30px">
+                              <a-tooltip
+                                v-if="file.status === 'uploading'"
+                                :title="`上传中(${Math.floor(file.percent)}%)`"
+                              >
+                                <a-icon type="loading" />
                               </a-tooltip>
+                              <a-tooltip v-else-if="file.status === 'done'" title="上传完成">
+                                <a-icon type="check-circle" style="color: #00db00" />
+                              </a-tooltip>
+                              <a-tooltip v-else title="上传失败">
+                                <a-icon type="exclamation-circle" style="color: red" />
+                              </a-tooltip>
+                            </div>
+                          </template>
 
-                              <a-menu slot="overlay">
-                                <a-menu-item v-if="col.allowDownload !== false" @click="handleClickDownloadFile(id)">
-                                  <span><a-icon type="download" />&nbsp;下载</span>
-                                </a-menu-item>
-                                <a-menu-item v-if="col.allowRemove !== false" @click="handleClickDelFile(id)">
-                                  <span><a-icon type="delete" />&nbsp;删除</span>
-                                </a-menu-item>
-                              </a-menu>
-                            </a-dropdown>
+                          <template v-if="col.allowDownload !== false || col.allowRemove !== false" slot="addonAfter">
+                            <div style="width: 30px">
+                              <a-dropdown
+                                :trigger="['click']"
+                                placement="bottomRight"
+                                :getPopupContainer="getParentContainer"
+                              >
+                                <a-tooltip title="操作" :getPopupContainer="getParentContainer">
+                                  <a-icon v-if="file.status !== 'uploading'" type="setting" style="cursor: pointer" />
+                                </a-tooltip>
+
+                                <a-menu slot="overlay">
+                                  <a-menu-item v-if="col.allowDownload !== false" @click="handleClickDownloadFile(id)">
+                                    <span><a-icon type="download" />&nbsp;下载</span>
+                                  </a-menu-item>
+                                  <a-menu-item v-if="col.allowRemove !== false" @click="handleClickDelFile(id)">
+                                    <span><a-icon type="delete" />&nbsp;删除</span>
+                                  </a-menu-item>
+                                </a-menu>
+                              </a-dropdown>
+                            </div>
                           </template>
                         </a-input>
                       </template>
@@ -510,9 +516,13 @@
                     <!-- update-end-author:jsh date:20210308 for:popupJsh -->
 
                     <!-- update-beign-author:taoyan date:0827 for:文件/图片逻辑新增 -->
-                    <div v-else-if="col.type === formTypes.file" :key="i">
-                      <template v-if="uploadValues[id] != null" v-for="(file, fileKey) of [uploadValues[id] || {}]">
-                        <div :key="fileKey" style="position: relative">
+                    <div v-else-if="col.type === formTypes.file" :key="i + 2">
+                      <template v-if="uploadValues[id] != null">
+                        <div
+                          v-for="(file, fileKey) of [uploadValues[id] || {}]"
+                          :key="fileKey"
+                          style="position: relative"
+                        >
                           <a-tooltip v-if="file.status === 'uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
                             <a-icon type="loading" style="color: red" />
                             <span style="color: red; margin-left: 5px">{{ file.status }}</span>
@@ -594,9 +604,13 @@
                       </div>
                     </div>
 
-                    <div v-else-if="col.type === formTypes.image" :key="i">
-                      <template v-if="uploadValues[id] != null" v-for="(file, fileKey) of [uploadValues[id] || {}]">
-                        <div :key="fileKey" style="position: relative">
+                    <div v-else-if="col.type === formTypes.image" :key="i + 3">
+                      <template v-if="uploadValues[id] != null">
+                        <div
+                          v-for="(file, fileKey) of [uploadValues[id] || {}]"
+                          :key="fileKey"
+                          style="position: relative"
+                        >
                           <template
                             v-if="
                               !uploadValues[id] ||
@@ -620,19 +634,21 @@
                               @click="handleClickShowImageError(id)"
                             />
                           </template>
-                          <template slot="addonBefore" style="width: 30px">
-                            <a-tooltip
-                              v-if="file.status === 'uploading'"
-                              :title="`上传中(${Math.floor(file.percent)}%)`"
-                            >
-                              <a-icon type="loading" />
-                            </a-tooltip>
-                            <a-tooltip v-else-if="file.status === 'done'" title="上传完成">
-                              <a-icon type="check-circle" style="color: #00db00" />
-                            </a-tooltip>
-                            <a-tooltip v-else title="上传失败">
-                              <a-icon type="exclamation-circle" style="color: red" />
-                            </a-tooltip>
+                          <template slot="addonBefore">
+                            <div style="width: 30px">
+                              <a-tooltip
+                                v-if="file.status === 'uploading'"
+                                :title="`上传中(${Math.floor(file.percent)}%)`"
+                              >
+                                <a-icon type="loading" />
+                              </a-tooltip>
+                              <a-tooltip v-else-if="file.status === 'done'" title="上传完成">
+                                <a-icon type="check-circle" style="color: #00db00" />
+                              </a-tooltip>
+                              <a-tooltip v-else title="上传失败">
+                                <a-icon type="exclamation-circle" style="color: red" />
+                              </a-tooltip>
+                            </div>
                           </template>
 
                           <template style="width: 30px">
@@ -828,7 +844,7 @@
                     </template>
                     <!-- select搜索 -end -->
 
-                    <div v-else-if="col.type === formTypes.slot" :key="i">
+                    <div v-else-if="col.type === formTypes.slot" :key="i + 4">
                       <a-tooltip
                         :key="i"
                         :id="id"
@@ -871,7 +887,7 @@
                     <!-- else (normal) -->
                     <span
                       v-else
-                      :key="i"
+                      :key="i + 5"
                       v-bind="buildProps(row, col)"
                       class="td-span"
                       :title="inputValues[rowIndex][col.key]"
@@ -2328,6 +2344,11 @@ export default {
         }
       }
     },
+    //获取焦点
+    handleFocusSearch(value, id, row, col) {
+      this.validateOneInput(value, row, col, this.notPassedIds, true, 'focus')
+      this.elemValueChange('unit', row, col, value)
+    },
     // blur 失去焦点
     handleBlurSearch(value, id, row, col) {
       if (col.allowInput === true) {

+ 42 - 7
jshERP-web/src/components/jeecg/JImageUpload.vue

@@ -82,14 +82,27 @@ export default {
       required: false,
       default: false,
     },
+    returnUrl: {
+      type: Boolean,
+      required: false,
+      default: true,
+    },
   },
   watch: {
-    value(val) {
-      if (val instanceof Array) {
-        this.initFileList(val.join(','))
-      } else {
-        this.initFileList(val)
-      }
+    value: {
+      immediate: true,
+      handler() {
+        let val = this.value
+        if (val instanceof Array) {
+          if (this.returnUrl) {
+            this.initFileList(val.join(','))
+          } else {
+            this.initFileListArr(val)
+          }
+        } else {
+          this.initFileList(val)
+        }
+      },
     },
   },
   created() {
@@ -105,6 +118,27 @@ export default {
         }
       })
     },
+    initFileListArr(val) {
+      if (!val || val.length == 0) {
+        this.fileList = []
+        return
+      }
+      let fileList = []
+      for (var a = 0; a < val.length; a++) {
+        let url = getFileAccessHttpUrl(val[a].filePath)
+        fileList.push({
+          uid: uidGenerator(),
+          name: val[a].fileName,
+          status: 'done',
+          url: url,
+          response: {
+            code: 'history',
+            data: val[a].filePath,
+          },
+        })
+      }
+      this.fileList = fileList
+    },
     initFileList(paths) {
       if (!paths || paths.length == 0) {
         this.fileList = []
@@ -115,7 +149,7 @@ export default {
       let fileList = []
       let arr = paths.split(',')
       for (var a = 0; a < arr.length; a++) {
-        let url = getFileAccessHttpUrl('systemConfig/static/' + arr[a])
+        let url = getFileAccessHttpUrl('' + arr[a])
         fileList.push({
           uid: uidGenerator(),
           name: getFileName(arr[a]),
@@ -128,6 +162,7 @@ export default {
         })
       }
       this.fileList = fileList
+      console.log('------------------21312', this.fileList)
     },
     beforeUpload: function (file) {
       this.uploadGoOn = true

+ 2 - 2
jshERP-web/src/components/jeecgbiz/JSelectList.vue

@@ -2,7 +2,7 @@
   <div>
     <a-input-group v-if="kind === 'material'" compact style="width: 100%; top: 0px">
       <a-select
-        placeholder="输入条码或名称"
+        placeholder="输入批次号或名称"
         :dropdownMatchSelectWidth="false"
         showSearch
         :showArrow="false"
@@ -24,7 +24,7 @@
             此处最多显示20条,如需更多请点击放大镜查询
           </div>
         </div>
-        <a-select-option v-for="item in materialData" :key="item.barCode">
+        <a-select-option v-for="item in materialData" :key="item.batchNumber">
           {{ item.materialStr }}
         </a-select-option>
       </a-select>

+ 31 - 6
jshERP-web/src/components/jeecgbiz/modal/JSelectMaterialModal.vue

@@ -138,6 +138,9 @@
               <a-tag v-if="record.enableSerialNumber == 1" color="orange">序</a-tag>
               <a-tag v-if="record.enableBatchNumber == 1" color="orange">批</a-tag>
             </template>
+            <span slot="action" slot-scope="text, record">
+              <a @click.stop="handleEdit(record)">编辑</a>
+            </span>
           </a-table>
         </div>
       </a-col>
@@ -149,7 +152,7 @@
 <script>
 import { getAction, getFileAccessHttpUrl } from '@/api/manage'
 import { filterObj, getMpListShort } from '@/utils/util'
-import { getMaterialBySelect, queryMaterialCategoryTreeList } from '@/api/api'
+import { getMaterialBySelect, queryMaterialCategoryTreeList, getMaterialById } from '@/api/api'
 import { JeecgListMixin } from '@/mixins/JeecgListMixin'
 import { mixinDevice } from '@/utils/mixin'
 import Vue from 'vue'
@@ -185,18 +188,32 @@ export default {
       },
       categoryTree: [],
       columns: [
-        { dataIndex: 'mBarCode', title: '条码', scopedSlots: { customRender: 'customBarCode' } },
+        {
+          title: '操作',
+          dataIndex: 'action',
+          align: 'center',
+          width: 60,
+          scopedSlots: { customRender: 'action' },
+        },
+        // { dataIndex: 'mBarCode', title: '条码', scopedSlots: { customRender: 'customBarCode' } },
+        { dataIndex: 'batchNumber', title: '批次号' },
         { dataIndex: 'name', title: '名称', scopedSlots: { customRender: 'customName' } },
         { dataIndex: 'categoryName', title: '类别' },
         { dataIndex: 'standard', title: '规格' },
         { dataIndex: 'model', title: '型号' },
         { dataIndex: 'color', title: '颜色' },
         { dataIndex: 'brand', title: '品牌' },
-        { dataIndex: 'mfrs', title: '制造商' },
+        { dataIndex: 'supplierName', title: '供应商' },
         { dataIndex: 'unit', title: '单位' },
         { dataIndex: 'sku', title: '多属性' },
         { dataIndex: 'stock', title: '库存' },
-        { dataIndex: 'expand', title: '扩展信息' },
+        { dataIndex: 'productionDate', title: '生产日期' },
+        { dataIndex: 'expiryNum', title: '保质期' },
+        { dataIndex: 'barCode', title: '商品条码' },
+        { dataIndex: 'depotId', title: '仓库名称' },
+        { dataIndex: 'position', title: '仓库货架' },
+
+        // { dataIndex: 'expand', title: '扩展信息' },
       ],
       scrollTrigger: {},
       dataSource: [],
@@ -267,7 +284,7 @@ export default {
           this.ipagination.total = res.total
           if (res.total === 1) {
             if (
-              this.queryParam.q === this.dataSource[0].mBarCode ||
+              this.queryParam.q === this.dataSource[0].batchNumber ||
               this.queryParam.q === this.dataSource[0].name ||
               this.queryParam.q === this.dataSource[0].mnemonic
             ) {
@@ -347,6 +364,14 @@ export default {
       this.$refs.modalForm.add()
       this.$refs.modalForm.title = '新增商品'
     },
+    handleEdit(record) {
+      getMaterialById({ mid: record.mid }).then((res) => {
+        this.$refs.modalForm.edit(res.data)
+        this.$refs.modalForm.title = '编辑'
+        this.$refs.modalForm.disableSubmit = false
+        this.$refs.modalForm.showOkFlag = true
+      })
+    },
     getImgUrl(imgName, type) {
       if (imgName && imgName.split(',')) {
         type = type ? type + '/' : ''
@@ -382,7 +407,7 @@ export default {
       for (let i = 0, len = dataSource.length; i < len; i++) {
         if (this.selectedRowKeys.includes(dataSource[i].id)) {
           this.selectMaterialRows.push(dataSource[i])
-          materialIds = materialIds + ',' + dataSource[i].mBarCode
+          materialIds = materialIds + ',' + dataSource[i].batchNumber
         }
       }
       this.selectMaterialIds = materialIds.substring(1)

+ 1 - 1
jshERP-web/src/mixins/JeecgListMixin.js

@@ -466,7 +466,7 @@ export const JeecgListMixin = {
           operatorDomLen = operatorDom[0].offsetHeight + 10
         }
         this.scroll.x = document.documentElement.clientWidth - basicWidth - 64
-        this.scroll.y = document.documentElement.clientHeight - searchWrapperDomLen - operatorDomLen - basicLength
+        this.scroll.y = '100%' //document.documentElement.clientHeight - searchWrapperDomLen - operatorDomLen - basicLength
       }
     },
     //拖拽组件

+ 1 - 1
jshERP-web/src/views/bill/PurchaseInList.vue

@@ -1,7 +1,7 @@
 <template>
   <a-row :gutter="24">
     <a-col :md="24">
-      <a-card :style="cardStyle" :bordered="false">
+      <a-card :bordered="false">
         <!-- 查询区域 -->
         <div class="table-page-search-wrapper">
           <!-- 搜索区域 -->

+ 46 - 25
jshERP-web/src/views/bill/dialog/BillDetail.vue

@@ -95,6 +95,8 @@
                   :loading="loading"
                   :columns="columns"
                   :dataSource="dataSource"
+                  :scroll="scroll"
+                  style="width: 90%"
                 >
                   <template slot="customBarCode" slot-scope="text, record">
                     <div :style="record.imgName ? 'float:left;line-height:30px' : 'float:left;'">
@@ -463,7 +465,7 @@
               </a-form-item>
             </a-col>
           </a-row>
-          <div :style="tableWidth">
+          <div>
             <a-table
               ref="table"
               size="middle"
@@ -473,6 +475,7 @@
               :loading="loading"
               :columns="columns"
               :dataSource="dataSource"
+              :scroll="{ x: 1500, y: 300 }"
             >
               <template slot="customBarCode" slot-scope="text, record">
                 <div :style="record.imgName ? 'float:left;line-height:30px' : 'float:left;'">{{ record.barCode }}</div>
@@ -1214,6 +1217,7 @@
               size="middle"
               bordered
               rowKey="id"
+              :scroll="scroll"
               :pagination="false"
               :loading="loading"
               :columns="columns"
@@ -1469,8 +1473,11 @@ import BillPrintIframe from './BillPrintIframe'
 import FinancialDetail from '../../financial/dialog/FinancialDetail'
 import JUpload from '@/components/jeecg/JUpload'
 import Vue from 'vue'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+
 export default {
   name: 'BillDetail',
+  mixins: [JeecgListMixin],
   components: {
     BillPrintIframe,
     FinancialDetail,
@@ -1602,31 +1609,44 @@ export default {
         { title: '备注', dataIndex: 'remark' },
       ],
       purchaseInColumns: [
-        { title: '仓库名称', dataIndex: 'depotName' },
-        { title: '条码', dataIndex: 'barCode' },
-        { title: '名称', dataIndex: 'name' },
-        { title: '规格', dataIndex: 'standard' },
-        { title: '型号', dataIndex: 'model' },
-        { title: '颜色', dataIndex: 'color' },
-        { title: '品牌', dataIndex: 'brand' },
-        { title: '制造商', dataIndex: 'mfrs' },
-        { title: '扩展信息', dataIndex: 'materialOther' },
-        { title: '库存', dataIndex: 'stock' },
-        { title: '单位', dataIndex: 'unit' },
+        { title: '批次号', dataIndex: 'batchNumber', width: 90 },
+        { title: '名称', dataIndex: 'name', width: 90 },
+        { title: '规格', dataIndex: 'standard', width: 90 },
+
+        { title: '生产日期', dataIndex: 'productionDate', width: 100 },
+        { title: '保质期', dataIndex: 'expiryNum', width: 60 },
+        { title: '商品条码', dataIndex: 'barCode', width: 90 },
+        { title: '仓库名称', dataIndex: 'depotName', width: 90 },
+        { title: '仓库货架', dataIndex: 'position', width: 90 },
+        { title: '包装规格', dataIndex: 'unitName', width: 90 },
+
+        { title: '型号', dataIndex: 'model', width: 60 },
+        { title: '颜色', dataIndex: 'color', width: 60 },
+        { title: '品牌', dataIndex: 'brand', width: 90 },
+        { title: '制造商', dataIndex: 'mfrs', width: 90 },
+        { title: '扩展信息', dataIndex: 'materialOther', width: 90 },
+        { title: '库存', dataIndex: 'stock', width: 90 },
+        { title: '单位', dataIndex: 'unit', width: 90 },
         { title: '序列号', dataIndex: 'snList', width: 300 },
-        { title: '批号', dataIndex: 'batchNumber' },
-        { title: '有效期', dataIndex: 'expirationDate' },
-        { title: '多属性', dataIndex: 'sku' },
-        { title: '数量', dataIndex: 'operNumber' },
-        { title: '已入库', dataIndex: 'finishNumber' },
-        { title: '单价', dataIndex: 'unitPrice' },
-        { title: '金额', dataIndex: 'allPrice' },
-        { title: '税率(%)', dataIndex: 'taxRate' },
-        { title: '税额', dataIndex: 'taxMoney' },
-        { title: '价税合计', dataIndex: 'taxLastMoney' },
-        { title: '重量', dataIndex: 'weight' },
-        { title: '仓位货架', dataIndex: 'position' },
-        { title: '备注', dataIndex: 'remark' },
+        { title: '有效期', dataIndex: 'expirationDate', width: 90 },
+        { title: '多属性', dataIndex: 'sku', width: 90 },
+        { title: '数量', dataIndex: 'operNumber', width: 90 },
+        { title: '已入库', dataIndex: 'finishNumber', width: 90 },
+        { title: '单价', dataIndex: 'unitPrice', width: 90 },
+        { title: '金额', dataIndex: 'allPrice', width: 90 },
+        { title: '税率(%)', dataIndex: 'taxRate', width: 90 },
+        { title: '税额', dataIndex: 'taxMoney', width: 90 },
+        { title: '价税合计', dataIndex: 'taxLastMoney', width: 90 },
+
+        { title: '实际入库数量', dataIndex: 'actualQuantityInStorage', width: 115 },
+        { title: '入库差异', dataIndex: 'warehousingVariance', width: 90 },
+        { title: '入库差异原因', dataIndex: 'reasonOfDifference', width: 115 },
+        { title: '入库人', dataIndex: 'warehousingUser', width: 90 },
+        { title: '入库时间', dataIndex: 'warehousingTime', width: 90 },
+
+        { title: '重量', dataIndex: 'weight', width: 90 },
+        { title: '仓位货架', dataIndex: 'position', width: 90 },
+        { title: '备注', dataIndex: 'remark', width: 90 },
       ],
       purchaseBackColumns: [
         { title: '仓库名称', dataIndex: 'depotName' },
@@ -1930,6 +1950,7 @@ export default {
           title: '#',
           dataIndex: '',
           align: 'center',
+          width: 30,
           customRender: function (t, r, index) {
             return parseInt(index) + 1
           },

+ 1 - 1
jshERP-web/src/views/bill/mixins/BillListMixin.js

@@ -83,7 +83,7 @@ export const BillListMixin = {
       this.$refs.modalForm.disableSubmit = false
       //开启明细的编辑模式
       this.$refs.modalForm.rowCanEdit = true
-      let columnIndex = record.subType === '组装单' || record.subType === '拆卸单' ? 2 : 1
+      let columnIndex = record.subType === '组装单' || record.subType === '拆卸单' ? 2 : 0
       this.$refs.modalForm.materialTable.columns[columnIndex].type = FormTypes.popupJsh
     },
     myHandleEdit(record) {

+ 86 - 66
jshERP-web/src/views/bill/mixins/BillModalMixin.js

@@ -7,9 +7,10 @@ import {
   getAccount,
   getBatchNumberList,
   getCurrentSystemConfig,
-  getMaterialByBarCode,
+  getMaterialByBatchNumber,
   getPersonByNumType,
   getPlatformConfigByKey,
+  getUnitInfo,
 } from '@/api/api'
 import { getAction } from '@/api/manage'
 import { getCheckFlag, getMpListShort, getNowFormatDateTime } from '@/utils/util'
@@ -375,21 +376,21 @@ export const BillModalMixin = {
         .then((allValues) => {
           //获取单据明细列表信息
           let detailArr = allValues.tablesValue[0].values
-          let barCodes = ''
+          let batchNumbers = ''
           for (let detail of detailArr) {
-            barCodes += detail.barCode + ','
+            batchNumbers += detail.batchNumber + ','
           }
-          if (barCodes) {
-            barCodes = barCodes.substring(0, barCodes.length - 1)
+          if (batchNumbers) {
+            batchNumbers = batchNumbers.substring(0, batchNumbers.length - 1)
           }
           let param = {
-            barCode: barCodes,
+            batchNumber: batchNumbers,
             organId: this.form.getFieldValue('organId'),
             depotId: depotId,
             mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
             prefixNo: this.prefixNo,
           }
-          getMaterialByBarCode(param).then((res) => {
+          getMaterialByBatchNumber(param).then((res) => {
             if (res && res.code === 200) {
               let mList = res.data
               //构造新的列表数组,用于存放单据明细信息
@@ -399,7 +400,7 @@ export const BillModalMixin = {
                   let item = detailArr[i]
                   item.depotId = depotId
                   for (let j = 0; j < mList.length; j++) {
-                    if (mList[j].mBarCode === item.barCode) {
+                    if (mList[j].batchNumber === item.batchNumber) {
                       item.stock = mList[j].stock
                     }
                   }
@@ -454,6 +455,7 @@ export const BillModalMixin = {
         })
       }
     },
+
     //单元值改变一个字符就触发一次
     onValueChange(event) {
       let that = this
@@ -466,14 +468,14 @@ export const BillModalMixin = {
             that.getStockByDepotBarCode(row, target)
           }
           break
-        case 'barCode':
+        case 'batchNumber':
           param = {
-            barCode: value,
+            batchNumber: value,
             organId: this.form.getFieldValue('organId'),
             mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
             prefixNo: this.prefixNo,
           }
-          getMaterialByBarCode(param).then((res) => {
+          getMaterialByBatchNumber(param).then((res) => {
             if (res && res.code === 200) {
               let mList = res.data
               if (value.indexOf(',') > -1) {
@@ -501,6 +503,7 @@ export const BillModalMixin = {
                       mArr[j].mType = '普通子件'
                     }
                   }
+
                   this.materialTable.dataSource = mArr
                   if (this.prefixNo === 'LSCK' || this.prefixNo === 'LSTH') {
                     target.statisticsColumns.allPrice = allPriceTotal
@@ -514,7 +517,7 @@ export const BillModalMixin = {
               } else {
                 //单个条码
                 let depotIdSelected = this.prefixNo !== 'CGDD' && this.prefixNo !== 'XSDD' ? row.depotId : ''
-                findStockByDepotAndBarCode({ depotId: depotIdSelected, barCode: row.barCode }).then((res) => {
+                findStockByDepotAndBarCode({ depotId: depotIdSelected, barCode: row.batchNumber }).then((res) => {
                   if (res && res.code === 200) {
                     let mArr = []
                     let mInfo = mList[0]
@@ -559,50 +562,51 @@ export const BillModalMixin = {
             that.autoChangePrice(target)
           }
           break
-        case 'batchNumber':
-          batchNumber = value
-          let depotItemId = ''
-          if (this.model.id) {
-            //只有在保存之后的编辑页面下才获取明细id
-            let rowId = row.id
-            if (rowId.length <= 19) {
-              depotItemId = rowId - 0
-            }
-          }
-          getBatchNumberList({
-            name: '',
-            depotItemId: depotItemId,
-            depotId: row.depotId,
-            barCode: row.barCode,
-            batchNumber: batchNumber,
-          }).then((res) => {
-            if (res && res.code === 200) {
-              if (res.data && res.data.rows) {
-                let info = res.data.rows[0]
-                operNumber = info.totalNum
-                taxRate = row.taxRate - 0 //税率
-                unitPrice = row.unitPrice - 0 //单价
-                allPrice = (unitPrice * operNumber).toFixed(2) - 0
-                taxMoney = (taxRate * 0.01 * allPrice).toFixed(2) - 0
-                taxLastMoney = (allPrice + taxMoney).toFixed(2) - 0
-                target.setValues([
-                  {
-                    rowKey: row.id,
-                    values: {
-                      expirationDate: info.expirationDateStr,
-                      operNumber: operNumber,
-                      allPrice: allPrice,
-                      taxMoney: taxMoney,
-                      taxLastMoney: taxLastMoney,
-                    },
-                  },
-                ])
-                target.recalcAllStatisticsColumns()
-                that.autoChangePrice(target)
-              }
-            }
-          })
-          break
+        // case 'batchNumber':
+        //   console.log('====================adasdas', column)
+        //   batchNumber = value
+        //   let depotItemId = ''
+        //   if (this.model.id) {
+        //     //只有在保存之后的编辑页面下才获取明细id
+        //     let rowId = row.id
+        //     if (rowId.length <= 19) {
+        //       depotItemId = rowId - 0
+        //     }
+        //   }
+        //   getBatchNumberList({
+        //     name: '',
+        //     depotItemId: depotItemId,
+        //     depotId: row.depotId,
+        //     barCode: row.barCode,
+        //     batchNumber: batchNumber,
+        //   }).then((res) => {
+        //     if (res && res.code === 200) {
+        //       if (res.data && res.data.rows) {
+        //         let info = res.data.rows[0]
+        //         operNumber = info.totalNum
+        //         taxRate = row.taxRate - 0 //税率
+        //         unitPrice = row.unitPrice - 0 //单价
+        //         allPrice = (unitPrice * operNumber).toFixed(2) - 0
+        //         taxMoney = (taxRate * 0.01 * allPrice).toFixed(2) - 0
+        //         taxLastMoney = (allPrice + taxMoney).toFixed(2) - 0
+        //         target.setValues([
+        //           {
+        //             rowKey: row.id,
+        //             values: {
+        //               expirationDate: info.expirationDateStr,
+        //               operNumber: operNumber,
+        //               allPrice: allPrice,
+        //               taxMoney: taxMoney,
+        //               taxLastMoney: taxLastMoney,
+        //             },
+        //           },
+        //         ])
+        //         target.recalcAllStatisticsColumns()
+        //         that.autoChangePrice(target)
+        //       }
+        //     }
+        //   })
+        //   break
         case 'operNumber':
           operNumber = value - 0
           taxRate = row.taxRate - 0 //税率
@@ -673,12 +677,18 @@ export const BillModalMixin = {
           target.recalcAllStatisticsColumns()
           that.autoChangePrice(target)
           break
+        case 'unit':
+          if (!row.unitId) return
+          getUnitInfo({ id: row.unitId }).then((res) => {
+            console.log('----------------sdsafds', res)
+          })
       }
     },
     //转为商品对象
     parseInfoToObj(mInfo) {
       return {
         barCode: mInfo.mBarCode,
+        batchNumber: mInfo.batchNumber,
         name: mInfo.name,
         standard: mInfo.standard,
         model: mInfo.model,
@@ -694,6 +704,16 @@ export const BillModalMixin = {
         taxRate: 0,
         taxMoney: 0,
         taxLastMoney: mInfo.billPrice,
+
+        productionDate: mInfo.productionDate,
+        expiryNum: mInfo.expiryNum,
+        position: mInfo.position,
+        unitName: mInfo.unitName,
+        actualQuantityInStorage: mInfo.actualQuantityInStorage,
+        warehousingVariance: mInfo.warehousingVariance,
+        warehousingUser: mInfo.warehousingUser,
+        warehousingTime: mInfo.warehousingTime,
+        unitId: mInfo.unitId,
       }
     },
     //使得型号、颜色、扩展信息、sku等为隐藏
@@ -756,7 +776,7 @@ export const BillModalMixin = {
     },
     //根据仓库和条码查询库存
     getStockByDepotBarCode(row, target) {
-      findStockByDepotAndBarCode({ depotId: row.depotId, barCode: row.barCode }).then((res) => {
+      findStockByDepotAndBarCode({ depotId: row.depotId, barCode: row.batchNumber }).then((res) => {
         if (res && res.code === 200) {
           target.setValues([{ rowKey: row.id, values: { stock: res.data.stock } }])
           target.recalcAllStatisticsColumns()
@@ -879,20 +899,20 @@ export const BillModalMixin = {
         })
         .then((allValues) => {
           let detailArr = allValues.tablesValue[0].values
-          let barCodeStr = ''
+          let batchNumberStr = ''
           for (let detail of detailArr) {
-            if (detail.barCode) {
-              barCodeStr += detail.barCode + ','
+            if (detail.batchNumber) {
+              batchNumberStr += detail.batchNumber + ','
             }
           }
-          if (barCodeStr) {
+          if (batchNumberStr) {
             let param = {
-              barCode: barCodeStr,
+              batchNumber: batchNumberStr,
               organId: organId,
               mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
               prefixNo: this.prefixNo,
             }
-            getMaterialByBarCode(param).then((res) => {
+            getMaterialByBatchNumber(param).then((res) => {
               if (res && res.code === 200) {
                 let allLastMoney = 0
                 let allTaxLastMoney = 0
@@ -901,11 +921,11 @@ export const BillModalMixin = {
                 //构造新的列表数组,用于存放单据明细信息
                 let newDetailArr = []
                 for (let detail of detailArr) {
-                  if (detail.barCode) {
+                  if (detail.batchNumber) {
                     //如果条码重复,就在给原来的数量加1
                     let mList = res.data
                     for (let i = 0; i < mList.length; i++) {
-                      if (detail.barCode === mList[i].mBarCode) {
+                      if (detail.batchNumber === mList[i].batchNumber) {
                         //由于改变了商品单价,需要同时更新相关金额和价税合计
                         let taxRate = detail.taxRate - 0 //税率
                         detail.unitPrice = mList[i].billPrice - 0 //单价
@@ -968,7 +988,7 @@ export const BillModalMixin = {
               mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
               prefixNo: this.prefixNo,
             }
-            getMaterialByBarCode(param).then((res) => {
+            getMaterialByBatchNumber(param).then((res) => {
               if (res && res.code === 200) {
                 let hasFinished = false
                 let allLastMoney = 0

+ 52 - 1
jshERP-web/src/views/bill/modules/AllocationOutModal.vue

@@ -101,6 +101,20 @@
             </a-form-item>
           </a-col>
         </a-row>
+        <a-row class="form-row" :gutter="24">
+          <a-col :lg="6" :md="12" :sm="24">
+            <a-form-item
+              :labelCol="labelCol"
+              :wrapperCol="wrapperCol"
+              label="凭证图片"
+              data-step="11"
+              data-title="附件"
+              data-intro="可以上传与单据相关的图片、文档,支持多个文件"
+            >
+              <j-image-upload v-model="imageList" bizPath="material" text="上传图片" isMultiple></j-image-upload>
+            </a-form-item>
+          </a-col>
+        </a-row>
       </a-form>
     </a-spin>
     <depot-modal ref="depotModalForm" @ok="depotModalFormOk"></depot-modal>
@@ -120,6 +134,8 @@ import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
 import { BillModalMixin } from '../mixins/BillModalMixin'
 import { getMpListShort } from '@/utils/util'
 import JUpload from '@/components/jeecg/JUpload'
+import JImageUpload from '@/components/jeecg/JImageUpload.vue'
+
 import JDate from '@/components/jeecg/JDate'
 import Vue from 'vue'
 export default {
@@ -144,6 +160,8 @@ export default {
       operTimeStr: '',
       prefixNo: 'DBCK',
       fileList: [],
+      imageList: [],
+
       model: {},
       labelCol: {
         xs: { span: 24 },
@@ -180,6 +198,14 @@ export default {
           },
           { title: '名称', key: 'name', width: '10%', type: FormTypes.normal },
           { title: '规格', key: 'standard', width: '9%', type: FormTypes.normal },
+
+          { title: '生产日期', key: 'productionDate', width: '9%', type: FormTypes.normal },
+          { title: '保质期', key: 'expiryNum', width: '6%', type: FormTypes.normal },
+          { title: '商品条码', key: 'barCode', width: '6%', type: FormTypes.normal },
+          { title: '仓库名', key: 'depotName', width: '6%', type: FormTypes.normal },
+          { title: '仓库货架', key: 'position', width: '6%', type: FormTypes.normal },
+          { title: '包装规格', key: 'unitName', width: '6%', type: FormTypes.input },
+
           { title: '型号', key: 'model', width: '9%', type: FormTypes.normal },
           { title: '颜色', key: 'color', width: '5%', type: FormTypes.normal },
           { title: '品牌', key: 'brand', width: '6%', type: FormTypes.normal },
@@ -207,6 +233,23 @@ export default {
           },
           { title: '单价', key: 'unitPrice', width: '5%', type: FormTypes.inputNumber },
           { title: '金额', key: 'allPrice', width: '5%', type: FormTypes.inputNumber, statistics: true },
+          {
+            title: '实际出库数量',
+            key: 'actualQuantityInStorage',
+            width: '9%',
+            type: FormTypes.inputNumber,
+            validateRules: [{ required: true, message: '实际入库数量不能为空' }],
+          },
+          { title: '出库差异', key: 'warehousingVariance', width: '9%', type: FormTypes.input },
+          { title: '出库差异原因', key: 'reasonOfDifference', width: '9%', type: FormTypes.input },
+          {
+            title: '出库人',
+            key: 'warehousingUser',
+            width: '9%',
+            type: FormTypes.input,
+            validateRules: [{ required: true, message: '出库人不能为空' }],
+          },
+          { title: '出库时间', key: 'warehousingTime', width: '9%', type: FormTypes.date },
           { title: '备注', key: 'remark', width: '5%', type: FormTypes.input },
         ],
       },
@@ -234,14 +277,17 @@ export default {
       this.currentSelectDepotId = ''
       this.changeColumnHide()
       this.changeFormTypes(this.materialTable.columns, 'snList', 0)
-      this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
+      // this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'expirationDate', 0)
       if (this.action === 'add') {
         this.addInit(this.prefixNo)
         this.fileList = []
+        this.imageList = []
       } else {
         this.model.operTime = this.model.operTimeStr
         this.fileList = this.model.fileName
+        this.imageList = this.model.voucherPicture
+
         this.$nextTick(() => {
           this.form.setFieldsValue(
             pick(
@@ -295,6 +341,11 @@ export default {
       } else {
         billMain.fileName = ''
       }
+      if (this.imageList && this.imageList.length > 0) {
+        billMain.voucherPicture = this.imageList
+      } else {
+        billMain.voucherPicture = ''
+      }
       if (this.model.id) {
         billMain.id = this.model.id
       }

+ 68 - 16
jshERP-web/src/views/bill/modules/OtherInModal.vue

@@ -146,6 +146,20 @@
             </a-form-item>
           </a-col>
         </a-row>
+        <a-row class="form-row" :gutter="24">
+          <a-col :lg="6" :md="12" :sm="24">
+            <a-form-item
+              :labelCol="labelCol"
+              :wrapperCol="wrapperCol"
+              label="凭证图片"
+              data-step="11"
+              data-title="附件"
+              data-intro="可以上传与单据相关的图片、文档,支持多个文件"
+            >
+              <j-image-upload v-model="imageList" bizPath="material" text="上传图片" isMultiple></j-image-upload>
+            </a-form-item>
+          </a-col>
+        </a-row>
       </a-form>
     </a-spin>
     <vendor-modal ref="vendorModalForm" @ok="vendorModalFormOk"></vendor-modal>
@@ -173,6 +187,8 @@ import JUpload from '@/components/jeecg/JUpload'
 import JDate from '@/components/jeecg/JDate'
 import Vue from 'vue'
 import WaitBillList from '../dialog/WaitBillList'
+import JImageUpload from '@/components/jeecg/JImageUpload.vue'
+
 export default {
   name: 'OtherInModal',
   mixins: [JEditableTableMixin, BillModalMixin],
@@ -185,6 +201,7 @@ export default {
     WorkflowIframe,
     BillPrintIframe,
     JUpload,
+    JImageUpload,
     JDate,
     VNodes: {
       functional: true,
@@ -202,6 +219,7 @@ export default {
       operTimeStr: '',
       prefixNo: 'QTRK',
       fileList: [],
+      imageList: [],
       rowCanEdit: true,
       //出入库管理开关,适合独立仓管场景
       inOutManageFlag: false,
@@ -220,19 +238,21 @@ export default {
         loading: false,
         dataSource: [],
         columns: [
+          // {
+          //   title: '仓库名称',
+          //   key: 'depotId',
+          //   width: '8%',
+          //   type: FormTypes.select,
+          //   placeholder: '请选择${title}',
+          //   options: [],
+          //   allowSearch: true,
+          //   disabled: true,
+          //   validateRules: [{ required: true, message: '${title}不能为空' }],
+          // },
+          // { title: '批次号', key: 'batchNumber', width: '9%', type: FormTypes.normal },
           {
-            title: '仓库名称',
-            key: 'depotId',
-            width: '8%',
-            type: FormTypes.select,
-            placeholder: '请选择${title}',
-            options: [],
-            allowSearch: true,
-            validateRules: [{ required: true, message: '${title}不能为空' }],
-          },
-          {
-            title: '条码',
-            key: 'barCode',
+            title: '批次号',
+            key: 'batchNumber',
             width: '12%',
             type: FormTypes.popupJsh,
             kind: 'material',
@@ -241,15 +261,22 @@ export default {
           },
           { title: '名称', key: 'name', width: '10%', type: FormTypes.normal },
           { title: '规格', key: 'standard', width: '9%', type: FormTypes.normal },
+
+          { title: '生产日期', key: 'productionDate', width: '9%', type: FormTypes.normal },
+          { title: '保质期', key: 'expiryNum', width: '6%', type: FormTypes.normal },
+          { title: '商品条码', key: 'barCode', width: '9%', type: FormTypes.normal },
+          { title: '仓库名', key: 'depotId', width: '9%', type: FormTypes.normal },
+          { title: '仓库货架', key: 'position', width: '9%', type: FormTypes.normal },
+          { title: '包装规格', key: 'unitName', width: '9%', type: FormTypes.input },
+
           { title: '型号', key: 'model', width: '9%', type: FormTypes.normal },
           { title: '颜色', key: 'color', width: '5%', type: FormTypes.normal },
           { title: '品牌', key: 'brand', width: '6%', type: FormTypes.normal },
           { title: '制造商', key: 'mfrs', width: '6%', type: FormTypes.normal },
           { title: '扩展信息', key: 'materialOther', width: '5%', type: FormTypes.normal },
           { title: '库存', key: 'stock', width: '5%', type: FormTypes.normal },
-          { title: '单位', key: 'unit', width: '4%', type: FormTypes.normal },
+          { title: '单位', key: 'unit', width: '4%', type: FormTypes.select },
           { title: '序列号', key: 'snList', width: '12%', type: FormTypes.popupJsh, kind: 'snAdd', multi: true },
-          { title: '批号', key: 'batchNumber', width: '7%', type: FormTypes.input },
           { title: '有效期', key: 'expirationDate', width: '7%', type: FormTypes.date },
           { title: '多属性', key: 'sku', width: '9%', type: FormTypes.normal },
           { title: '原数量', key: 'preNumber', width: '4%', type: FormTypes.normal },
@@ -264,6 +291,23 @@ export default {
           },
           { title: '单价', key: 'unitPrice', width: '5%', type: FormTypes.inputNumber },
           { title: '金额', key: 'allPrice', width: '5%', type: FormTypes.inputNumber, statistics: true },
+          {
+            title: '实际入库数量',
+            key: 'actualQuantityInStorage',
+            width: '9%',
+            type: FormTypes.inputNumber,
+            validateRules: [{ required: true, message: '实际入库数量不能为空' }],
+          },
+          { title: '入库差异', key: 'warehousingVariance', width: '9%', type: FormTypes.input },
+          { title: '入库差异原因', key: 'reasonOfDifference', width: '9%', type: FormTypes.input },
+          {
+            title: '入库人',
+            key: 'warehousingUser',
+            width: '9%',
+            type: FormTypes.input,
+            validateRules: [{ required: true, message: '入库人不能为空' }],
+          },
+          { title: '入库时间', key: 'warehousingTime', width: '9%', type: FormTypes.date },
           { title: '备注', key: 'remark', width: '5%', type: FormTypes.input },
           { title: '关联id', key: 'linkId', width: '5%', type: FormTypes.hidden },
         ],
@@ -291,16 +335,17 @@ export default {
       this.billStatus = '0'
       this.currentSelectDepotId = ''
       this.rowCanEdit = true
-      this.materialTable.columns[1].type = FormTypes.popupJsh
+      this.materialTable.columns[0].type = FormTypes.popupJsh
       this.changeColumnHide()
       this.changeFormTypes(this.materialTable.columns, 'snList', 0)
-      this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
+      // this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'expirationDate', 0)
       this.changeFormTypes(this.materialTable.columns, 'preNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'finishNumber', 0)
       if (this.action === 'add') {
         this.addInit(this.prefixNo)
         this.fileList = []
+        this.imageList = []
       } else {
         if (this.model.linkNumber) {
           this.rowCanEdit = false
@@ -308,6 +353,8 @@ export default {
         }
         this.model.operTime = this.model.operTimeStr
         this.fileList = this.model.fileName
+        this.imageList = this.model.voucherPicture
+
         this.$nextTick(() => {
           this.form.setFieldsValue(
             pick(
@@ -363,6 +410,11 @@ export default {
       } else {
         billMain.fileName = ''
       }
+      if (this.imageList && this.imageList.length > 0) {
+        billMain.voucherPicture = this.imageList
+      } else {
+        billMain.voucherPicture = ''
+      }
       if (this.model.id) {
         billMain.id = this.model.id
       }

+ 65 - 15
jshERP-web/src/views/bill/modules/OtherOutModal.vue

@@ -147,6 +147,20 @@
             </a-form-item>
           </a-col>
         </a-row>
+        <a-row class="form-row" :gutter="24">
+          <a-col :lg="6" :md="12" :sm="24">
+            <a-form-item
+              :labelCol="labelCol"
+              :wrapperCol="wrapperCol"
+              label="凭证图片"
+              data-step="11"
+              data-title="附件"
+              data-intro="可以上传与单据相关的图片、文档,支持多个文件"
+            >
+              <j-image-upload v-model="imageList" bizPath="material" text="上传图片" isMultiple></j-image-upload>
+            </a-form-item>
+          </a-col>
+        </a-row>
       </a-form>
     </a-spin>
     <customer-modal ref="customerModalForm" @ok="customerModalFormOk"></customer-modal>
@@ -174,6 +188,8 @@ import JUpload from '@/components/jeecg/JUpload'
 import JDate from '@/components/jeecg/JDate'
 import Vue from 'vue'
 import WaitBillList from '../dialog/WaitBillList'
+import JImageUpload from '@/components/jeecg/JImageUpload.vue'
+
 export default {
   name: 'OtherOutModal',
   mixins: [JEditableTableMixin, BillModalMixin],
@@ -186,6 +202,7 @@ export default {
     WorkflowIframe,
     BillPrintIframe,
     JUpload,
+    JImageUpload,
     JDate,
     VNodes: {
       functional: true,
@@ -203,6 +220,7 @@ export default {
       operTimeStr: '',
       prefixNo: 'QTCK',
       fileList: [],
+      imageList: [],
       rowCanEdit: true,
       //出入库管理开关,适合独立仓管场景
       inOutManageFlag: false,
@@ -221,19 +239,19 @@ export default {
         loading: false,
         dataSource: [],
         columns: [
+          // {
+          //   title: '仓库名称',
+          //   key: 'depotId',
+          //   width: '8%',
+          //   type: FormTypes.select,
+          //   placeholder: '请选择${title}',
+          //   options: [],
+          //   allowSearch: true,
+          //   validateRules: [{ required: true, message: '${title}不能为空' }],
+          // },
           {
-            title: '仓库名称',
-            key: 'depotId',
-            width: '8%',
-            type: FormTypes.select,
-            placeholder: '请选择${title}',
-            options: [],
-            allowSearch: true,
-            validateRules: [{ required: true, message: '${title}不能为空' }],
-          },
-          {
-            title: '条码',
-            key: 'barCode',
+            title: '批次号',
+            key: 'batchNumber',
             width: '12%',
             type: FormTypes.popupJsh,
             kind: 'material',
@@ -242,6 +260,14 @@ export default {
           },
           { title: '名称', key: 'name', width: '10%', type: FormTypes.normal },
           { title: '规格', key: 'standard', width: '9%', type: FormTypes.normal },
+
+          { title: '生产日期', key: 'productionDate', width: '9%', type: FormTypes.normal },
+          { title: '保质期', key: 'expiryNum', width: '6%', type: FormTypes.normal },
+          { title: '商品条码', key: 'barCode', width: '6%', type: FormTypes.normal },
+          { title: '仓库名', key: 'depotName', width: '6%', type: FormTypes.normal },
+          { title: '仓库货架', key: 'position', width: '6%', type: FormTypes.normal },
+          { title: '包装规格', key: 'unitName', width: '6%', type: FormTypes.input },
+
           { title: '型号', key: 'model', width: '9%', type: FormTypes.normal },
           { title: '颜色', key: 'color', width: '5%', type: FormTypes.normal },
           { title: '品牌', key: 'brand', width: '6%', type: FormTypes.normal },
@@ -256,7 +282,7 @@ export default {
           { title: '原数量', key: 'preNumber', width: '4%', type: FormTypes.normal },
           { title: '已入库', key: 'finishNumber', width: '4%', type: FormTypes.normal },
           {
-            title: '数量',
+            title: '出库数量',
             key: 'operNumber',
             width: '5%',
             type: FormTypes.inputNumber,
@@ -265,6 +291,23 @@ export default {
           },
           { title: '单价', key: 'unitPrice', width: '5%', type: FormTypes.inputNumber },
           { title: '金额', key: 'allPrice', width: '5%', type: FormTypes.inputNumber, statistics: true },
+          {
+            title: '实际出库数量',
+            key: 'actualQuantityInStorage',
+            width: '9%',
+            type: FormTypes.inputNumber,
+            validateRules: [{ required: true, message: '实际入库数量不能为空' }],
+          },
+          { title: '出库差异', key: 'warehousingVariance', width: '9%', type: FormTypes.input },
+          { title: '出库差异原因', key: 'reasonOfDifference', width: '9%', type: FormTypes.input },
+          {
+            title: '出库人',
+            key: 'warehousingUser',
+            width: '9%',
+            type: FormTypes.input,
+            validateRules: [{ required: true, message: '出库人不能为空' }],
+          },
+          { title: '出库时间', key: 'warehousingTime', width: '9%', type: FormTypes.date },
           { title: '备注', key: 'remark', width: '5%', type: FormTypes.input },
           { title: '关联id', key: 'linkId', width: '5%', type: FormTypes.hidden },
         ],
@@ -292,16 +335,17 @@ export default {
       this.billStatus = '0'
       this.currentSelectDepotId = ''
       this.rowCanEdit = true
-      this.materialTable.columns[1].type = FormTypes.popupJsh
+      this.materialTable.columns[0].type = FormTypes.popupJsh
       this.changeColumnHide()
       this.changeFormTypes(this.materialTable.columns, 'snList', 0)
-      this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
+      // this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'expirationDate', 0)
       this.changeFormTypes(this.materialTable.columns, 'preNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'finishNumber', 0)
       if (this.action === 'add') {
         this.addInit(this.prefixNo)
         this.fileList = []
+        this.imageList = []
       } else {
         if (this.model.linkNumber) {
           this.rowCanEdit = false
@@ -309,6 +353,7 @@ export default {
         }
         this.model.operTime = this.model.operTimeStr
         this.fileList = this.model.fileName
+        this.imageList = this.model.voucherPicture
         this.$nextTick(() => {
           this.form.setFieldsValue(
             pick(
@@ -364,6 +409,11 @@ export default {
       } else {
         billMain.fileName = ''
       }
+      if (this.imageList && this.imageList.length > 0) {
+        billMain.voucherPicture = this.imageList
+      } else {
+        billMain.voucherPicture = ''
+      }
       if (this.model.id) {
         billMain.id = this.model.id
       }

+ 79 - 22
jshERP-web/src/views/bill/modules/PurchaseInModal.vue

@@ -114,7 +114,7 @@
         >
           <template #buttonAfter>
             <a-row
-              v-if="rowCanEdit"
+              v-if="false"
               :gutter="24"
               style="float: left; padding-bottom: 5px"
               data-step="4"
@@ -315,6 +315,20 @@
             </a-form-item>
           </a-col>
         </a-row>
+        <a-row class="form-row" :gutter="24">
+          <a-col :lg="6" :md="12" :sm="24">
+            <a-form-item
+              :labelCol="labelCol"
+              :wrapperCol="wrapperCol"
+              label="凭证图片"
+              data-step="11"
+              data-title="附件"
+              data-intro="可以上传与单据相关的图片、文档,支持多个文件"
+            >
+              <j-image-upload v-model="imageList" bizPath="material" text="上传图片" isMultiple></j-image-upload>
+            </a-form-item>
+          </a-col>
+        </a-row>
       </a-form>
     </a-spin>
     <many-account-modal ref="manyAccountModalForm" @ok="manyAccountModalFormOk"></many-account-modal>
@@ -349,6 +363,7 @@ import { getMpListShort, changeListFmtMinus, handleIntroJs } from '@/utils/util'
 import JUpload from '@/components/jeecg/JUpload'
 import JDate from '@/components/jeecg/JDate'
 import Vue from 'vue'
+import JImageUpload from '@/components/jeecg/JImageUpload.vue'
 
 export default {
   name: 'PurchaseInModal',
@@ -370,6 +385,7 @@ export default {
       functional: true,
       render: (h, ctx) => ctx.props.vnodes,
     },
+    JImageUpload,
   },
   data() {
     return {
@@ -383,6 +399,7 @@ export default {
       prefixNo: 'CGRK',
       depositStatus: false,
       fileList: [],
+      imageList: [],
       rowCanEdit: true,
       model: {},
       labelCol: {
@@ -399,44 +416,55 @@ export default {
         loading: false,
         dataSource: [],
         columns: [
+          // {
+          //   title: '仓库名称',
+          //   key: 'depotId',
+          //   width: '8%',
+          //   type: FormTypes.select,
+          //   placeholder: '请选择${title}',
+          //   options: [],
+          //   allowSearch: true,
+          //   disabled: true,
+          //   validateRules: [{ required: true, message: '${title}不能为空' }],
+          // },
           {
-            title: '仓库名称',
-            key: 'depotId',
-            width: '8%',
-            type: FormTypes.select,
-            placeholder: '请选择${title}',
-            options: [],
-            allowSearch: true,
-            validateRules: [{ required: true, message: '${title}不能为空' }],
-          },
-          {
-            title: '条码',
-            key: 'barCode',
+            title: '批次号',
+            key: 'batchNumber',
             width: '12%',
             type: FormTypes.popupJsh,
             kind: 'material',
             multi: true,
+            newBatch: true,
+
             validateRules: [{ required: true, message: '${title}不能为空' }],
           },
-          { title: '名称', key: 'name', width: '10%', type: FormTypes.normal },
-          { title: '规格', key: 'standard', width: '9%', type: FormTypes.normal },
+          { title: '名称', key: 'name', width: '7%', type: FormTypes.normal },
+          { title: '规格', key: 'standard', width: '6%', type: FormTypes.normal },
+
+          { title: '生产日期', key: 'productionDate', width: '9%', type: FormTypes.normal, disabled: true },
+          { title: '保质期', key: 'expiryNum', width: '6%', type: FormTypes.normal },
+          { title: '商品条码', key: 'barCode', width: '6%', type: FormTypes.normal },
+          { title: '仓库名', key: 'depotId', width: '6%', type: FormTypes.select, disabled: true },
+          { title: '仓库货架', key: 'position', width: '6%', type: FormTypes.normal },
+          { title: '包装规格', key: 'unitName', width: '6%', type: FormTypes.input },
+
           { title: '型号', key: 'model', width: '9%', type: FormTypes.normal },
           { title: '颜色', key: 'color', width: '5%', type: FormTypes.normal },
           { title: '品牌', key: 'brand', width: '6%', type: FormTypes.normal },
           { title: '制造商', key: 'mfrs', width: '6%', type: FormTypes.normal },
           { title: '扩展信息', key: 'materialOther', width: '5%', type: FormTypes.normal },
           { title: '库存', key: 'stock', width: '5%', type: FormTypes.normal },
-          { title: '单位', key: 'unit', width: '4%', type: FormTypes.normal },
+          { title: '单位', key: 'unit', width: '4%', type: FormTypes.select, options: [] },
+          { title: '单位id', key: 'unitId', width: '4%', type: FormTypes.hidden },
           { title: '序列号', key: 'snList', width: '12%', type: FormTypes.popupJsh, kind: 'snAdd', multi: true },
-          { title: '批号', key: 'batchNumber', width: '7%', type: FormTypes.input },
           { title: '有效期', key: 'expirationDate', width: '7%', type: FormTypes.date },
           { title: '多属性', key: 'sku', width: '9%', type: FormTypes.normal },
           { title: '原数量', key: 'preNumber', width: '4%', type: FormTypes.normal },
           { title: '已入库', key: 'finishNumber', width: '4%', type: FormTypes.normal },
           {
-            title: '数量',
+            title: '入库数量',
             key: 'operNumber',
-            width: '4%',
+            width: '5%',
             type: FormTypes.inputNumber,
             statistics: true,
             validateRules: [{ required: true, message: '${title}不能为空' }],
@@ -453,6 +481,25 @@ export default {
             statistics: true,
           },
           { title: '价税合计', key: 'taxLastMoney', width: '7%', type: FormTypes.inputNumber, statistics: true },
+
+          {
+            title: '实际入库数量',
+            key: 'actualQuantityInStorage',
+            width: '9%',
+            type: FormTypes.inputNumber,
+            validateRules: [{ required: true, message: '实际入库数量不能为空' }],
+          },
+          { title: '入库差异', key: 'warehousingVariance', width: '9%', type: FormTypes.input },
+          { title: '入库差异原因', key: 'reasonOfDifference', width: '9%', type: FormTypes.input },
+          {
+            title: '入库人',
+            key: 'warehousingUser',
+            width: '9%',
+            type: FormTypes.input,
+            validateRules: [{ required: true, message: '入库人不能为空' }],
+          },
+          { title: '入库时间', key: 'warehousingTime', width: '9%', type: FormTypes.date },
+
           { title: '备注', key: 'remark', width: '6%', type: FormTypes.input },
           { title: '关联id', key: 'linkId', width: '5%', type: FormTypes.hidden },
         ],
@@ -489,10 +536,10 @@ export default {
       this.billStatus = '0'
       this.currentSelectDepotId = ''
       this.rowCanEdit = true
-      this.materialTable.columns[1].type = FormTypes.popupJsh
+      this.materialTable.columns[0].type = FormTypes.popupJsh
       this.changeColumnHide()
       this.changeFormTypes(this.materialTable.columns, 'snList', 0)
-      this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
+      // this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'expirationDate', 0)
       this.changeFormTypes(this.materialTable.columns, 'preNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'finishNumber', 0)
@@ -500,13 +547,14 @@ export default {
         this.depositStatus = false
         this.addInit(this.prefixNo)
         this.fileList = []
+        this.imageList = []
         this.$nextTick(() => {
           handleIntroJs(this.prefixNo, 1)
         })
       } else {
         if (this.model.linkNumber) {
           this.rowCanEdit = false
-          this.materialTable.columns[1].type = FormTypes.normal
+          this.materialTable.columns[0].type = FormTypes.normal
         }
         this.model.operTime = this.model.operTimeStr
         if (this.model.deposit) {
@@ -530,6 +578,8 @@ export default {
           this.manyAccountBtnStatus = false
         }
         this.fileList = this.model.fileName
+        this.imageList = this.model.voucherPicture
+
         this.$nextTick(() => {
           this.form.setFieldsValue(
             pick(
@@ -595,10 +645,16 @@ export default {
       } else {
         billMain.fileName = ''
       }
+      if (this.imageList && this.imageList.length > 0) {
+        billMain.voucherPicture = this.imageList
+      } else {
+        billMain.voucherPicture = ''
+      }
       if (this.model.id) {
         billMain.id = this.model.id
       }
       billMain.status = this.billStatus
+
       return {
         info: JSON.stringify(billMain),
         rows: JSON.stringify(detailArr),
@@ -637,6 +693,7 @@ export default {
           this.changeColumnShow(info)
         }
         this.materialTable.dataSource = listEx
+
         ///给优惠后金额重新赋值
         allTaxLastMoney = allTaxLastMoney ? allTaxLastMoney : 0
         let discount = 0

+ 70 - 17
jshERP-web/src/views/bill/modules/SaleOutModal.vue

@@ -339,6 +339,20 @@
             </a-form-item>
           </a-col>
         </a-row>
+        <a-row class="form-row" :gutter="24">
+          <a-col :lg="6" :md="12" :sm="24">
+            <a-form-item
+              :labelCol="labelCol"
+              :wrapperCol="wrapperCol"
+              label="凭证图片"
+              data-step="11"
+              data-title="附件"
+              data-intro="可以上传与单据相关的图片、文档,支持多个文件"
+            >
+              <j-image-upload v-model="imageList" bizPath="material" text="上传图片" isMultiple></j-image-upload>
+            </a-form-item>
+          </a-col>
+        </a-row>
       </a-form>
     </a-spin>
     <many-account-modal ref="manyAccountModalForm" @ok="manyAccountModalFormOk"></many-account-modal>
@@ -371,6 +385,8 @@ import { BillModalMixin } from '../mixins/BillModalMixin'
 import { getMpListShort, handleIntroJs } from '@/utils/util'
 import JSelectMultiple from '@/components/jeecg/JSelectMultiple'
 import JUpload from '@/components/jeecg/JUpload'
+import JImageUpload from '@/components/jeecg/JImageUpload.vue'
+
 import JDate from '@/components/jeecg/JDate'
 import Vue from 'vue'
 export default {
@@ -390,6 +406,7 @@ export default {
     JUpload,
     JDate,
     JSelectMultiple,
+    JImageUpload,
     VNodes: {
       functional: true,
       render: (h, ctx) => ctx.props.vnodes,
@@ -407,6 +424,7 @@ export default {
       prefixNo: 'XSCK',
       depositStatus: false,
       fileList: [],
+      imageList: [],
       rowCanEdit: true,
       model: {},
       labelCol: {
@@ -423,19 +441,19 @@ export default {
         loading: false,
         dataSource: [],
         columns: [
+          // {
+          //   title: '仓库名称',
+          //   key: 'depotId',
+          //   width: '8%',
+          //   type: FormTypes.select,
+          //   placeholder: '请选择${title}',
+          //   options: [],
+          //   allowSearch: true,
+          //   validateRules: [{ required: true, message: '${title}不能为空' }],
+          // },
           {
-            title: '仓库名称',
-            key: 'depotId',
-            width: '8%',
-            type: FormTypes.select,
-            placeholder: '请选择${title}',
-            options: [],
-            allowSearch: true,
-            validateRules: [{ required: true, message: '${title}不能为空' }],
-          },
-          {
-            title: '条码',
-            key: 'barCode',
+            title: '批次号',
+            key: 'batchNumber',
             width: '12%',
             type: FormTypes.popupJsh,
             kind: 'material',
@@ -444,6 +462,14 @@ export default {
           },
           { title: '名称', key: 'name', width: '10%', type: FormTypes.normal },
           { title: '规格', key: 'standard', width: '9%', type: FormTypes.normal },
+
+          { title: '生产日期', key: 'productionDate', width: '9%', type: FormTypes.normal },
+          { title: '保质期', key: 'expiryNum', width: '6%', type: FormTypes.normal },
+          { title: '商品条码', key: 'barCode', width: '6%', type: FormTypes.normal },
+          { title: '仓库名', key: 'depotName', width: '6%', type: FormTypes.normal },
+          { title: '仓库货架', key: 'position', width: '6%', type: FormTypes.normal },
+          { title: '包装规格', key: 'unitName', width: '6%', type: FormTypes.input },
+
           { title: '型号', key: 'model', width: '9%', type: FormTypes.normal },
           { title: '颜色', key: 'color', width: '5%', type: FormTypes.normal },
           { title: '品牌', key: 'brand', width: '6%', type: FormTypes.normal },
@@ -452,15 +478,14 @@ export default {
           { title: '库存', key: 'stock', width: '5%', type: FormTypes.normal },
           { title: '单位', key: 'unit', width: '4%', type: FormTypes.normal },
           { title: '序列号', key: 'snList', width: '12%', type: FormTypes.popupJsh, kind: 'sn', multi: true },
-          { title: '批号', key: 'batchNumber', width: '7%', type: FormTypes.popupJsh, kind: 'batch', multi: false },
           { title: '有效期', key: 'expirationDate', width: '7%', type: FormTypes.input, readonly: true },
           { title: '多属性', key: 'sku', width: '9%', type: FormTypes.normal },
           { title: '原数量', key: 'preNumber', width: '4%', type: FormTypes.normal },
           { title: '已出库', key: 'finishNumber', width: '4%', type: FormTypes.normal },
           {
-            title: '数量',
+            title: '出库数量',
             key: 'operNumber',
-            width: '4%',
+            width: '5%',
             type: FormTypes.inputNumber,
             statistics: true,
             validateRules: [{ required: true, message: '${title}不能为空' }],
@@ -477,6 +502,25 @@ export default {
             statistics: true,
           },
           { title: '价税合计', key: 'taxLastMoney', width: '7%', type: FormTypes.inputNumber, statistics: true },
+
+          {
+            title: '实际出库数量',
+            key: 'actualQuantityInStorage',
+            width: '9%',
+            type: FormTypes.inputNumber,
+            validateRules: [{ required: true, message: '实际入库数量不能为空' }],
+          },
+          { title: '出库差异', key: 'warehousingVariance', width: '9%', type: FormTypes.input },
+          { title: '出库差异原因', key: 'reasonOfDifference', width: '9%', type: FormTypes.input },
+          {
+            title: '出库人',
+            key: 'warehousingUser',
+            width: '9%',
+            type: FormTypes.input,
+            validateRules: [{ required: true, message: '出库人不能为空' }],
+          },
+          { title: '出库时间', key: 'warehousingTime', width: '9%', type: FormTypes.date },
+
           { title: '备注', key: 'remark', width: '6%', type: FormTypes.input },
           { title: '关联id', key: 'linkId', width: '5%', type: FormTypes.hidden },
         ],
@@ -513,10 +557,10 @@ export default {
       this.billStatus = '0'
       this.currentSelectDepotId = ''
       this.rowCanEdit = true
-      this.materialTable.columns[1].type = FormTypes.popupJsh
+      this.materialTable.columns[0].type = FormTypes.popupJsh
       this.changeColumnHide()
       this.changeFormTypes(this.materialTable.columns, 'snList', 0)
-      this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
+      // this.changeFormTypes(this.materialTable.columns, 'batchNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'expirationDate', 0)
       this.changeFormTypes(this.materialTable.columns, 'preNumber', 0)
       this.changeFormTypes(this.materialTable.columns, 'finishNumber', 0)
@@ -525,6 +569,8 @@ export default {
         this.addInit(this.prefixNo)
         this.personList.value = ''
         this.fileList = []
+        this.imageList = []
+
         this.$nextTick(() => {
           handleIntroJs(this.prefixNo, 1)
         })
@@ -556,6 +602,8 @@ export default {
         }
         this.personList.value = this.model.salesMan
         this.fileList = this.model.fileName
+        this.imageList = this.model.voucherPicture
+
         this.$nextTick(() => {
           this.form.setFieldsValue(
             pick(
@@ -621,6 +669,11 @@ export default {
       } else {
         billMain.fileName = ''
       }
+      if (this.imageList && this.imageList.length > 0) {
+        billMain.voucherPicture = this.imageList
+      } else {
+        billMain.voucherPicture = ''
+      }
       if (this.model.id) {
         billMain.id = this.model.id
       }

+ 4 - 4
jshERP-web/src/views/material/MaterialList.vue

@@ -2,7 +2,7 @@
 <template>
   <a-row :gutter="24">
     <a-col :md="24">
-      <a-card :style="cardStyle" :bordered="false">
+      <a-card :bordered="false">
         <!-- 查询区域 -->
         <div class="table-page-search-wrapper">
           <!-- 搜索区域 -->
@@ -158,14 +158,14 @@
             <template slot="content">
               <a-checkbox-group @change="onColChange" v-model="settingDataIndex" :defaultValue="settingDataIndex">
                 <a-row style="width: 500px">
-                  <template v-for="(item, index) in defColumns">
-                    <template>
+                  <template>
+                    <div v-for="(item, index) in defColumns" :key="index">
                       <a-col :span="8">
                         <a-checkbox :value="item.dataIndex">
                           <j-ellipsis :value="item.title" :length="10"></j-ellipsis>
                         </a-checkbox>
                       </a-col>
-                    </template>
+                    </div>
                   </template>
                 </a-row>
                 <a-row style="padding-top: 10px">

+ 0 - 1
jshERP-web/src/views/material/modules/MaterialModal.vue

@@ -890,7 +890,6 @@ export default {
           this.fileList = record.imgName
         }, 5)
       }
-      console.log('this.model--------', this.model)
       this.$nextTick(() => {
         this.form.setFieldsValue(
           pick(

+ 1 - 1
pom.xml

@@ -145,7 +145,7 @@
 		<dependency>
 			<groupId>cn.hutool</groupId>
 			<artifactId>hutool-all</artifactId>
-			<version>5.7.17</version>
+			<version>5.8.25</version>
 		</dependency>
 
 		<!-- 二维码 -->

+ 43 - 0
src/main/java/com/jsh/erp/controller/OssController.java

@@ -0,0 +1,43 @@
+package com.jsh.erp.controller;
+
+import com.jsh.erp.base.AjaxResult;
+import com.jsh.erp.utils.OssUtils;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+@RestController
+@Api(tags = "OSS对象存储Controller")
+@RequestMapping("/oss")
+public class OssController {
+    @Autowired
+    OssUtils ossUtils;
+
+    @PostMapping("upload")
+    public AjaxResult uploadFile(MultipartFile file) {
+        //返回上传oss的url
+        String url = ossUtils.uploadOneFile(file);
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("fileName", file.getOriginalFilename());
+        ajax.put("url", url);
+        return ajax;
+    }
+
+    @PostMapping("uploadArrayFile")
+    public List<String> uploadArrayFile(MultipartFile[] files) {
+        //返回上传oss的url
+        return ossUtils.uploadArrayFile(files);
+    }
+
+    @PostMapping("deleteFile")
+    public boolean deleteFile(@RequestBody String fileUrl) {
+        //返回是否删除成功
+        return ossUtils.deleteFile(fileUrl);
+    }
+}

+ 111 - 0
src/main/java/com/jsh/erp/utils/OssUtils.java

@@ -0,0 +1,111 @@
+package com.jsh.erp.utils;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.lang.UUID;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+public class OssUtils {
+
+    @Value("${aliyun.accessKeyId}")
+    private String accessKeyId;
+
+    @Value("${aliyun.secretAccessKey}")
+    private String secretAccessKey;
+
+    @Value("${aliyun.oss.endPoint}")
+    private String endPoint;
+
+    @Value("${aliyun.oss.bucketName}")
+    private String bucketName;
+
+    public String uploadOneFile(MultipartFile file) {
+
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
+        //设置文件名
+        String fileName = new DateTime().toString("yyyy/MM/dd")
+                + UUID.randomUUID().toString().replace("-", "")
+                + file.getOriginalFilename();
+
+        try {
+            // 创建PutObject请求。
+            ossClient.putObject(bucketName, fileName, file.getInputStream());
+
+            String url = "https://" + bucketName + "." + endPoint + "/" + fileName;
+            return url;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+    }
+
+    public List<String> uploadArrayFile(MultipartFile[] files) {
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
+        List<String> list = new ArrayList<>();
+
+        try {
+            //设置文件名
+            for (MultipartFile file : files) {
+                String fileName = new DateTime().toString("yyyy/MM/dd")
+                        + UUID.randomUUID().toString().replace("-", "")
+                        + file.getOriginalFilename();
+                // 创建PutObject请求。
+                ossClient.putObject(bucketName, fileName, file.getInputStream());
+
+                String url = "http://" + bucketName + "." + endPoint + "/" + fileName;
+//                System.out.println(url);
+                list.add(url);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+        return list;
+
+    }
+
+    public boolean deleteFile(String fileUrl) {
+
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
+        /** oss删除文件是根据文件完成路径删除的,但文件完整路径中不能包含Bucket名称。
+         * 比如文件路径为:http://edu-czf.oss-cn-guangzhou.aliyuncs.com/2022/08/abc.jpg",
+         * 则完整路径就是:2022/08/abc.jpg
+         */
+        int begin = ("http://" + bucketName + "." + endPoint + "/").length(); //找到文件路径的开始下标
+        String deleteUrl = fileUrl.substring(begin);
+
+        try {
+            // 删除文件请求
+            ossClient.deleteObject(bucketName, deleteUrl);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+    }
+
+}
+

+ 8 - 0
src/main/resources/application-dev.yml

@@ -21,3 +21,11 @@ spring:
     host: 127.0.0.1
     port: 6379
     password:
+
+aliyun:
+  accessKeyId: LTAI5tAWjmJQaDBF6u7JAgap
+  secretAccessKey: t9ffHVVngMbMZcVPXtgxF6NU9lHc95
+  oss:
+    endPoint: oss-cn-hangzhou.aliyuncs.com
+    bucketName: xiangli-erp
+    miniProgramAppId: wxd716cb744e32271a

+ 8 - 0
src/main/resources/application-pro.yml

@@ -21,3 +21,11 @@ spring:
     host: 127.0.0.1
     port: 16379
     password: jiesuiredis2022
+
+aliyun:
+  accessKeyId: LTAI5tAWjmJQaDBF6u7JAgap
+  secretAccessKey: t9ffHVVngMbMZcVPXtgxF6NU9lHc95
+  oss:
+    endPoint: oss-cn-hangzhou.aliyuncs.com
+    bucketName: xiangli-erp
+    miniProgramAppId: wxd716cb744e32271a

+ 8 - 0
src/main/resources/application-test.yml

@@ -21,3 +21,11 @@ spring:
     host: 127.0.0.1
     port: 16379
     password: jiesuiredis2022
+
+aliyun:
+  accessKeyId: LTAI5tAWjmJQaDBF6u7JAgap
+  secretAccessKey: t9ffHVVngMbMZcVPXtgxF6NU9lHc95
+  oss:
+    endPoint: oss-cn-hangzhou.aliyuncs.com
+    bucketName: xiangli-erp
+    miniProgramAppId: wxd716cb744e32271a

+ 1 - 1
src/main/resources/application.yml

@@ -18,7 +18,7 @@ plugin:
 
 spring:
   profiles:
-    active: test
+    active: dev
   servlet:
     #文件上传限制(byte)
     multipart: