Commit ecd603e2 authored by yanglilong's avatar yanglilong

Merge branch 'yll-fix' into 'master'

fix(custom): 修改回款管理账单列表虚拟滚动

See merge request !87
parents 4b18951c 092fad97
<template> <template>
<div ref="burt" class="white_bg burt-container"> <div ref="burt" class="white_bg burt-container">
<Goback ref="goback" title="回款详情" /> <Goback ref="goback" title="回款详情" />
<a-tabs v-model="activeKey" @change="paneChange"> <a-tabs v-model="activeKey" @change="paneChange">
<a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title"> <a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title">
<a-form-model ref="ruleForm" :model="form" :rules="rules"> <a-form-model ref="ruleForm" :model="form" :rules="rules">
<a-row :gutter="30"> <a-row :gutter="30">
<template v-if="activeKey === '0'"> <template v-if="activeKey === '0'">
<a-col :lg="7" :sm="12"> <a-col :lg="7" :sm="12">
<a-form-model-item label="保险公司" prop="payorCode"> <a-form-model-item label="保险公司" prop="payorCode">
<a-select <a-select
v-model="form.payorCode" v-model="form.payorCode"
placeholder="请选择保险公司" placeholder="请选择保险公司"
allow-clear allow-clear
show-search show-search
:disabled="!isEdit" :disabled="!isEdit"
style="min-width: 200px; max-width: 250px" style="min-width: 200px; max-width: 250px"
@change="changePayor" @change="changePayor"
:filterOption="filterCode" :filterOption="filterCode"
> >
<a-select-option v-for="item in companyOptions" :key="item.payorCode" :value="item.payorCode"> <a-select-option
{{ item.longName }} v-for="item in companyOptions"
</a-select-option> :key="item.payorCode"
</a-select> :value="item.payorCode"
</a-form-model-item> >
</a-col> {{ item.longName }}
<a-col :lg="5" :sm="12"> </a-select-option>
<a-form-model-item label="回款日期" prop="backDate"> </a-select>
<a-date-picker </a-form-model-item>
format="YYYY-MM-DD" </a-col>
format-value="YYYY-MM-DD 00:00:00" <a-col :lg="5" :sm="12">
v-model="form.backDate" <a-form-model-item label="回款日期" prop="backDate">
placeholder="选择日期" <a-date-picker
allow-clear format="YYYY-MM-DD"
:disabled="!isEdit" format-value="YYYY-MM-DD 00:00:00"
/> v-model="form.backDate"
</a-form-model-item> placeholder="选择日期"
</a-col> allow-clear
<a-col :lg="6" :sm="12"> :disabled="!isEdit"
<a-form-model-item label="回款金额(人民币)" prop="backAmountCny"> />
<a-input </a-form-model-item>
class="fixed_width" </a-col>
type="number" <a-col :lg="6" :sm="12">
v-model="form.backAmountCny" <a-form-model-item
placeholder="请输入金额" label="回款金额(人民币)"
allow-clear prop="backAmountCny"
:disabled="!isEdit" >
/> <a-input
</a-form-model-item> class="fixed_width"
</a-col> type="number"
<a-col :lg="5" :sm="12"> v-model="form.backAmountCny"
<a-form-model-item label="可核销余额"> placeholder="请输入金额"
<a-input class="fixed_width" v-model="residueBackAmount" disabled /> allow-clear
</a-form-model-item> :disabled="!isEdit"
</a-col> />
<a-col :lg="7" :sm="12"> </a-form-model-item>
<a-form-model-item label="回款金额(美元)"> </a-col>
<a-input <a-col :lg="5" :sm="12">
class="fixed_width" <a-form-model-item label="可核销余额">
type="number" <a-input
v-model="form.backAmountUsd" class="fixed_width"
placeholder="请输入金额" v-model="residueBackAmount"
allow-clear disabled
:disabled="!isEdit" />
/> </a-form-model-item>
</a-form-model-item> </a-col>
</a-col> <a-col :lg="7" :sm="12">
<a-col :lg="5" :sm="12"> <a-form-model-item label="回款金额(美元)">
<a-form-model-item label="汇率差"> <a-input
<a-input v-model="form.backExchangeRate" placeholder="请输入金额" allow-clear :disabled="!isEdit" /> class="fixed_width"
</a-form-model-item> type="number"
</a-col> v-model="form.backAmountUsd"
<a-col :lg="6" :sm="12"> placeholder="请输入金额"
<a-form-model-item label="EOB编号"> allow-clear
<a-input v-model="form.eobNos" placeholder="请输入EOB编号" allow-clear :disabled="!isEdit" /> :disabled="!isEdit"
</a-form-model-item> />
</a-col> </a-form-model-item>
<a-col :lg="5" :sm="12"> </a-col>
<a-form-model-item label="EOB备注"> <a-col :lg="5" :sm="12">
<a-input v-model="form.eobRemark" placeholder="请输入EOB备注" allow-clear :disabled="!isEdit" /> <a-form-model-item label="汇率差">
</a-form-model-item> <a-input
</a-col> v-model="form.backExchangeRate"
<a-col :lg="5" :sm="12"> placeholder="请输入金额"
<a-form-model-item label="上传附件"> allow-clear
<a-upload :disabled="!isEdit"
name="file" />
:multiple="false" </a-form-model-item>
:showUploadList="true" </a-col>
:disabled="!isEdit" <a-col :lg="6" :sm="12">
:fileList="fileList" <a-form-model-item label="EOB编号">
:customRequest="(file) => uploadFile(file)" <a-input
:beforeUpload="() => beforeUpload()" v-model="form.eobNos"
:remove="(file) => removeFile(file)" placeholder="请输入EOB编号"
> allow-clear
<a-button type="primary"> <Icon name="ssiupload" :size="18" />上传文件 </a-button> :disabled="!isEdit"
</a-upload> />
</a-form-model-item> </a-form-model-item>
</a-col> </a-col>
</template> <a-col :lg="5" :sm="12">
<template v-else> <a-form-model-item label="EOB备注">
<a-col :lg="6" :sm="12"> <a-input
<a-form-model-item label="保险公司" prop="payorCode"> v-model="form.eobRemark"
<a-select placeholder="请输入EOB备注"
v-model="form.payorCode" allow-clear
placeholder="请选择保险公司" :disabled="!isEdit"
allow-clear />
show-search </a-form-model-item>
:disabled="!isEdit" </a-col>
style="min-width: 200px" <a-col :lg="5" :sm="12">
@change="changePayor" <a-form-model-item label="上传附件">
:filterOption="filterCode" <a-upload
> name="file"
<a-select-option v-for="item in companyOptions" :key="item.payorCode" :value="item.payorCode"> :multiple="false"
{{ item.longName }} :showUploadList="true"
</a-select-option> :disabled="!isEdit"
</a-select> :fileList="fileList"
</a-form-model-item> :customRequest="(file) => uploadFile(file)"
</a-col> :beforeUpload="() => beforeUpload()"
<a-col :lg="6" :sm="12"> :remove="(file) => removeFile(file)"
<a-form-model-item label="回款金额(人民币)" prop="backAmountCny"> >
<a-input <a-button type="primary">
class="fixed_width" <Icon name="ssiupload" :size="18" />上传文件
type="number" </a-button>
v-model="form.backAmountCny" </a-upload>
placeholder="请输入金额" </a-form-model-item>
allow-clear </a-col>
:disabled="!isEdit" </template>
/> <template v-else>
</a-form-model-item> <a-col :lg="6" :sm="12">
</a-col> <a-form-model-item label="保险公司" prop="payorCode">
<a-col :lg="6" :sm="12"> <a-select
<a-form-model-item label="本次账单回款金额合计"> v-model="form.payorCode"
<!-- <div class="blue-text">{{ ciReceiptTotalVo.backAmountTotal || 0 }}</div> --> placeholder="请选择保险公司"
<div class="blue-text">{{ accuracy.subtract(form.backAmountCny, residueBackAmount) || 0 }}</div> allow-clear
</a-form-model-item> show-search
:disabled="!isEdit"
</a-col> style="min-width: 200px"
<a-col :lg="6" :sm="12"> @change="changePayor"
<a-form-model-item label="可核销余额"> :filterOption="filterCode"
<a-input class="fixed_width" v-model="residueBackAmount" disabled /> >
</a-form-model-item> <a-select-option
</a-col> v-for="item in companyOptions"
</template> :key="item.payorCode"
</a-row> :value="item.payorCode"
</a-form-model> >
<template v-if="activeKey === '1'"> {{ item.longName }}
<div class="bill-content"> </a-select-option>
<div class="checked-count"> </a-select>
<a-button type="primary" size="small" @click="selectAllList">全选</a-button> </a-form-model-item>
已勾选账单:<span class="blue-text">{{ selectedRowKeys.length || 0 }}</span> </a-col>
<span v-if="selectedRows.filter(v=> v.status == 2).length != 0">,其中:无效 <span style="color: red;">{{ selectedRows.filter(v=> v.status == 2).length || 0 }}</span></span> <a-col :lg="6" :sm="12">
</div> <a-form-model-item
<a-tabs type="card" v-model="activeKey1"> label="回款金额(人民币)"
<a-tab-pane v-for="pane in panes1" :key="pane.key" :tab="pane.title"> prop="backAmountCny"
<div> >
<a-row type="flex" align="middle" class="search-form"> <a-input
<a-form-model class="fixed_width"
ref="searchForm" type="number"
layout="inline" v-model="form.backAmountCny"
:labelCol="{ span: 8 }" placeholder="请输入金额"
:wrapperCol="{ span: 16 }" allow-clear
:model="searchForm" :disabled="!isEdit"
> />
<a-row> </a-form-model-item>
<a-col :lg="4" :sm="12"> </a-col>
<a-form-model-item label="账单日期"> <a-col :lg="6" :sm="12">
<a-range-picker <a-form-model-item label="本次账单回款金额合计">
format="YYYY-MM-DD" <!-- <div class="blue-text">{{ ciReceiptTotalVo.backAmountTotal || 0 }}</div> -->
value-format="YYYY-MM-DD" <div class="blue-text">
v-model="searchForm.billDate" {{
:placeholder="['开始时间', '结束时间']" accuracy.subtract(
/> form.backAmountCny,
</a-form-model-item> residueBackAmount
</a-col> ) || 0
<a-col :lg="4" :sm="12"> }}
<a-form-model-item label="病历号"> </div>
<a-input </a-form-model-item>
v-model="searchForm.mrnNo" </a-col>
placeholder="请输入病历号" <a-col :lg="6" :sm="12">
allow-clear <a-form-model-item label="可核销余额">
:disabled="!isEdit" <a-input
/> class="fixed_width"
</a-form-model-item> v-model="residueBackAmount"
</a-col> disabled
<a-col :lg="4" :sm="12"> />
<a-form-model-item label="客户名称"> </a-form-model-item>
<a-input </a-col>
v-model="searchForm.patientName" </template>
placeholder="请输入客户名称" </a-row>
allow-clear </a-form-model>
:disabled="!isEdit" <template v-if="activeKey === '1'">
/> <div class="bill-content">
</a-form-model-item> <div class="checked-count">
</a-col> <a-button type="primary" size="small" @click="selectAllList"
<a-col :lg="4" :sm="12"> >全选</a-button
<a-form-model-item label="状态" :labelCol="{ span: 7 }" :wrapperCol="{ span: 14 }"> >
<a-select v-model="searchForm.rStatus" placeholder="请选择状态" allowClear> 已勾选账单:<span class="blue-text">{{
<a-select-option v-for="item in statusOptions" :key="item.code" :value="item.code"> selectedRowKeys.length || 0
{{ item.name }} }}</span>
</a-select-option>
</a-select> <span v-if="selectedRows.filter((v) => v.status == 2).length != 0"
</a-form-model-item> >,其中:无效
</a-col> <span style="color: red">{{
<a-col :lg="4" :sm="12"> selectedRows.filter((v) => v.status == 2).length || 0
<a-form-model-item label="账单编号"> }}</span>
<a-input </span
v-model="searchForm.receiptNo" >
placeholder="请输入账单编号" </div>
allow-clear <a-tabs type="card" v-model="activeKey1">
:disabled="!isEdit" <a-tab-pane
/> v-for="pane in panes1"
</a-form-model-item> :key="pane.key"
</a-col> :tab="pane.title"
<a-col class="flex-col" :lg="4" :sm="12"> >
<div> <div>
<a-button type="primary" @click="searchData"> <a-row type="flex" align="middle" class="search-form">
<Icon name="ssisearch_active" :size="14" />查询 <a-form-model
</a-button> ref="searchForm"
</div> layout="inline"
<div v-if="activeKey1 === '0' && selectedRows.length > 0"> :labelCol="{ span: 8 }"
<a-button type="primary" @click="exportExcel"> :wrapperCol="{ span: 16 }"
<Icon name="ssidaochu" :size="14" />导出 :model="searchForm"
</a-button> >
</div> <a-row>
</a-col> <a-col :lg="4" :sm="12">
</a-row> <a-form-model-item label="账单日期">
</a-form-model> <a-range-picker
</a-row> format="YYYY-MM-DD"
</div> value-format="YYYY-MM-DD"
<!-- 已关联账单 --> v-model="searchForm.billDate"
<template v-if="activeKey1 === '0'"> :placeholder="['开始时间', '结束时间']"
<template v-if="selectedRows.length > 0"> />
<div class="all-list_box"> </a-form-model-item>
<a-table </a-col>
class="table-content" <a-col :lg="4" :sm="12">
:rowClassName="rowClassName" <a-form-model-item label="病历号">
:columns="selectedColumns" <a-input
:data-source="selectedRows" v-model="searchForm.mrnNo"
:rowKey="'id'" placeholder="请输入病历号"
:scroll="{ x: '100%', y: tableHeight }" allow-clear
:pagination="false" :disabled="!isEdit"
> />
<template slot="status" slot-scope="text"> </a-form-model-item>
<span :style="{ color: text == 2 ? 'red' : '' }">{{ </a-col>
text == 1 ? '有效' : text == 2 ? '无效' : '' <a-col :lg="4" :sm="12">
}}</span> <a-form-model-item label="客户名称">
</template> <a-input
<template slot="patientName" slot-scope="text"> v-model="searchForm.patientName"
<a-tooltip placement="top"> placeholder="请输入客户名称"
<template slot="title"> allow-clear
<span>{{ text }}</span> :disabled="!isEdit"
</template> />
<span class="ellipsis_">{{ text }}</span> </a-form-model-item>
</a-tooltip> </a-col>
</template> <a-col :lg="4" :sm="12">
<template slot="operation" slot-scope="text, record, index"> <a-form-model-item
<a-button type="link" class="danger" @click.stop="delRecord(record, index)">删除</a-button> label="状态"
</template> :labelCol="{ span: 7 }"
</a-table> :wrapperCol="{ span: 14 }"
</div> >
</template> <a-select
<div class="all-list_box no-data" v-else><a-empty :image="simpleImage" /></div> v-model="searchForm.rStatus"
</template> placeholder="请选择状态"
<template v-else> allowClear
<!-- table --> >
<template v-if="isEdit"> <a-select-option
<div class="all-list_box"> v-for="item in statusOptions"
<a-table :key="item.code"
class="table-content all-list" :value="item.code"
:columns="columns" >
:data-source="dataList" {{ item.name }}
:scroll="{ x: '100%', y: tableHeight1 }" </a-select-option>
:pagination="false" </a-select>
:rowKey="'id'" </a-form-model-item>
:row-selection="{ </a-col>
selectedRowKeys: selectedRowKeys, <a-col :lg="4" :sm="12">
onSelect: onSelectChange, <a-form-model-item label="账单编号">
onSelectAll: onSelectAll <a-input
}" v-model="searchForm.receiptNo"
> placeholder="请输入账单编号"
<template slot="status" slot-scope="text"> allow-clear
<span :style="{ color: text == 2 ? 'red' : '' }">{{ :disabled="!isEdit"
text == 1 ? '有效' : text == 2 ? '无效' : '' />
}}</span> </a-form-model-item>
</template> </a-col>
<template slot="patientName" slot-scope="text"> <a-col class="flex-col" :lg="4" :sm="12">
<a-tooltip placement="top"> <div>
<template slot="title"> <a-button type="primary" @click="searchData">
<span>{{ text }}</span> <Icon name="ssisearch_active" :size="14" />查询
</template> </a-button>
<span class="ellipsis_">{{ text }}</span> </div>
</a-tooltip> <div
</template> v-if="activeKey1 === '0' && selectedRows.length > 0"
</a-table> >
<BurtPagination class="pagination" :pagination="pagination" @pageChange="pageChange" /> <a-button type="primary" @click="exportExcel">
</div> <Icon name="ssidaochu" :size="14" />导出
</template> </a-button>
</template> </div>
</a-tab-pane> </a-col>
</a-tabs> </a-row>
</div> </a-form-model>
</template> </a-row>
</a-tab-pane> </div>
<div v-if="isEdit" slot="tabBarExtraContent"> <!-- 已关联账单 -->
<a-button class="mar-left10" type="primary" @click="addNewEvt(0)"> <template v-if="activeKey1 === '0'">
<Icon :name="backMoneyNo ? 'ssibaocun' : 'ssiadd'" :size="14" />暂存 <template v-if="selectedRows.length > 0">
</a-button> <div class="all-list_box">
<a-button class="mar-left10" type="primary" @click="addNewEvt(1)"> <a-virtual-table
<Icon :name="backMoneyNo ? 'ssibaocun' : 'ssiadd'" :size="14" />结案 class="table-content"
</a-button> :rowClassName="rowClassName"
</div> :columns="selectedColumns"
</a-tabs> :data-source="selectedRows"
</div> :itemSize="46"
keyProp="id"
row-key="id"
:pagination="false"
bordered
:scroll="{ x: 1300, y: tableHeight }"
>
<!-- 账单状态 -->
<template slot="status" slot-scope="{ text }">
<span
:style="{
color: text == 2 ? 'red' : ''
}"
>{{
text == 1 ? '有效' : text == 2 ? '无效' : ''
}}</span
>
</template>
<!-- 客户姓名 -->
<template slot="patientName" slot-scope="{ text }">
<a-tooltip placement="top">
<template slot="title">
<span>{{ text }}</span>
</template>
<span class="ellipsis_">{{ text }}</span>
</a-tooltip>
</template>
</a-virtual-table>
<!-- s -->
</div>
</template>
<div class="all-list_box no-data" v-else>
<a-empty :image="simpleImage" />
</div>
</template>
<template v-else>
<!-- table -->
<template v-if="isEdit">
<div class="all-list_box">
<a-table
class="table-content all-list"
:columns="columns"
:data-source="dataList"
:scroll="{ x: '100%', y: tableHeight1 }"
:pagination="false"
:rowKey="'id'"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onSelect: onSelectChange,
onSelectAll: onSelectAll
}"
>
<template slot="status" slot-scope="text">
<span :style="{ color: text == 2 ? 'red' : '' }">{{
text == 1 ? '有效' : text == 2 ? '无效' : ''
}}</span>
</template>
<template slot="patientName" slot-scope="text">
<a-tooltip placement="top">
<template slot="title">
<span>{{ text }}</span>
</template>
<span class="ellipsis_">{{ text }}</span>
</a-tooltip>
</template>
</a-table>
<BurtPagination
class="pagination"
:pagination="pagination"
@pageChange="pageChange"
/>
</div>
</template>
</template>
</a-tab-pane>
</a-tabs>
</div>
</template>
</a-tab-pane>
<div v-if="isEdit" slot="tabBarExtraContent">
<a-button class="mar-left10" type="primary" @click="addNewEvt(0)">
<Icon :name="backMoneyNo ? 'ssibaocun' : 'ssiadd'" :size="14" />暂存
</a-button>
<a-button class="mar-left10" type="primary" @click="addNewEvt(1)">
<Icon :name="backMoneyNo ? 'ssibaocun' : 'ssiadd'" :size="14" />结案
</a-button>
</div>
</a-tabs>
</div>
</template> </template>
<script> <script>
import { Empty } from 'ant-design-vue'; import { Empty } from 'ant-design-vue'
import Goback from '@/components/Customers/goback'; import Goback from '@/components/Customers/goback'
import BurtPagination from '@/components/Customers/pagation'; import BurtPagination from '@/components/Customers/pagation'
import { eobStatusOptions } from '@/assets/js/utilsdictOptions.js'; import { eobStatusOptions } from '@/assets/js/utilsdictOptions.js'
import { exportFile, accuracy } from '@/utils/index'; import { exportFile, accuracy } from '@/utils/index'
import moment from 'moment'; import moment from 'moment'
import mixins from '@/mixins'; import mixins from '@/mixins'
const panes = [ const panes = [
{ title: '基础信息', key: '0', show: true, content: 'PaymentClaims' }, { title: '基础信息', key: '0', show: true, content: 'PaymentClaims' },
{ title: '账单列表', key: '1', show: false, content: 'Insurance' } { title: '账单列表', key: '1', show: false, content: 'Insurance' }
]; ]
import AVirtualTable from './components/a-virtual-table/Index.vue'
export default { export default {
data() { data() {
return { return {
accuracy, accuracy,
isEdit: false, crollHeight: 0,
eobStatusOptions, isEdit: false,
dialogShow: false, eobStatusOptions,
ciReceiptTotalVo:{}, dialogShow: false,
form: { ciReceiptTotalVo: {},
payorCode: undefined, form: {
backDate: null, payorCode: undefined,
backAmountCny: '', backDate: null,
backAmountUsd: '', backAmountCny: '',
backExchangeRate: '', backAmountUsd: '',
eobNos: '', // EOB编号 backExchangeRate: '',
eobRemark: '' // EOB备注 eobNos: '', // EOB编号
}, eobRemark: '' // EOB备注
fileList: [], // 上传文件列表 },
dataList: [], fileList: [], // 上传文件列表
isEditNewEOB: false, //是否在新建回款 dataList: [],
companyOptions: [], //保险公司 isEditNewEOB: false, //是否在新建回款
pagination: { companyOptions: [], //保险公司
pageNum: 1, pagination: {
pageSize: 5, pageNum: 1,
total: 0 pageSize: 5,
}, total: 0
selectedRowKeys: [], // Check here to configure the default column },
selectedRows: [], // Check here to configure the default column selectedRowKeys: [], // Check here to configure the default column
backMoneyNo: '', selectedRows: [], // Check here to configure the default column
rules: { backMoneyNo: '',
payorCode: [{ required: true, message: '请选择保险公司', trigger: 'change' }], rules: {
backDate: [{ required: true, message: '请选择回款日期', trigger: 'change' }], payorCode: [
backAmountCny: [{ required: true, message: '请输入回款金额(人民币)', trigger: ['change', 'blur'] }] { required: true, message: '请选择保险公司', trigger: 'change' }
}, ],
backDate: [
{ required: true, message: '请选择回款日期', trigger: 'change' }
],
backAmountCny: [
{
required: true,
message: '请输入回款金额(人民币)',
trigger: ['change', 'blur']
}
]
},
searchForm: { searchForm: {
billDate: [], billDate: [],
mrnNo: '', // 病历号 mrnNo: '', // 病历号
patientName: '' // 客户名字 patientName: '' // 客户名字
}, },
savedStatus: false, //是否已保存 savedStatus: false, //是否已保存
relatedList: [], relatedList: [],
panes: Object.seal(panes), panes: Object.seal(panes),
activeKey: '0', activeKey: '0',
activeKey1: '0', activeKey1: '0',
statusOptions: [ statusOptions: [
{ {
name: '无效', name: '无效',
code: 2 code: 2
}, },
{ {
name: '有效', name: '有效',
code: 1 code: 1
} }
], ],
tableHeight: 200, // 已关联账单表格高度 tableHeight1: 200 // 全部账单表格高度
tableHeight1: 200 // 全部账单表格高度 }
}; },
}, mixins: [mixins],
mixins: [mixins], components: {
components: { Goback,
Goback, BurtPagination,
BurtPagination AVirtualTable
}, },
computed: { computed: {
panes1() { panes1() {
const panes = [{ title: '已关联账单', key: '0', show: true, content: 'Associated' }]; const panes = [
if (this.isEdit) { { title: '已关联账单', key: '0', show: true, content: 'Associated' }
panes.push({ title: '全部账单', key: '1', show: false, content: 'Insurance' }); ]
} if (this.isEdit) {
return panes; panes.push({
}, title: '全部账单',
columns() { key: '1',
const base = [ show: false,
{ content: 'Insurance'
title: '账单日期', })
dataIndex: 'receiptDate', }
ellipsis: true, return panes
width: 160, },
fixed: 'left' columns() {
}, const base = [
{ {
title: '账单状态', title: '账单日期',
dataIndex: 'status', dataIndex: 'receiptDate',
ellipsis: true, ellipsis: true,
width: 100, width: 160,
fixed: 'left', fixed: 'left'
scopedSlots: { customRender: 'status' } },
}, {
{ title: '账单状态',
title: '客户姓名', dataIndex: 'status',
dataIndex: 'patientName', ellipsis: true,
ellipsis: true, width: 100,
fixed: 'left', fixed: 'left',
width: 180, scopedSlots: { customRender: 'status' }
scopedSlots: { customRender: 'patientName' } },
}, {
{ title: '病历号', dataIndex: 'mrnNo', ellipsis: true, width: 195 }, title: '客户姓名',
{ title: '保险公司', dataIndex: 'payorName', ellipsis: true, width: 195 }, dataIndex: 'patientName',
{ ellipsis: true,
title: '账单编号', fixed: 'left',
dataIndex: 'receiptNo', width: 180,
ellipsis: true, scopedSlots: { customRender: 'patientName' }
width: 150 },
}, { title: '病历号', dataIndex: 'mrnNo', ellipsis: true, width: 195 },
{ {
title: '理赔账单金额', title: '保险公司',
dataIndex: 'actualAmount', dataIndex: 'payorName',
ellipsis: true, ellipsis: true,
width: 150 width: 195
}, },
{ {
title: '回款金额', title: '账单编号',
dataIndex: 'writeOffAmount', dataIndex: 'receiptNo',
ellipsis: true, ellipsis: true,
width: 150 width: 150
}, },
{ {
title: '未清余额', title: '理赔账单金额',
dataIndex: 'residueBackAmount', dataIndex: 'actualAmount',
ellipsis: true, ellipsis: true,
width: 150 width: 150
}, },
{ {
title: '个人欠费', title: '回款金额',
dataIndex: 'arrearsAmountShow', dataIndex: 'writeOffAmount',
ellipsis: true, ellipsis: true,
width: 150, width: 150
customRender: (val) => { },
return <span style="color: red;">{val}</span>; {
} title: '未清余额',
}, dataIndex: 'residueBackAmount',
{ ellipsis: true,
title: '备注', width: 150
dataIndex: 'remark', },
ellipsis: true, {
width: 200, title: '个人欠费',
customRender: (val) => { dataIndex: 'arrearsAmountShow',
return <span style="color: red;">{val}</span>; ellipsis: true,
} width: 150,
}, customRender: (val) => {
{ return <span style="color: red;">{val}</span>
title: '收银', }
dataIndex: 'receiptTellerName', },
ellipsis: true, {
width: 120 title: '备注',
} dataIndex: 'remark',
]; ellipsis: true,
return base; width: 200,
}, customRender: (val) => {
selectedColumns() { return <span style="color: red;">{val}</span>
const base = JSON.parse(JSON.stringify(this.columns)); }
const changeAmount = this.changeAmount; },
base[7] = { {
title: '回款金额', title: '收银',
dataIndex: 'backAmount', dataIndex: 'receiptTellerName',
ellipsis: true, ellipsis: true,
width: 150, width: 120
customRender: (val, row) => { }
return ( ]
<a-input-number return base
v-model={row.backAmount} },
allow-clear selectedColumns() {
disabled={!this.isEdit} const base = JSON.parse(JSON.stringify(this.columns))
style={{ color: row.backAmount == row.currentReceiptAmount ? '' : 'red' }} const changeAmount = this.changeAmount
onBlur={() => { const delRecord = this.delRecord
changeAmount(row, 'backAmount'); // base[1] = {
}} // title: '账单状态',
/> // dataIndex: 'status',
); // ellipsis: true,
} // width: 100,
}; // fixed: 'left',
base[10].customRender = (val, row) => { // customRender: (val, row) => {
return ( // return (
<div> // <span
{this.isEdit ? ( // style={{
<a-popover title="备注" trigger="click"> // color: row.staus == 2 ? 'red' : ''
<template slot="content"> // }}
<a-textarea // >
class="remark_inp red_inp" // {row.staus == 1 ? '有效' : row.staus == 2 ? '无效' : ''}
v-model={row.remark} // </span>
auto-size={{ minRows: 3, maxRows: 5 }} // )
allow-clear // }
disabled={!this.isEdit} // }
></a-textarea> base[7] = {
</template> title: '回款金额',
<a-tooltip> dataIndex: 'backAmount',
<template slot="title">{row.remark}</template> ellipsis: true,
<a-input class="red_inp" v-model={row.remark} allow-clear disabled={!this.isEdit} /> width: 150,
</a-tooltip> customRender: (val, row) => {
</a-popover> return (
) : ( <a-input-number
<a-tooltip> v-model={row.backAmount}
<template slot="title">{row.remark}</template> allow-clear
<a-input class="red_inp" v-model={row.remark} disabled /> disabled={!this.isEdit}
</a-tooltip> style={{
)} color: row.backAmount == row.currentReceiptAmount ? '' : 'red'
</div> }}
); onBlur={() => {
}; changeAmount(row, 'backAmount')
base[8] = { }}
title: '未清余额', />
dataIndex: 'residueBackAmount', )
ellipsis: true, }
width: 150, }
customRender: (val, row) => { base[10].customRender = (val, row) => {
const residueBackAmount = return (
Number(row.currentReceiptAmount || 0) - Number(row.backAmount || 0) - Number(row.arrearsAmount || 0); <div>
return Number(residueBackAmount.toFixed(2)); {this.isEdit ? (
} <a-popover title="备注" trigger="click">
}; <template slot="content">
base[9] = { <a-textarea
title: '个人欠费', class="remark_inp red_inp"
dataIndex: 'arrearsAmount', v-model={row.remark}
ellipsis: true, auto-size={{ minRows: 3, maxRows: 5 }}
width: 150, allow-clear
customRender: (val, row) => { disabled={!this.isEdit}
return ( ></a-textarea>
<a-input-number </template>
class="red_inp" <a-tooltip>
v-model={row.arrearsAmount} <template slot="title">{row.remark}</template>
allow-clear <a-input
disabled={!this.isEdit} class="red_inp"
onBlur={() => { v-model={row.remark}
changeAmount(row, 'arrearsAmount'); allow-clear
}} disabled={!this.isEdit}
/> />
); </a-tooltip>
} </a-popover>
}; ) : (
base.splice(7, 0, { <a-tooltip>
title: '余末金额', <template slot="title">{row.remark}</template>
dataIndex: 'currentReceiptAmount', <a-input class="red_inp" v-model={row.remark} disabled />
ellipsis: true, </a-tooltip>
width: 150 )}
}); </div>
base.push({ )
title: '回款日期', }
dataIndex: 'backDate', base[8] = {
ellipsis: true, title: '未清余额',
width: 150 dataIndex: 'residueBackAmount',
}); ellipsis: true,
if (this.isEdit) { width: 150,
base.push({ customRender: (val, row) => {
title: '操作', const residueBackAmount =
dataIndex: 'operation', Number(row.currentReceiptAmount || 0) -
fixed: 'right', Number(row.backAmount || 0) -
width: 100, Number(row.arrearsAmount || 0)
scopedSlots: { customRender: 'operation' } return Number(residueBackAmount.toFixed(2))
}); }
} }
return base; base[9] = {
}, title: '个人欠费',
// 可核销余额 dataIndex: 'arrearsAmount',
residueBackAmount() { ellipsis: true,
let totalMoney = Number(this.form.backAmountCny || 0); width: 150,
this.selectedRows.forEach((item) => { customRender: (val, row) => {
totalMoney -= Number(item.backAmount); return (
}); <a-input-number
return Number(totalMoney.toFixed(2)); class="red_inp"
} v-model={row.arrearsAmount}
}, allow-clear
watch: { disabled={!this.isEdit}
activeKey1() { onBlur={() => {
this.searchForm = { changeAmount(row, 'arrearsAmount')
billDate: [], }}
mrnNo: '', // 病历号 />
patientName: '' // 客户名字 )
}; }
} }
}, base.splice(7, 0, {
created() { title: '余末金额',
this.simpleImage = Empty.PRESENTED_IMAGE_SIMPLE; dataIndex: 'currentReceiptAmount',
const { backMoneyNo, isEdit } = this.$route.query; ellipsis: true,
this.backMoneyNo = backMoneyNo; width: 150
this.isEdit = isEdit; })
this._getCompanyOptions(); base.push({
if (backMoneyNo) { title: '回款日期',
const backMoneyDataDetail = JSON.parse(localStorage.getItem('backMoneyDataDetail') || '{}'); dataIndex: 'backDate',
this.form = backMoneyDataDetail; ellipsis: true,
this.form.backDate = this.form.backDate ? moment(this.form.backDate).format('YYYY-MM-DD 00:00:00') : null; width: 150
})
if (this.isEdit) {
base.push({
title: '操作',
dataIndex: 'operation',
fixed: 'right',
width: 100,
scopedSlots: { customRender: 'operation' },
customRender: (val, row, index) => {
return (
<a-button
type="link"
class="danger"
onClick={() => {
delRecord(row, index)
}}
>
删除
</a-button>
)
}
})
}
return base
},
// 可核销余额
residueBackAmount() {
let totalMoney = Number(this.form.backAmountCny || 0)
this.selectedRows.forEach((item) => {
totalMoney -= Number(item.backAmount)
})
return Number(totalMoney.toFixed(2))
}
},
watch: {
activeKey1() {
this.searchForm = {
billDate: [],
mrnNo: '', // 病历号
patientName: '' // 客户名字
}
}
},
created() {
this.simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
const { backMoneyNo, isEdit } = this.$route.query
this.backMoneyNo = backMoneyNo
this.isEdit = isEdit
this._getCompanyOptions()
if (backMoneyNo) {
const backMoneyDataDetail = JSON.parse(
localStorage.getItem('backMoneyDataDetail') || '{}'
)
this.form = backMoneyDataDetail
this.form.backDate = this.form.backDate
? moment(this.form.backDate).format('YYYY-MM-DD 00:00:00')
: null
// 如果有上传附件则显示列表 // 如果有上传附件则显示列表
if (backMoneyDataDetail.fileList) { if (backMoneyDataDetail.fileList) {
this.fileList = backMoneyDataDetail.fileList.map((d) => { this.fileList = backMoneyDataDetail.fileList.map((d) => {
const file = { const file = {
uid: Math.random() * 10000, uid: Math.random() * 10000,
name: d.fileName, name: d.fileName,
status: 'done', status: 'done',
url: d.fileUrl url: d.fileUrl
}; }
return file; return file
}); })
} }
this.getData(); this.getData()
} }
}, },
mounted() { mounted() {
this.calcTableHeight(); this.calcTableHeight()
this._getNewEOBList(); this._getNewEOBList()
}, },
methods: { methods: {
moment, moment,
// 获取未清余额合计 // 获取未清余额合计
getBackMoneyReportCount(params) { getBackMoneyReportCount(params) {
this.$apis.queryBackReceiptCount({ this.$apis
...params, .queryBackReceiptCount({
...this.pagination ...params,
}).then((res) => { ...this.pagination
if (res.returnCode == '0000') { })
console.log(res.content) .then((res) => {
this.ciReceiptTotalVo = res.content if (res.returnCode == '0000') {
} console.log(res.content)
}); this.ciReceiptTotalVo = res.content
}, }
// 计算表格最大高度 })
calcTableHeight() { },
const dom = this.$refs.burt; // 计算表格最大高度
const containterH = dom.clientHeight; calcTableHeight() {
const gobackH = document.querySelector('.back-container').clientHeight; const dom = this.$refs.burt
const style = window.getComputedStyle(dom, null); const containterH = dom.clientHeight
const paddingT = parseFloat(style.getPropertyValue('padding-top')); const gobackH = document.querySelector('.back-container').clientHeight
const paddingB = parseFloat(style.getPropertyValue('padding-bottom')); const style = window.getComputedStyle(dom, null)
const paddingSum = paddingT + paddingB; const paddingT = parseFloat(style.getPropertyValue('padding-top'))
this.tableHeight = containterH - 300 - gobackH - paddingSum; const paddingB = parseFloat(style.getPropertyValue('padding-bottom'))
this.tableHeight1 = containterH - 340 - gobackH - paddingSum; const paddingSum = paddingT + paddingB
// 设置每页展示条数 this.tableHeight = containterH - 300 - gobackH - paddingSum
const pageSize = Math.floor((this.tableHeight1 - 10) / 32); this.tableHeight1 = containterH - 340 - gobackH - paddingSum
this.$set(this.pagination, 'pageSize', pageSize); // 设置每页展示条数
}, const pageSize = Math.floor((this.tableHeight1 - 10) / 32)
// 已关联账单表格行类名 this.$set(this.pagination, 'pageSize', pageSize)
rowClassName(record) { },
return record.hidden ? 'hide_' : ''; // 已关联账单表格行类名
}, rowClassName(record) {
// 账单查询 return record.hidden ? 'hide_' : ''
searchData() { },
if (this.activeKey1 === '1') { // 账单查询
this._getNewEOBList(); searchData() {
} else { if (this.activeKey1 === '1') {
this.getData(); this._getNewEOBList()
} } else {
}, this.getData()
// 选择框筛选 }
filterCode(input, option) { },
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0; // 选择框筛选
}, filterCode(input, option) {
paneChange() { return (
this.$refs.ruleForm[0].clearValidate(); option.componentOptions.children[0].text
this.panes.forEach((item) => { .toLowerCase()
item.show = false; .indexOf(input.toLowerCase()) >= 0
}); )
this.panes[Number(this.activeKey)].show = true; },
}, paneChange() {
changeAmount(row) { this.$refs.ruleForm[0].clearValidate()
let totalMoney = Number(this.form.backAmountCny || 0); this.panes.forEach((item) => {
this.selectedRows.forEach((item) => { item.show = false
totalMoney -= Number(item.backAmount); })
}); this.panes[Number(this.activeKey)].show = true
if (totalMoney < 0) { },
this.$message.error('可核销余额不足'); changeAmount(row) {
} let totalMoney = Number(this.form.backAmountCny || 0)
if (Number(row.actualAmount || 0) - Number(row.backAmount || 0) < 0) { this.selectedRows.forEach((item) => {
this.$message.warning('录入账单回款金额大于账单金额'); totalMoney -= Number(item.backAmount)
} })
}, if (totalMoney < 0) {
onSelectChange(selectedRow, selected) { this.$message.error('可核销余额不足')
selectedRow['backAmount'] = }
this.residueBackAmount > selectedRow.currentReceiptAmount if (Number(row.actualAmount || 0) - Number(row.backAmount || 0) < 0) {
? selectedRow.currentReceiptAmount this.$message.warning('录入账单回款金额大于账单金额')
: this.residueBackAmount; }
if (selected) { },
this.selectedRowKeys.push(selectedRow.id); onSelectChange(selectedRow, selected) {
this.selectedRows.push(selectedRow); selectedRow['backAmount'] =
} else { this.residueBackAmount > selectedRow.currentReceiptAmount
const index = this.selectedRowKeys.findIndex((item) => item === selectedRow.id); ? selectedRow.currentReceiptAmount
this.selectedRowKeys.splice(index, 1); : this.residueBackAmount
this.selectedRows.splice(index, 1); if (selected) {
this._confirmDelReceipt([selectedRow]); this.selectedRowKeys.push(selectedRow.id)
} this.selectedRows.push(selectedRow)
this.addNewEvt(0); } else {
}, const index = this.selectedRowKeys.findIndex(
onSelectAll(selected, selectedRows, changeRows) { (item) => item === selectedRow.id
if (selected) { )
this.selectedRowKeys = this.selectedRowKeys.concat(changeRows.map((item) => item.id)); this.selectedRowKeys.splice(index, 1)
changeRows.forEach((item) => { this.selectedRows.splice(index, 1)
const obj = { this._confirmDelReceipt([selectedRow])
...item, }
backAmount: this.addNewEvt(0)
this.residueBackAmount > item.currentReceiptAmount ? item.currentReceiptAmount : this.residueBackAmount },
}; onSelectAll(selected, selectedRows, changeRows) {
this.selectedRows.push(obj); if (selected) {
}); this.selectedRowKeys = this.selectedRowKeys.concat(
// this.selectedRows = this.selectedRows.concat(chgRows); changeRows.map((item) => item.id)
} else { )
changeRows.forEach((item) => { changeRows.forEach((item) => {
const findIndex = this.selectedRowKeys.findIndex((rowId) => rowId === item.id); const obj = {
this.selectedRowKeys.splice(findIndex, 1); ...item,
this.selectedRows.splice(findIndex, 1); backAmount:
}); this.residueBackAmount > item.currentReceiptAmount
this._confirmDelReceipt(changeRows); ? item.currentReceiptAmount
} : this.residueBackAmount
this.addNewEvt(0); }
}, this.selectedRows.push(obj)
// 全选 })
selectAllList() { // this.selectedRows = this.selectedRows.concat(chgRows);
let billDate = this.searchForm.billDate || []; } else {
this.$apis changeRows.forEach((item) => {
.queryReceiptInfoList({ const findIndex = this.selectedRowKeys.findIndex(
pageNum: 1, (rowId) => rowId === item.id
pageSize: this.pagination.total, )
backMoneyNo: this.backMoneyNo, this.selectedRowKeys.splice(findIndex, 1)
payorCode: this.form.payorCode, this.selectedRows.splice(findIndex, 1)
...this.searchForm, })
receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined, this._confirmDelReceipt(changeRows)
receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined }
}) this.addNewEvt(0)
.then((res) => { },
if (res.returnCode == '0000') { // 全选
let content = res.content || {}; selectAllList() {
const dataList = let billDate = this.searchForm.billDate || []
content.list.map((item) => { this.$apis
item.arrearsAmountShow = item.arrearsAmount; .queryReceiptInfoList({
item.arrearsAmount = ''; pageNum: 1,
return item; pageSize: this.pagination.total,
}) || []; backMoneyNo: this.backMoneyNo,
// payorCode: this.form.payorCode,
this.selectedRowKeys = dataList.map(item => item.id) ...this.searchForm,
this.selectedRows = dataList receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined,
this.addNewEvt(0); receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined
} else { })
this.$message.error(res.returnMsg); .then((res) => {
} if (res.returnCode == '0000') {
}); let content = res.content || {}
}, const dataList =
delRecord(record, index) { content.list.map((item) => {
this.selectedRowKeys.splice(index, 1); item.arrearsAmountShow = item.arrearsAmount
this.selectedRows.splice(index, 1); item.arrearsAmount = ''
if (record.relationed) { return item
// 已经关联的调用接口删除 }) || []
this._confirmDelReceipt([record]); //
} this.selectedRowKeys = dataList.map((item) => item.id)
}, this.selectedRows = dataList
_confirmDelReceipt(records) { this.addNewEvt(0)
if (!this.backMoneyNo) return; } else {
const receiptVoList = records this.$message.error(res.returnMsg)
.filter((item) => { }
const findIndex = this.relatedList.findIndex((rowId) => rowId === item.id); })
return findIndex > -1; },
}) delRecord(record, index) {
.map((item) => { this.selectedRowKeys.splice(index, 1)
return { this.selectedRows.splice(index, 1)
id: item.id if (record.relationed) {
}; // 已经关联的调用接口删除
}); this._confirmDelReceipt([record])
if (receiptVoList.length === 0) return; }
this.$apis },
.deleteReceiptRecord({ _confirmDelReceipt(records) {
backMoneyNo: this.backMoneyNo, if (!this.backMoneyNo) return
receiptVoList const receiptVoList = records
}) .filter((item) => {
.then((res) => { const findIndex = this.relatedList.findIndex(
if (res.returnCode == '0000') { (rowId) => rowId === item.id
this._getNewEOBList(); )
} else { return findIndex > -1
this.$message.error(res.returnMsg); })
} .map((item) => {
}); return {
}, id: item.id
// 修改保险公司 }
changePayor() { })
if (this.selectedRowKeys.length > 0 && (this.form.id || this.savedStatus)) { if (receiptVoList.length === 0) return
this.$modal.confirm({ this.$apis
title: '提示', .deleteReceiptRecord({
content: '是否解除已关联账单', backMoneyNo: this.backMoneyNo,
okText: '确认', receiptVoList
cancelText: '取消', })
onOk: () => { .then((res) => {
this.selectedRowKeys = []; if (res.returnCode == '0000') {
this.selectedRows = []; this._getNewEOBList()
}, } else {
onCancel: () => {} this.$message.error(res.returnMsg)
}); }
} })
this._getNewEOBList(); },
}, // 修改保险公司
pageChange(pager) { changePayor() {
this.pagination = { if (
...this.pagination, this.selectedRowKeys.length > 0 &&
...pager (this.form.id || this.savedStatus)
}; ) {
this._getNewEOBList(); this.$modal.confirm({
}, title: '提示',
// 获取保险公司下拉选项 content: '是否解除已关联账单',
_getCompanyOptions() { okText: '确认',
this.$apis.getCompanyOptions().then((res) => { cancelText: '取消',
this.companyOptions = res.content || []; onOk: () => {
}); this.selectedRowKeys = []
}, this.selectedRows = []
// 获取已关联的账单 },
getData() { onCancel: () => {}
if (!this.backMoneyNo) { })
if (this.activeKey1 === '0') { }
this.$message.error('暂未关联账单,请在全部账单中添加账单'); this._getNewEOBList()
} },
return; pageChange(pager) {
} this.pagination = {
let billDate = this.searchForm.billDate || []; ...this.pagination,
this.$apis ...pager
.queryBackReceiptList({ }
pageNum: 1, this._getNewEOBList()
pageSize: 999, },
backMoneyNo: this.backMoneyNo, // 获取保险公司下拉选项
...this.searchForm, _getCompanyOptions() {
receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined, this.$apis.getCompanyOptions().then((res) => {
receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined this.companyOptions = res.content || []
}) })
.then((res) => { },
if (res.returnCode == '0000') { // 获取已关联的账单
this.getBackMoneyReportCount({ getData() {
pageNum: 1, if (!this.backMoneyNo) {
pageSize: 999, if (this.activeKey1 === '0') {
backMoneyNo: this.backMoneyNo, this.$message.error('暂未关联账单,请在全部账单中添加账单')
...this.searchForm, }
receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined, return
receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined }
}) let billDate = this.searchForm.billDate || []
const list = res.content.list || []; this.$apis
let ids = []; .queryBackReceiptList({
this.selectedRows = list.map((item) => { pageNum: 1,
item.relationed = true; pageSize: 999,
ids.push(item.id); backMoneyNo: this.backMoneyNo,
return item; ...this.searchForm,
}); receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined,
this.selectedRowKeys = this.$lodash.cloneDeep(ids); receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined
this.relatedList = this.$lodash.cloneDeep(ids); })
} else { .then((res) => {
this.$message.error(res.returnMsg); if (res.returnCode == '0000') {
} this.getBackMoneyReportCount({
}); pageNum: 1,
}, pageSize: 999,
// 获取所有账单 backMoneyNo: this.backMoneyNo,
_getNewEOBList() { ...this.searchForm,
let billDate = this.searchForm.billDate || []; receiptEndDate: billDate[1]
this.$apis ? billDate[1] + ' 23:59:59'
.queryReceiptInfoList({ : undefined,
pageNum: this.pagination.pageNum, receiptStartDate: billDate[0]
pageSize: this.pagination.pageSize, ? billDate[0] + ' 00:00:00'
backMoneyNo: this.backMoneyNo, : undefined
payorCode: this.form.payorCode, })
...this.searchForm, const list = res.content.list || []
receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined, let ids = []
receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined this.selectedRows = list.map((item) => {
}) item.relationed = true
.then((res) => { ids.push(item.id)
if (res.returnCode == '0000') { return item
this.getBackMoneyReportCount({ })
pageNum: this.pagination.pageNum, this.selectedRowKeys = this.$lodash.cloneDeep(ids)
pageSize: this.pagination.pageSize, this.relatedList = this.$lodash.cloneDeep(ids)
backMoneyNo: this.backMoneyNo, } else {
payorCode: this.form.payorCode, this.$message.error(res.returnMsg)
...this.searchForm, }
receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined, })
receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined },
}) // 获取所有账单
let content = res.content || {}; _getNewEOBList() {
this.pagination.total = content.total || 0; let billDate = this.searchForm.billDate || []
this.dataList = this.$apis
content.list.map((item) => { .queryReceiptInfoList({
item.arrearsAmountShow = item.arrearsAmount; pageNum: this.pagination.pageNum,
item.arrearsAmount = ''; pageSize: this.pagination.pageSize,
return item; backMoneyNo: this.backMoneyNo,
}) || []; payorCode: this.form.payorCode,
} else { ...this.searchForm,
this.$message.error(res.returnMsg); receiptEndDate: billDate[1] ? billDate[1] + ' 23:59:59' : undefined,
} receiptStartDate: billDate[0] ? billDate[0] + ' 00:00:00' : undefined
}); })
}, .then((res) => {
//新建/保存回款 if (res.returnCode == '0000') {
addNewEvt(backStatus) { this.getBackMoneyReportCount({
if (!this.form.payorCode) { pageNum: this.pagination.pageNum,
this.$message.warning('请选择保险公司'); pageSize: this.pagination.pageSize,
return; backMoneyNo: this.backMoneyNo,
} payorCode: this.form.payorCode,
if (!this.form.backDate) { ...this.searchForm,
this.$message.warning('请选择回款日期'); receiptEndDate: billDate[1]
return; ? billDate[1] + ' 23:59:59'
} : undefined,
if (!this.form.backAmountCny && this.form.backAmountCny !== 0) { receiptStartDate: billDate[0]
this.$message.warning('请输入回款金额(人民币)'); ? billDate[0] + ' 00:00:00'
return; : undefined
} })
let receiptVoList = this.selectedRows.map((item) => { let content = res.content || {}
return { this.pagination.total = content.total || 0
id: item.id, this.dataList =
backAmount: item.backAmount, content.list.map((item) => {
arrearsAmount: item.arrearsAmount, item.arrearsAmountShow = item.arrearsAmount
remark: item.remark item.arrearsAmount = ''
}; return item
}); }) || []
const flag = receiptVoList.some((item) => { } else {
const exist = !item.backAmount && item.backAmount !== 0; this.$message.error(res.returnMsg)
return exist; }
}); })
if (flag) { },
this.$message.warning('存在关联账单未输入回款金额'); //新建/保存回款
return; addNewEvt(backStatus) {
} if (!this.form.payorCode) {
this.$message.warning('请选择保险公司')
return
}
if (!this.form.backDate) {
this.$message.warning('请选择回款日期')
return
}
if (!this.form.backAmountCny && this.form.backAmountCny !== 0) {
this.$message.warning('请输入回款金额(人民币)')
return
}
let receiptVoList = this.selectedRows.map((item) => {
return {
id: item.id,
backAmount: item.backAmount,
arrearsAmount: item.arrearsAmount,
remark: item.remark
}
})
const flag = receiptVoList.some((item) => {
const exist = !item.backAmount && item.backAmount !== 0
return exist
})
if (flag) {
this.$message.warning('存在关联账单未输入回款金额')
return
}
const formData = { const formData = {
...this.form, ...this.form,
receiptVoList, receiptVoList,
backDate: this.form.backDate ? moment(this.form.backDate).format('YYYY-MM-DD HH:mm:ss') : '', backDate: this.form.backDate
backMoneyNo: this.backMoneyNo, //回款编号 ? moment(this.form.backDate).format('YYYY-MM-DD HH:mm:ss')
backStatus // 0暂存 1结案 : '',
}; backMoneyNo: this.backMoneyNo, //回款编号
backStatus // 0暂存 1结案
}
// 上传附件格式转换 // 上传附件格式转换
formData.fileList = this.fileList.map((d) => { formData.fileList = this.fileList.map((d) => {
const file = { const file = {
fileName: d.name, fileName: d.name,
fileUrl: d.url fileUrl: d.url
}; }
return file; return file
}); })
this.$apis.saveBackMoney(formData).then((res) => { this.$apis.saveBackMoney(formData).then((res) => {
const msg = backStatus === 1 ? '结案' : '暂存'; const msg = backStatus === 1 ? '结案' : '暂存'
if (res.returnCode == '0000') { if (res.returnCode == '0000') {
this.backMoneyNo = res.content; this.backMoneyNo = res.content
this.savedStatus = true; this.savedStatus = true
this.$message.success(`${msg}成功`); this.$message.success(`${msg}成功`)
this.selectedRowKeys = []; this.selectedRowKeys = []
this.getData(); this.getData()
this._getNewEOBList(); this._getNewEOBList()
// this.$router.go(-1); // this.$router.go(-1);
} else { } else {
this.$message.error(res.returnMsg); this.$message.error(res.returnMsg)
} }
}); })
}, },
/* ======== 上传区域 ======== */ /* ======== 上传区域 ======== */
// 上传之前 // 上传之前
beforeUpload() { beforeUpload() {
const len = this.fileList.length; const len = this.fileList.length
if (len >= 5) { if (len >= 5) {
this.$message.warning('不能超过5个文件'); this.$message.warning('不能超过5个文件')
return false; return false
} }
return true; return true
}, },
// 删除文件 // 删除文件
removeFile(file) { removeFile(file) {
let index; let index
this.fileList.forEach((item, i) => { this.fileList.forEach((item, i) => {
if (item.uid == file.uid) { if (item.uid == file.uid) {
index = i; index = i
} }
}); })
this.fileList.splice(index, 1); this.fileList.splice(index, 1)
return true; return true
}, },
// 上传文件 // 上传文件
uploadFile(fileData) { uploadFile(fileData) {
let formData = new FormData(); let formData = new FormData()
formData.append('file', fileData.file); formData.append('file', fileData.file)
this.$apis.uploadImg(formData).then((res) => { this.$apis.uploadImg(formData).then((res) => {
fileData.onSuccess(); fileData.onSuccess()
let tmp = { let tmp = {
uid: Math.random() * 10000, uid: Math.random() * 10000,
name: res.original, name: res.original,
status: 'done', status: 'done',
url: res.url url: res.url
}; }
this.fileList.push(tmp); this.fileList.push(tmp)
this.$forceUpdate(); this.$forceUpdate()
}); })
}, },
//导出报表 //导出报表
exportExcel() { exportExcel() {
let filter = { let filter = {
backMoneyNo: this.backMoneyNo, backMoneyNo: this.backMoneyNo,
payorCode: this.form.payorCode payorCode: this.form.payorCode
}; }
this.$apis.exportBackReceiptList(filter).then((res) => { this.$apis.exportBackReceiptList(filter).then((res) => {
exportFile(res, '已关联账单.xls'); exportFile(res, '已关联账单.xls')
}); })
}, },
// 保险公司支持输入搜索 // 保险公司支持输入搜索
filterOption(input, option) { filterOption(input, option) {
return option.componentOptions.children[0].text.indexOf(input) >= 0; return option.componentOptions.children[0].text.indexOf(input) >= 0
} }
} }
}; }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.none-label { .none-label {
text-align: right; text-align: right;
.ant-form-item-label { .ant-form-item-label {
opacity: 0; opacity: 0;
} }
} }
.all-list_box { .all-list_box {
height: calc(100vh - 400px); height: calc(100vh - 400px);
overflow-y: auto; overflow-y: auto;
&.no-data { &.no-data {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: red; color: red;
} }
} }
.table-content { .table-content {
::v-deep { ::v-deep {
tr.hide_ { tr.hide_ {
display: none; display: none;
} }
td { td {
padding: 5px 16px !important; padding: 5px 16px !important;
} }
} }
} }
.search-form { .search-form {
.ant-form .ant-form-item { .ant-form .ant-form-item {
margin-bottom: 4px; margin-bottom: 4px;
} }
.flex-col { .flex-col {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
height: 44px; height: 44px;
} }
} }
.ant-btn .icon-class { .ant-btn .icon-class {
.mg-r(10); .mg-r(10);
} }
.success.ant-btn-link { .success.ant-btn-link {
color: #4cd964; color: #4cd964;
} }
.danger.ant-btn-link { .danger.ant-btn-link {
color: #ff3b30; color: #ff3b30;
} }
.burt-container { .burt-container {
height: calc(100vh - 86px); height: calc(100vh - 86px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-bottom: 10px; padding-bottom: 10px;
::v-deep { ::v-deep {
.ant-form-item { .ant-form-item {
display: flex; display: flex;
&.ant-form-item-with-help { &.ant-form-item-with-help {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.ant-tabs { .ant-tabs {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
} }
} }
.fixed_width { .fixed_width {
max-width: 150px; max-width: 150px;
} }
} }
.bill-content { .bill-content {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
padding-right: 12px; padding-right: 12px;
position: relative; position: relative;
::v-deep { ::v-deep {
.ant-form-item { .ant-form-item {
margin-right: 0; margin-right: 0;
} }
} }
.pagination { .pagination {
margin-top: 10px; margin-top: 10px;
::v-deep .jump-page { ::v-deep .jump-page {
height: 30px; height: 30px;
} }
} }
} }
::v-deep .bill-form { ::v-deep .bill-form {
.ant-form .ant-form-item { .ant-form .ant-form-item {
margin-bottom: 4px !important; margin-bottom: 4px !important;
} }
} }
.remark_inp { .remark_inp {
width: 300px; width: 300px;
} }
.red_inp { .red_inp {
color: red !important; color: red !important;
::v-deep .ant-input { ::v-deep .ant-input {
color: red; color: red;
} }
} }
.ellipsis_ { .ellipsis_ {
display: block; display: block;
max-width: 148px; max-width: 148px;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
@media screen and (min-width: 1920px) { @media screen and (min-width: 1920px) {
.all-list_box { .all-list_box {
height: calc(100vh - 420px); height: calc(100vh - 420px);
} }
} }
@media screen and (min-width: 1440px) { @media screen and (min-width: 1440px) {
.all-list_box { .all-list_box {
height: calc(100vh - 400px); height: calc(100vh - 400px);
} }
} }
.checked-count{ .checked-count {
position: absolute; position: absolute;
top: 14px; top: 14px;
left: 210px; left: 210px;
z-index: 10; z-index: 10;
button { button {
margin-right: 6px; margin-right: 6px;
} }
} }
</style> </style>
<template>
<!-- 表格虚拟滚动 -->
<div>
<a-table
v-bind="$attrs"
v-on="$listeners"
:pagination="false"
:columns="tableColumns"
:data-source="renderData"
>
<template
v-for="slot in Object.keys($scopedSlots)"
:slot="slot"
slot-scope="text, record, index"
>
<slot :name="slot" v-bind="{ text, record, index }"></slot>
</template>
</a-table>
<div class="ant-table-append" ref="append" v-show="!isHideAppend">
<slot name="append"></slot>
</div>
</div>
</template>
<script>
import { throttle } from 'lodash'
// 判断是否是滚动容器
function isScroller(el) {
const style = window.getComputedStyle(el, null)
const scrollValues = ['auto', 'scroll']
return (
scrollValues.includes(style.overflow) ||
scrollValues.includes(style['overflow-y'])
)
}
// 获取父层滚动容器
function getParentScroller(el) {
let parent = el
while (parent) {
if ([window, document, document.documentElement].includes(parent)) {
return window
}
if (isScroller(parent)) {
return parent
}
parent = parent.parentNode
}
return parent || window
}
// 获取容器滚动位置
function getScrollTop(el) {
return el === window ? window.pageYOffset : el.scrollTop
}
// 获取容器高度
function getOffsetHeight(el) {
return el === window ? window.innerHeight : el.offsetHeight
}
// 滚动到某个位置
function scrollToY(el, y) {
if (el === window) {
window.scroll(0, y)
} else {
el.scrollTop = y
}
}
// 表格body class名称
const TableBodyClassNames = [
'.ant-table-scroll .ant-table-body',
'.ant-table-fixed-left .ant-table-body-inner',
'.ant-table-fixed-right .ant-table-body-inner'
]
let checkOrder = 0 // 多选:记录多选选项改变的顺序
export default {
inheritAttrs: false,
name: 'a-virtual-table',
props: {
dataSource: {
type: Array,
default: () => []
},
columns: {
type: Array,
default: () => []
},
// key值,data数据中的唯一id
keyProp: {
type: String,
default: 'id'
},
// 每一行的预估高度
itemSize: {
type: Number,
default: 60
},
// 指定滚动容器
scrollBox: {
type: String
},
// 顶部和底部缓冲区域,值越大显示表格的行数越多
buffer: {
type: Number,
default: 100
},
// 滚动事件的节流时间
throttleTime: {
type: Number,
default: 10
},
// 是否获取表格行动态高度
dynamic: {
type: Boolean,
default: true
},
// 是否开启虚拟滚动
virtualized: {
type: Boolean,
default: true
},
// 是否是树形结构
isTree: {
type: Boolean,
default: false
}
},
data() {
return {
start: 0,
end: undefined,
sizes: {}, // 尺寸映射(依赖响应式)
renderData: [],
// 兼容多选
isCheckedAll: false, // 全选
isCheckedImn: false, // 控制半选样式
isHideAppend: false
}
},
computed: {
tableColumns() {
return this.columns.map((column) => {
// 兼容多选
if (column.type === 'selection') {
return {
title: () => {
return (
<a-checkbox
checked={this.isCheckedAll}
indeterminate={this.isCheckedImn}
onchange={() => this.onCheckAllRows(!this.isCheckedAll)}
></a-checkbox>
)
},
customRender: (text, row) => {
return (
<a-checkbox
checked={row.$v_checked}
onchange={() => this.onCheckRow(row, !row.$v_checked)}
></a-checkbox>
)
},
width: 60,
...column
}
} else if (column.index) {
// 兼容索引
return {
customRender: (text, row, index) => {
const curIndex = this.start + index
return typeof column.index === 'function'
? column.index(curIndex)
: curIndex + 1
},
...column
}
} else if (
column.customRender &&
typeof column.customRender === 'function'
) {
// 如果定义了 customRender 函数,使用一个新的 customRender 方法包装它
const originalCustomRender = column.customRender
column.customRender = (text, record, index) => {
// 调用原始的 customRender 函数,并传入必要的参数
return originalCustomRender(text, record, index)
}
}
return column
})
},
// 计算出每个item(的key值)到滚动容器顶部的距离
offsetMap({ keyProp, itemSize, sizes, dataSource }) {
if (!this.dynamic) return {}
const res = {}
let total = 0
for (let i = 0; i < dataSource.length; i++) {
const key = dataSource[i][keyProp]
res[key] = total
const curSize = sizes[key]
const size = typeof curSize === 'number' ? curSize : itemSize
total += size
}
return res
}
},
methods: {
// 初始化数据
initData() {
// 是否是表格内部滚动
this.isInnerScroll = false
this.scroller = this.getScroller()
this.setToTop()
// 首次需要执行2次handleScroll:因为第一次计算renderData时表格高度未确认导致计算不准确;第二次执行时,表格高度确认后,计算renderData是准确的
this.handleScroll()
this.$nextTick(() => {
this.handleScroll()
})
// 监听事件
this.onScroll = throttle(this.handleScroll, this.throttleTime)
this.scroller.addEventListener('scroll', this.onScroll)
window.addEventListener('resize', this.onScroll)
},
// 设置表格到滚动容器的距离
setToTop() {
if (this.isInnerScroll) {
this.toTop = 0
} else {
this.toTop =
this.$el.getBoundingClientRect().top -
(this.scroller === window
? 0
: this.scroller.getBoundingClientRect().top) +
getScrollTop(this.scroller)
}
},
// 获取滚动元素
getScroller() {
let el
if (this.scrollBox) {
if (this.scrollBox === 'window' || this.scrollBox === window)
return window
el = document.querySelector(this.scrollBox)
if (!el)
throw new Error(
` scrollBox prop: '${this.scrollBox}' is not a valid selector`
)
if (!isScroller(el))
console.warn(
`Warning! scrollBox prop: '${this.scrollBox}' is not a scroll element`
)
return el
}
// 如果表格是固定高度,则获取表格内的滚动节点,否则获取父层滚动节点
if (this.$attrs.scroll && this.$attrs.scroll.y) {
this.isInnerScroll = true
return this.$el.querySelector('.ant-table-body')
} else {
return getParentScroller(this.$el)
}
},
// 处理滚动事件
handleScroll() {
if (!this.virtualized) return
// 更新当前尺寸(高度)
this.updateSizes()
// 计算renderData
this.calcRenderData()
// 计算位置
this.calcPosition()
},
// 更新尺寸(高度)
updateSizes() {
if (!this.dynamic) return
let rows = []
if (this.isTree) {
// 处理树形表格,筛选出一级树形结构
rows = this.$el.querySelectorAll(
'.ant-table-body .ant-table-row-level-0'
)
} else {
rows = this.$el.querySelectorAll(
'.ant-table-body .ant-table-tbody .ant-table-row'
)
}
Array.from(rows).forEach((row, index) => {
const item = this.renderData[index]
if (!item) return
// 计算表格行的高度
let offsetHeight = row.offsetHeight
// 表格行如果有扩展行,需要加上扩展内容的高度
const nextEl = row.nextSibling
if (
nextEl &&
nextEl.classList &&
nextEl.classList.contains('ant-table-expanded-row')
) {
offsetHeight += row.nextSibling.offsetHeight
}
// 表格行如果有子孙节点,需要加上子孙节点的高度
if (this.isTree) {
let next = row.nextSibling
while (
next &&
next.tagName === 'TR' &&
!next.classList.contains('ant-table-row-level-0')
) {
offsetHeight += next.offsetHeight
next = next.nextSibling
}
}
const key = item[this.keyProp]
if (this.sizes[key] !== offsetHeight) {
this.$set(this.sizes, key, offsetHeight)
row._offsetHeight = offsetHeight
}
})
},
// 计算只在视图上渲染的数据
calcRenderData() {
const { scroller, buffer, dataSource: data } = this
// 计算可视范围顶部、底部
const top = getScrollTop(scroller) - buffer - this.toTop
const scrollerHeight = this.isInnerScroll
? this.$attrs.scroll.y
: getOffsetHeight(scroller)
const bottom =
getScrollTop(scroller) + scrollerHeight + buffer - this.toTop
let start
let end
if (!this.dynamic) {
start = top <= 0 ? 0 : Math.floor(top / this.itemSize)
end = bottom <= 0 ? 0 : Math.ceil(bottom / this.itemSize)
} else {
// 二分法计算可视范围内的开始的第一个内容
let l = 0
let r = data.length - 1
let mid = 0
while (l <= r) {
mid = Math.floor((l + r) / 2)
const midVal = this.getItemOffsetTop(mid)
if (midVal < top) {
const midNextVal = this.getItemOffsetTop(mid + 1)
if (midNextVal > top) break
l = mid + 1
} else {
r = mid - 1
}
}
// 计算渲染内容的开始、结束索引
start = mid
end = data.length - 1
for (let i = start + 1; i < data.length; i++) {
const offsetTop = this.getItemOffsetTop(i)
if (offsetTop >= bottom) {
end = i
break
}
}
}
// 开始索引始终保持偶数,如果为奇数,则加1使其保持偶数【确保表格行的偶数数一致,不会导致斑马纹乱序显示】
if (start % 2) {
start = start - 1
}
this.top = top
this.bottom = bottom
this.start = start
this.end = end
this.renderData = data.slice(start, end + 1)
this.$emit('change', this.renderData, this.start, this.end)
},
// 计算位置
calcPosition() {
const last = this.dataSource.length - 1
// 计算内容总高度
const wrapHeight = this.getItemOffsetTop(last) + this.getItemSize(last)
// 计算当前滚动位置需要撑起的高度
const offsetTop = this.getItemOffsetTop(this.start)
// 设置dom位置
TableBodyClassNames.forEach((className) => {
const el = this.$el.querySelector(className)
if (!el) return
// 创建wrapEl、innerEl
if (!el.wrapEl) {
const wrapEl = document.createElement('div')
const innerEl = document.createElement('div')
// 此处设置display为'inline-block',是让div宽度等于表格的宽度,修复x轴滚动时右边固定列没有阴影的bug
wrapEl.style.display = 'inline-block'
innerEl.style.display = 'inline-block'
wrapEl.appendChild(innerEl)
innerEl.appendChild(el.children[0])
el.insertBefore(wrapEl, el.firstChild)
el.wrapEl = wrapEl
el.innerEl = innerEl
}
if (el.wrapEl) {
// 设置高度
el.wrapEl.style.height = wrapHeight + 'px'
// 设置transform撑起高度
el.innerEl.style.transform = `translateY(${offsetTop}px)`
// 设置paddingTop撑起高度
// el.innerEl.style.paddingTop = `${offsetTop}px`
}
})
},
// 获取某条数据offsetTop
getItemOffsetTop(index) {
if (!this.dynamic) {
return this.itemSize * index
}
const item = this.dataSource[index]
if (item) {
return this.offsetMap[item[this.keyProp]] || 0
}
return 0
},
// 获取某条数据的尺寸
getItemSize(index) {
if (index <= -1) return 0
const item = this.dataSource[index]
if (item) {
const key = item[this.keyProp]
return this.sizes[key] || this.itemSize
}
return this.itemSize
},
// 【外部调用】更新
update() {
this.setToTop()
this.handleScroll()
},
// 【外部调用】滚动到第几行
// (不太精确:滚动到第n行时,如果周围的表格行计算出真实高度后会更新高度,导致内容坍塌或撑起)
scrollTo(index, stop = false) {
const item = this.dataSource[index]
if (item && this.scroller) {
this.updateSizes()
this.calcRenderData()
this.$nextTick(() => {
const offsetTop = this.getItemOffsetTop(index)
scrollToY(this.scroller, offsetTop)
// 调用两次scrollTo,第一次滚动时,如果表格行初次渲染高度发生变化时,会导致滚动位置有偏差,此时需要第二次执行滚动,确保滚动位置无误
if (!stop) {
setTimeout(() => {
this.scrollTo(index, true)
}, 50)
}
})
}
},
// 渲染全部数据
renderAllData() {
this.renderData = this.dataSource
this.$emit('change', this.dataSource, 0, this.dataSource.length - 1)
this.$nextTick(() => {
// 清除撑起的高度和位置
TableBodyClassNames.forEach((className) => {
const el = this.$el.querySelector(className)
if (!el) return
if (el.wrapEl) {
// 设置高度
el.wrapEl.style.height = 'auto'
// 设置transform撑起高度
el.innerEl.style.transform = `translateY(${0}px)`
}
})
})
},
// 执行update方法更新虚拟滚动,且每次nextTick只能执行一次【在数据大于100条开启虚拟滚动时,由于监听了data、virtualized会连续触发两次update方法:第一次update时,(updateSize)计算尺寸里的渲染数据(renderData)与表格行的dom是一一对应,之后会改变渲染数据(renderData)的值;而第二次执行update时,renderData改变了,而表格行dom未改变,导致renderData与dom不一一对应,从而位置计算错误,最终渲染的数据对应不上。因此使用每次nextTick只能执行一次来避免bug发生】
doUpdate() {
if (this.hasDoUpdate) return // nextTick内已经执行过一次就不执行
if (!this.scroller) return // scroller不存在说明未初始化完成,不执行
// 启动虚拟滚动的瞬间,需要暂时隐藏el-table__append-wrapper里的内容,不然会导致滚动位置一直到append的内容处
this.isHideAppend = true
this.update()
this.hasDoUpdate = true
this.$nextTick(() => {
this.hasDoUpdate = false
this.isHideAppend = false
})
},
// 兼容多选:选择表格所有行
onCheckAllRows(val) {
val = this.isCheckedImn ? true : val
this.dataSource.forEach((row) => {
if (row.$v_checked === val) return
this.$set(row, '$v_checked', val)
this.$set(row, '$v_checkedOrder', val ? checkOrder++ : undefined)
})
this.isCheckedAll = val
this.isCheckedImn = false
this.emitSelectionChange()
// 取消全选,则重置checkOrder
if (val === false) checkOrder = 0
},
// 兼容多选:选择表格某行
onCheckRow(row, val) {
if (row.$v_checked === val) return
this.$set(row, '$v_checked', val)
this.$set(row, '$v_checkedOrder', val ? checkOrder++ : undefined)
const checkedLen = this.dataSource.filter(
(row) => row.$v_checked === true
).length
if (checkedLen === 0) {
this.isCheckedAll = false
this.isCheckedImn = false
} else if (checkedLen === this.dataSource.length) {
this.isCheckedAll = true
this.isCheckedImn = false
} else {
this.isCheckedAll = false
this.isCheckedImn = true
}
this.emitSelectionChange()
},
// 多选:兼容表格selection-change事件
emitSelectionChange() {
const selection = this.dataSource
.filter((row) => row.$v_checked)
.sort((a, b) => a.$v_checkedOrder - b.$v_checkedOrder)
this.$emit('selection-change', selection)
},
// 多选:兼容表格toggleRowSelection方法
toggleRowSelection(row, selected) {
const val = typeof selected === 'boolean' ? selected : !row.$v_checked
this.onCheckRow(row, val)
},
// 多选:兼容表格clearSelection方法
clearSelection() {
this.isCheckedImn = false
this.onCheckAllRows(false)
}
},
watch: {
dataSource() {
if (!this.virtualized) {
this.renderAllData()
} else {
this.doUpdate()
}
},
virtualized: {
immediate: true,
handler(val) {
if (!val) {
this.renderAllData()
} else {
this.doUpdate()
}
}
}
},
created() {
this.$nextTick(() => {
this.initData()
})
},
mounted() {
const appendEl = this.$refs.append
this.$el.querySelector('.ant-table-body').appendChild(appendEl)
},
beforeDestroy() {
if (this.scroller) {
this.scroller.removeEventListener('scroll', this.onScroll)
window.removeEventListener('resize', this.onScroll)
}
}
}
</script>
<style lang="scss" scoped></style>
### 表格虚拟滚动
#### api文档
1. 属性说明
参数 说明 类型 可选值 默认值
dataSource 总数据 Array 必填
keyProp key值,data数据中的唯一id【⚠️若keyProp未设置或keyProp值不唯一,可能导致表格空数据或者滚动时渲染的数据断层、不连贯】 string — id
itemSize 每一行的预估高度 number — 60
scrollBox 指定滚动容器;在指定滚动容器时,如果表格设置了height高度,则滚动容器为表格内的滚动容器;如果表格为设置height高度,则自动获取父层以外的滚动容器,直至window容器为止 string — -
buffer 顶部和底部缓冲区域,值越大显示表格的行数越多 Number — 200
throttleTime 滚动事件的节流时间 number — 10
dynamic 动态获取表格行高度,默认开启。设置为false时,则以itemSize为表格行的真实高度,能大大减少虚拟滚动计算量,减少滚动白屏;如果itemSize与表格行的真实高度不一致,可能导致滚动时表格数据错乱 boolean — true
virtualized 是否开启虚拟滚动 boolean — true
* 支持 <a-table> 组件的props属性,更多请看 <a-table> api - — -
2. 方法说明
方法名 说明 参数
scrollTo 滚动到第几行【不太精确:因为滚动到第n行时,如果周围的表格行计算出真实高度后会更新高度,导致当前行坍塌或撑起】 index
update 更新 -
clearSelection 用于多选 <virtual-column type="selection">,清空用户的选择 -
toggleRowSelection 用于多选 <virtual-column type="selection">, 切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中) row, selected
3. 事件说明
事件名称 说明 参数
change 计算完成真实显示的表格行数 (renderData, start, end):renderData 真实渲染的数据,start和end指的是渲染的数据在总数据的开始到结束的区间范围
selection-change 虚拟表格多选选项发生更改时触发事件 selectedRows
const path = require("path"); const path = require('path')
const LodashModuleReplacementPlugin = require("lodash-webpack-plugin"); const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
const CompressionPlugin = require("compression-webpack-plugin"); // 代码压缩 const CompressionPlugin = require('compression-webpack-plugin') // 代码压缩
const defaultSettings = require("./src/settings.js"); const defaultSettings = require('./src/settings.js')
module.exports = { module.exports = {
publicPath: "/bims", publicPath: '/bims',
productionSourceMap: false, productionSourceMap: false,
pluginOptions: { pluginOptions: {
"style-resources-loader": { 'style-resources-loader': {
preProcessor: "less", preProcessor: 'less',
patterns: [path.resolve(__dirname, "src/assets/style/common.less")], patterns: [path.resolve(__dirname, 'src/assets/style/common.less')]
}, }
}, },
css: { css: {
loaderOptions: { loaderOptions: {
less: { less: {
javascriptEnabled: true, javascriptEnabled: true
}, }
} }
}, },
chainWebpack: (config) => { chainWebpack: (config) => {
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === 'production') {
// lodash 按需加载 // lodash 按需加载
config.plugin("loadshReplace").use(new LodashModuleReplacementPlugin()); config.plugin('loadshReplace').use(new LodashModuleReplacementPlugin())
} }
}, },
configureWebpack: (config) => { configureWebpack: (config) => {
config.name = defaultSettings.title; config.name = defaultSettings.title
const plugins = []; const plugins = []
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === 'production') {
plugins.push( plugins.push(
new CompressionPlugin({ new CompressionPlugin({
filename: "[path][base].gz", filename: '[path][base].gz',
algorithm: "gzip", algorithm: 'gzip',
test: new RegExp(".(" + ["js", "css", "json"].join("|") + ")$"), test: new RegExp('.(' + ['js', 'css', 'json'].join('|') + ')$'),
threshold: 8192, threshold: 8192,
include: /\/src/, include: /\/src/,
exclude: /node_modules/, exclude: /node_modules/,
minRatio: 0.8, minRatio: 0.8,
deleteOriginalAssets: false, // 此处源文件保留吧,以防不测 deleteOriginalAssets: false // 此处源文件保留吧,以防不测
}) })
); )
} }
config.plugins = [...config.plugins, ...plugins]; config.plugins = [...config.plugins, ...plugins]
}, },
devServer: { devServer: {
...@@ -51,14 +51,15 @@ module.exports = { ...@@ -51,14 +51,15 @@ module.exports = {
port: 8888, port: 8888,
hot: true, hot: true,
proxy: { proxy: {
"^/api_bims": { '^/api_bims': {
target: "http://47.99.75.3:8070", target: 'http://47.99.75.3:8070', // 测试
// target: 'http://bims.medilink-global.com.cn/api_bims', // 生产
pathRewrite: { pathRewrite: {
"^/api_bims": "/", '^/api_bims': '/'
}, },
changeOrigin: true, changeOrigin: true,
secure: false, secure: false
}, }
}, }
}, }
}; }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment