@dongkboy 3 månader sedan
förälder
incheckning
896209e9f2

+ 4 - 1
src/api/modules/finance.ts

@@ -74,7 +74,10 @@ const financeApi = (axiosInstance: ApiInstance) => ({
     exportTemplateReceivableList: (data: any) => axiosInstance.post('/receivable/exportTemplateReceivableList', data),
     // 私有协议-导入修改
     importReceivableListUpdate: (data: any) => axiosInstance.post('/receivable/importReceivableListUpdate', data),
-
+    // 应收开票导入
+    importAccountsReceivableInvoice: (data: any) => axiosInstance.post('/receivable/importAccountsReceivableInvoice', data),
+    // 应收开票导入模版下载
+    exportAccountsReceivableInvoiceTemplate: (data: any) => axiosInstance.post('/receivable/exportAccountsReceivableInvoiceTemplate', data),
     // 应付账款-提现审核
     amountAuditingList: (data: any) => axiosInstance.post('/amountAuditing/auditList', data), // 提现列表
     amountAuditingIsLock: (data: string) => axiosInstance.get(`/amountAuditing/isLock?id=${data}`), // 判断领取按钮是否锁定

+ 23 - 21
src/views/receivable/handingFee/index.vue

@@ -631,30 +631,32 @@ const selectTypeChange = (type) => {
 let options = ref([])
 const handleInvoice = () => {
   if (selectedList.value.length < 1) {
-    ElMessage({
-      message: '请选择数据!',
-      type: 'warning'
+    myRouter.push({
+      name: 'HandingFeeTicket',
+      query: {
+        invoiceType: activeName.value == '1' ? '1' : activeName.value == '2' ? '3' : ''
+      }
     })
-    return
-  }
-  if (selectedList.value.some((item: any) => item.invoiceStatusName == '已开票')) {
-    ElMessage({
-      message: '存在已开票数据,不能开票!',
-      type: 'warning'
+  } else {
+    if (selectedList.value.some((item: any) => item.invoiceStatusName == '已开票')) {
+      ElMessage({
+        message: '存在已开票数据,不能开票!',
+        type: 'warning'
+      })
+      return
+    }
+    invoiceShow.value = true
+    let arr = selectedList.value.map((item) => {
+      return item.id
+    })
+    api.financeApi.getReceivableCompany({
+      incomeIds: [...arr]
+    }).then((res: any) => {
+      if (res.code == 200) {
+        options.value = res.data
+      }
     })
-    return
   }
-  invoiceShow.value = true
-  let arr = selectedList.value.map((item) => {
-    return item.id
-  })
-  api.financeApi.getReceivableCompany({
-    incomeIds: [...arr]
-  }).then((res: any) => {
-    if (res.code == 200) {
-      options.value = res.data
-    }
-  })
 }
 const handleExport = () => {
   api.financeApi.exportSuperviseExcel({

+ 120 - 13
src/views/receivable/handingFee/ticket.vue

@@ -9,12 +9,15 @@
       </div>
       <div class="search-right">
         <div class="search-type" v-for="(item, index) in searchList">
-          <el-select v-model="item.name" style="margin-right: 20px; width: 200px" disabled>
+          <el-select v-model="item.name" style="margin-right: 20px; width: 220px" disabled>
             <el-option value="companyId" label="保险公司"></el-option>
             <el-option value="signDate" label="签单时间"></el-option>
             <el-option value="ptlAgreement" label="出单协议"></el-option>
             <el-option value="orderType" label="订单类型"></el-option>
             <el-option value="signYear" label="签单年份"></el-option>
+            <el-option value="licenseNo" label="车牌号"></el-option>
+            <el-option value="jqPolicyNo" label="交强险保单号"></el-option>
+            <el-option value="syPolicyNo" label="商业险保单号"></el-option>
           </el-select>
           <el-select v-model="item.type" v-if="item.name != 'signDate'" style="margin-right: 20px; width: 150px"
             @change="val => signDateSelectChange(index, val)">
@@ -53,18 +56,21 @@
           <el-date-picker v-if="item.name == 'signYear'" style="width: 350px" format="YYYY" value-format="YYYY"
             v-model="yearrangesearch" type="yearrange" range-separator="-" :disabled="item.type == '为空'"
             @change="handlePtlAgreementChange(index, $event)" />
-          <!-- <el-icon style="margin-left: 20px; cursor:pointer;"><CircleClose /></el-icon> -->
+          <el-input v-if="item.name == 'licenseNo' || item.name == 'jqPolicyNo' || item.name == 'syPolicyNo'"
+            placeholder="请输入" style="width: 350px" v-model="item.search" />
         </div>
-        <el-button type="primary" @click="handleSearch">搜索</el-button>
+      <el-button type="primary" class="w-88px" @click="handleSearch">搜索</el-button>
+
       </div>
+
     </div>
     <div class="tips">
       <p>应收明细</p>
       <el-button type="primary" @click="addTicket">添加应收</el-button>
     </div>
-    <el-table :data="tableData" style="height: calc(100% - 340px)">
+    <el-table :data="tableData" style="height: calc(100% - 300px)">
       <template #empty>
-        <div v-if="noData">暂无应收,点击<el-button link type="primary">导入应收</el-button></div>
+        <div v-if="noData">暂无应收,点击<el-button link type="primary" @click="batchShow = true">导入应收</el-button></div>
         <div v-else>没有符合的应收单据~</div>
       </template>
       <el-table-column prop="licenseNo" label="车牌号"></el-table-column>
@@ -167,7 +173,7 @@
         </el-form-item>
         <el-form-item prop="receivableSupervisePremium" label="应收金额">
           <el-input-number v-model="countForm.receivableSupervisePremium" style="width: 100%;" :min="0" :precision="4"
-            controls-position="right"  @change="handleChange" />
+            controls-position="right" @change="handleChange" />
         </el-form-item>
         <el-form-item prop="overinflatedAmount" label="虚增金额">
           <el-input v-model="countForm.overinflatedAmount" disabled></el-input>
@@ -181,7 +187,7 @@
         </el-form-item>
         <el-form-item v-if="isSettlement" prop="actualReceivedAmount" label="实收金额">
           <el-input-number v-model="countForm.actualReceivedAmount" style="width: 100%;" :min="0" :precision="4"
-            controls-position="right"  @change="handleChange1" />
+            controls-position="right" @change="handleChange1" />
         </el-form-item>
         <el-form-item v-if="isSettlement" prop="actualReceivedAmount" label="回款差额">
           <el-input v-model="countForm.paymentDifference" disabled></el-input>
@@ -204,6 +210,37 @@
         <el-button type="primary" @click="handelComfirm()">确定</el-button>
       </template>
     </el-dialog>
+    <el-dialog v-model="batchShow" width="800" title="数据导入">
+      <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 10px">
+        下载「标准导入模板」,编辑后上传;系统将自动匹配相关字段
+        <el-button link type="primary" @click="downloadTemplate">下载模板</el-button>
+      </div>
+      <el-upload class="upload-demo " drag accept=".xls, .xlsx" :auto-upload="false" @change="uploadJYFile">
+        <div class="flex f-c a-c">
+          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+          <div class="el-upload__text">
+            点击或将文件拖拽到这里上传
+          </div>
+          <a style="color: #999; font-size: 12px">目前支持的文件类型为*.xls, *.xlsx</a>
+        </div>
+      </el-upload>
+      <div v-if="importModifyCallback">
+        <div>
+          您将导入 <span style="color:#409eff;">{{ importModifyCallback?.failedNumber +
+            importModifyCallback?.successNumber
+            ||
+            0 }}
+          </span> 条数据,其中 <span style="color:#409eff;">{{ importModifyCallback?.successNumber || 0 }} </span>
+          条正常导入;<span style="color: red;">{{ importModifyCallback?.failedNumber || 0 }}</span> 条不符合要求无法导入。
+        </div>
+        <el-button type="primary" link @click="downloadImportFailedData(importModifyCallback)">下载导入失败文件</el-button>
+      </div>
+      <template #footer>
+        <el-button class="border-[#0083FF] color-[#0083FF]" plain @click="batchShow = false">取消</el-button>
+        <el-button type="primary" @click="batchShow = false">确定</el-button>
+      </template>
+    </el-dialog>
+
   </div>
 </template>
 
@@ -215,6 +252,7 @@ import { ElMessage } from "element-plus";
 
 let route = useRoute()
 let router = useRouter()
+let batchShow = ref(false)
 const selectedList = ref([])//选中的应收单据
 const companyList = ref()//保险公司
 const insurerContract = ref()//保险公司协议
@@ -256,6 +294,20 @@ let searchList = ref([
     name: 'signYear',
     type: '等于',
     search: ''
+  },
+  {
+    name: 'licenseNo',
+    type: '等于',
+    search: ''
+  },
+  {
+    name: 'jqPolicyNo',
+    type: '等于',
+    search: ''
+  }, {
+    name: 'syPolicyNo',
+    type: '等于',
+    search: ''
   }
 ])
 if (route.query) {
@@ -334,7 +386,11 @@ const signDateSelectChange = (index: any, e: any) => {
 
 // 未审核订单查询
 const getUnauditedOrder = () => {
-  api.financeApi.getUnauditedOrder(addSearchValue.value).then((res: any) => {
+  api.financeApi.getUnauditedOrder({
+    orderNo: addSearchValue.value,
+    agreementType: '2',
+    queryType: route.query.invoiceType == '1' ? '1' : route.query.invoiceType == '2' ? '3' : ''
+  }).then((res: any) => {
     if (res.code == 200) {
       selectingData.value = res.data
     }
@@ -350,12 +406,19 @@ const handleAddSubmit = () => {
       type: 'warning'
     })
   } else {
-    api.financeApi.addReceivable(selectedData.value).then((res: any) => {
+    api.financeApi.addReceivable({
+      orderNo: [...selectedData.value.map(item => item.orderNo)]
+    }).then((res: any) => {
       if (res.code == 200) {
         ElMessage({
           message: res.msg,
           type: 'success'
         })
+        api.financeApi.getSelectedReceivableList({ orderNos: [...selectedData.value.map(item => item.orderNo)] }).then((res: any) => {
+          if (res.code == 200) {
+            tableData.value = res.data
+          }
+        })
         addShow.value = false
       }
     })
@@ -376,6 +439,48 @@ const handleToAdd = (row) => {
   // })
 }
 
+let importModifyCallback = ref()// 导入数据回调
+const uploadJYFile = async (file) => {
+  let files = file.raw
+  const params = new FormData(); // 声明formData数据类型
+  params.append("file", files);
+  const { code, data, msg } = await api.financeApi.importAccountsReceivableInvoice(params)
+  if (code == 200) {
+    importModifyCallback.value = data
+    api.financeApi.getSelectedReceivableList({ orderNos: data.orderNos }).then((res: any) => {
+      if (res.code == 200) {
+        tableData.value = res.data
+      }
+    })
+    ElMessage({
+      message: msg,
+      type: 'success'
+    })
+  }
+}
+// 下载导入失败文件
+const downloadImportFailedData = (item) => {
+  const link = document.createElement('a');
+  link.href = item.failFileUrl;
+  link.download = '';
+  // 触发下载
+  document.body.appendChild(link);
+  link.click();
+  document.body.removeChild(link);
+}
+const downloadTemplate = () => {
+  api.financeApi.exportAccountsReceivableInvoiceTemplate({}).then((res: any) => {
+    if (res.code == 200) {
+      const link = document.createElement('a');
+      link.href = res.msg;
+      link.download = '应收开票导入模版.xlsx';
+      // 触发下载
+      document.body.appendChild(link);
+      link.click();
+      document.body.removeChild(link);
+    }
+  })
+}
 // 开票并结算
 const handleBack = () => {
   router.back()
@@ -392,7 +497,7 @@ const handleTicket = (bool) => {
   const params = {
     incomeIds: tableData.value.map(v => v.id),
     orderNos: tableData.value.map(v => v.orderNo),
-    companyId: route.query.id,
+    companyId: route.query.id || '',
     invoiceType: route.query.invoiceType
   }
   api.financeApi.invoicingCheck(params).then(async (res: any) => {
@@ -431,7 +536,7 @@ const handleChange1 = async () => {
  * @param subtrahend 减数
  * @returns 差值,若接口无数据则返回 0
  */
-const calSub = async (minuend:number, subtrahend:number) => {
+const calSub = async (minuend: number, subtrahend: number) => {
   const res = await api.financeApi.calSub({ minuend, subtrahend })
   return res.data || 0
 }
@@ -473,6 +578,7 @@ const handelComfirm = () => {
 
 const initData = () => {
   // router
+  if (selectedList.value.length < 1) return
   api.financeApi.getSelectedReceivableList({ orderNos: selectedList.value.map(v => v.orderNo), companyId: route.query.id }).then((res: any) => {
     if (res.code == 200) {
       tableData.value = res.data
@@ -518,8 +624,9 @@ onMounted(() => {
     }
 
     .search-right {
-      width: 700px;
-
+      display: grid;
+      grid-template-columns: repeat(2, 1fr);
+      gap:0  12px;
       .search-type {
         display: flex;
         align-items: center;