1226 lines
42 KiB
Vue
1226 lines
42 KiB
Vue
<template>
|
||
<div class="p-2 h-full flex flex-col">
|
||
<PageHeader></PageHeader>
|
||
<div class="mb-[10px]">
|
||
<el-card shadow="hover">
|
||
<el-form ref="queryFormRef" :model="queryParams" @submit.prevent="handleQuery" :inline="true">
|
||
<div>
|
||
<el-form-item label="小区" prop="villageId">
|
||
<el-select @change="handleChangeVillage" v-model="queryParams.villageId" placeholder="请选择小区">
|
||
<el-option v-for="(item, index) in villageList" :key="index" :value="item.villageId" :label="item.villageName"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="楼栋" prop="buildingId">
|
||
<el-select @change="handleChangeBuilding" v-model="queryParams.buildingId" placeholder="请选择楼栋">
|
||
<el-option v-for="(item, index) in buildingList" :key="index" :value="item.id" :label="item.buildingName"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="单元" prop="unitNoId">
|
||
<el-select @change="handleChangeUnit" v-model="queryParams.unitNoId" placeholder="请选择单元">
|
||
<el-option v-for="(item, index) in unitList" :key="index" :value="item.unitNoId" :label="item.unitNoName"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item @change="handleChangeHouseNo" label="房号" prop="houseId">
|
||
<el-select v-model="queryParams.houseId" placeholder="请选择房号">
|
||
<el-option-group v-for="group in houseList" :key="group.floorNo" :label="String(group.floorNo) + ' 楼'">
|
||
<el-option v-for="item in group.houses" :key="item.houseId" :label="item.houseNo" :value="item.houseId" />
|
||
</el-option-group>
|
||
</el-select>
|
||
</el-form-item>
|
||
</div>
|
||
<div>
|
||
<el-form-item label="收费项目" prop="itemId">
|
||
<el-select multiple v-model="queryParams.chargeItemId" placeholder="请选择收费项目">
|
||
<el-option
|
||
:disabled="item.status === '1'"
|
||
v-for="(item, index) in chargeItems"
|
||
:key="index"
|
||
:value="item.id"
|
||
:label="item.itemName"
|
||
></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="缴费周期" prop="chargePeriod">
|
||
<el-date-picker
|
||
v-model="chargePeriod"
|
||
type="daterange"
|
||
format="YYYY-MM-DD"
|
||
value-format="YYYY-MM-DD"
|
||
range-separator="到"
|
||
start-placeholder="开始日期"
|
||
@clear="handleClearChargePeriod"
|
||
end-placeholder="结束日期"
|
||
placeholder="请选择缴费日期"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="房屋分类" prop="houseUseTypeId">
|
||
<el-select v-model="queryParams.houseUseTypeId">
|
||
<el-option v-for="item in houseUseTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="缴费时间" prop="payTime">
|
||
<el-date-picker
|
||
v-model="payTime"
|
||
type="datetimerange"
|
||
format="YYYY-MM-DD HH:mm:ss"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
range-separator="到"
|
||
start-placeholder="开始日期"
|
||
@clear="handleClearPayTime"
|
||
end-placeholder="结束日期"
|
||
placeholder="请选择缴费日期"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="业主姓名" prop="residentName">
|
||
<el-input maxlength="30" v-model.trim="queryParams.residentName" placeholder="请选择业主姓名"></el-input>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<div style="text-align: right">
|
||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||
<el-button @click="resetQuery">重置</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
</div>
|
||
</el-form>
|
||
</el-card>
|
||
</div>
|
||
<div class="actionsBox">
|
||
<div class="tabs-box">
|
||
<div
|
||
class="tabs-items"
|
||
v-for="(item, index) in tabs"
|
||
:key="index"
|
||
:class="{
|
||
active: activeTabs === item.value
|
||
}"
|
||
@click="changeTabs(item.value)"
|
||
>
|
||
{{ item.type }}
|
||
</div>
|
||
</div>
|
||
<div class="actions">
|
||
<el-button @click="handleIncome(false)" :disabled="!single">收费</el-button>
|
||
<el-button @click="printPIaoJuByOnly(false)" :disabled="!printSingle">打印票据</el-button>
|
||
</div>
|
||
</div>
|
||
<el-card class="flex-1" shadow="never">
|
||
<el-table v-loading="loading" border :data="tableData" @selection-change="handleSelectionChange">
|
||
<el-table-column type="selection" fixed="left" width="55" align="center" />
|
||
<el-table-column label="房屋/车位/车辆" fixed="left" align="center" prop="unitNo" width="120">
|
||
<template #default="scope">
|
||
{{ scope.row.unitNo }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="收费项目" fixed="left" align="center" prop="billCode" width="120">
|
||
<template #default="scope">
|
||
{{ scope.row.chargeItemName }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="收费周期" align="center" prop="periodDisplay" width="280">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.periodDisplay }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column label="单价" width="100" align="center" prop="fixedPrice">
|
||
<template #default="scope">
|
||
<div class="flex justify-center">
|
||
<span>
|
||
{{ scope.row.fixedPrice }}
|
||
</span>
|
||
<span v-if="scope.row.unit"> / </span>
|
||
<dict-tag v-if="scope.row.unit" :options="com_charge_item_unit" :value="scope.row.unit"></dict-tag>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="数量" width="80" align="center" prop="quantity">
|
||
<template #default="scope">
|
||
<span>{{ scope.row.quantity }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="应收金额" width="100" align="center" prop="amount" />
|
||
<el-table-column label="缴费状态" width="100" align="center" prop="payStatus">
|
||
<template #default="scope">
|
||
<span v-if="scope.row.payStatus === '0'">未缴纳</span>
|
||
<span v-else-if="scope.row.payStatus === '1'">已缴纳</span>
|
||
<span v-else-if="scope.row.payStatus === '2'">缴纳失败</span>
|
||
<span v-else>部分缴纳</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="应缴金额" width="100" align="center" prop="amount" />
|
||
<el-table-column label="优惠金额" width="100" align="center" prop="singleDiscountAmount" />
|
||
<el-table-column label="实缴金额" width="100" align="center" prop="actualAccount" />
|
||
<el-table-column label="缴费人" width="120" align="center" prop="residentName" />
|
||
<el-table-column label="缴费时间" width="200" align="center" prop="payTime" />
|
||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
||
<el-table-column label="操作" width="110" align="center" fixed="right" class-name="small-padding fixed-width">
|
||
<template #default="scope">
|
||
<el-button link type="primary" v-if="scope.row.payStatus !== '1'" @click="handleIncome(scope.row)" v-has-permi="['bill:bill:edit']"
|
||
>收款</el-button
|
||
>
|
||
<el-button link type="success" v-if="scope.row.payStatus === '1'" @click="printPIaoJuByOnly(scope.row)" v-has-permi="['bill:bill:query']"
|
||
>打印票据</el-button
|
||
>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="footerBox">
|
||
<div class="totalBox">
|
||
<span>合计:</span>
|
||
<span>应收:{{ totalAll.totalAccount }}元</span>
|
||
<span style="padding: 0 20px">实收:{{ totalAll.TotalPaymentAmount }}元</span>
|
||
<span>优惠:{{ totalAll.totalDiscountAmount }}元</span>
|
||
</div>
|
||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||
</div>
|
||
</el-card>
|
||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
|
||
<div class="payInfo">
|
||
<div>
|
||
<div class="flex flex-items-center justify-between">
|
||
<span>缴费人: {{ inComeFrom.residentName }}</span>
|
||
<span style="color: #ff9947">待缴纳</span>
|
||
</div>
|
||
</div>
|
||
<div class="flex">
|
||
<span>收费名称: </span>
|
||
<div>
|
||
<div
|
||
v-for="(item, index) in inComeFrom.billResidentId"
|
||
:key="index"
|
||
class="flex flex-items-center"
|
||
style="text-wrap: wrap; margin-bottom: 5px"
|
||
>
|
||
<div class="flex flex-items-center">
|
||
<div style="text-decoration: underline; padding-right: 5px; text-align: center">
|
||
{{ item.detailsName }} (应缴:¥{{ item.needPayAmount }})
|
||
</div>
|
||
<el-tooltip class="box-item" effect="light" placement="top" v-if="item.payStatus === '3'">
|
||
<el-icon color="#909399"><QuestionFilled /></el-icon>
|
||
<template #content>
|
||
<div style="line-height: 1.8; font-size: 13px; width: 180px">
|
||
<div style="text-align: right" class="flex justify-between">
|
||
<span>总金额</span>
|
||
<span>{{ item.amount }}¥</span>
|
||
</div>
|
||
<div style="text-align: right" class="flex justify-between">
|
||
<span>累计优惠金额</span>
|
||
<span>− {{ item.singleDiscountAmount }}¥</span>
|
||
</div>
|
||
<div style="text-align: right" class="flex justify-between">
|
||
<span>累计已交金额</span>
|
||
<span>− {{ item.paidAmount }}¥</span>
|
||
</div>
|
||
<div
|
||
class="flex justify-between cursor-pointer"
|
||
style="margin-top: 6px; border-top: 1px solid #ccc; text-align: right; padding-top: 6px"
|
||
>
|
||
<span>待缴金额</span>
|
||
<span style="font-weight: bold; color: red">{{ item.needPayAmount }}¥</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-tooltip>
|
||
</div>
|
||
<span v-if="item.payStatus === '1'">(已缴费,不计入金额)</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<span>应收合计:¥{{ inComeFrom.allCost }}</span>
|
||
</div>
|
||
<div
|
||
:class="{
|
||
DiscountColorRed: gtMoney(totalDiscountAmount, inComeFrom.allCost)
|
||
}"
|
||
class="flex flex-items-center"
|
||
>
|
||
<div>优惠合计:¥{{ totalDiscountAmount }}</div>
|
||
<div v-if="totalDiscountAmount !== totalReadDiscount && totalReadDiscount !== '0' && inComeFrom.discountMethod === 2">
|
||
|
||
<span>(实际优惠合计:¥{{ totalReadDiscount }})</span>
|
||
<el-tooltip class="box-item" effect="light" placement="top">
|
||
<el-icon color="#909399" style="vertical-align: middle"><QuestionFilled /></el-icon>
|
||
<template #content>
|
||
<span>有账单 应缴费用 不足 优惠金额</span>
|
||
</template>
|
||
</el-tooltip>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<span>预计实缴合计:¥{{ totalPayAmount }}</span>
|
||
</div>
|
||
<div>
|
||
<span>实际实缴合计:¥{{ payListAllAmount }}</span>
|
||
</div>
|
||
</div>
|
||
<el-form ref="formRef" :model="inComeFrom" label-width="100px">
|
||
<el-form-item label="费用合计" prop="allCost">
|
||
<el-input v-model="inComeFrom.allCost" disabled style="width: 400px">
|
||
<template #suffix>
|
||
<span>元</span>
|
||
</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="缴纳状态" prop="payStatus">
|
||
<el-radio-group v-model="inComeFrom.payStatus">
|
||
<el-radio value="1" label="已缴纳"></el-radio>
|
||
<el-radio value="2" label="部分缴纳"></el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="优惠方式" prop="discountMethod" v-if="inComeFrom.payStatus !== '0'">
|
||
<el-select style="width: 400px" @change="handleChangeDisCountMethod" v-model="inComeFrom.discountMethod" placeholder="请选择">
|
||
<el-option label="不优惠" :value="0"></el-option>
|
||
<el-option label="金额" :value="2"></el-option>
|
||
<el-option label="比例" :value="1"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<div v-if="inComeFrom.discountMethod !== 0">
|
||
<div v-if="inComeFrom.discountMethod === 2">
|
||
<el-form-item label="单笔优惠金额" prop="discount">
|
||
<el-input style="width: 400px" v-model.trim.number="inComeFrom.discount" @input="debouncedHandleDiscountMoney">
|
||
<template #append>
|
||
<span>¥</span>
|
||
</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
</div>
|
||
<el-form-item label="优惠比例" prop="discountRate" v-else>
|
||
<el-input
|
||
style="width: 400px"
|
||
v-model.trim.number="inComeFrom.discountRate"
|
||
placeholder="0~100:0=无优惠,80=优惠80%,100=全免"
|
||
@input="debounceDiscountRate"
|
||
>
|
||
<template #append>
|
||
<span>%</span>
|
||
</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="总优惠金额" prop="totalDiscountAmount">
|
||
<el-input style="width: 400px" disabled v-model="totalDiscountAmount">
|
||
<template #append>
|
||
<span>¥</span>
|
||
</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
</div>
|
||
<el-form-item label="支付方式" prop="payType" v-if="inComeFrom.payStatus !== '0'">
|
||
<div class="flex-1">
|
||
<div class="flex flex-items-center" v-for="(item, index) in payList" :key="index">
|
||
<div class="flex-1 flex">
|
||
<el-select @change="handleChangePayTypeId($event, index)" v-model="item.payType" placeholder="请选择">
|
||
<el-option
|
||
:disabled="isOptionDisabled(dict.value, item.payType)"
|
||
v-for="dict in com_pay_method"
|
||
:key="dict.value"
|
||
:label="dict.label"
|
||
:value="dict.value"
|
||
></el-option>
|
||
</el-select>
|
||
<el-input @change="(val: string) => handleChangePay(val, index)" v-model.number.trim="item.payAmount" style="margin: 0 10px">
|
||
<template #append>¥</template>
|
||
</el-input>
|
||
</div>
|
||
<div style="width: 80px; text-align: left">
|
||
<el-icon
|
||
color="blue"
|
||
size="24"
|
||
v-if="index === payList.length - 1 && payList.length < com_pay_method.length"
|
||
@click="addPayList"
|
||
style="margin-right: 10px; cursor: pointer"
|
||
><CirclePlus
|
||
/></el-icon>
|
||
<el-icon color="red" style="cursor: pointer" size="24" v-if="payList.length > 1" @click="removePayList(index)"><Delete /></el-icon>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input style="width: 400px" type="textarea" show-word-limit maxlength="100" :rows="5" v-model="inComeFrom.remark"></el-input>
|
||
</el-form-item>
|
||
<div class="flex justify-end">
|
||
<el-button @click="closer">取消</el-button>
|
||
<el-button @click="submitForm" :loading="buttonLoading" type="primary">提交</el-button>
|
||
</div>
|
||
</el-form>
|
||
</el-dialog>
|
||
<el-dialog :title="dialog_print.title" v-model="dialog_print.visible" width="1200px" append-to-body>
|
||
<template #header>
|
||
<div class="flex" style="justify-content: space-between; padding: 0 20px">
|
||
<div class="title">票据打印</div>
|
||
<el-button type="primary" v-print="printOption" :loading="isLoading" @click="conFimPrint">打印</el-button>
|
||
</div>
|
||
</template>
|
||
<div class="printBox" id="printBox-Bill" style="margin: 0; color: rgba(0, 0, 0, 1); padding: 5px">
|
||
<div class="title" style="font-size: 1.2rem; margin-bottom: 10px; text-indent: 5em">{{ print_form.title }}</div>
|
||
<div style="font-size: 12px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-gap: 10px; grid-template-rows: 1fr">
|
||
<div>单据日期:{{ print_form.printDate }}</div>
|
||
<div>房号:{{ print_form.HouseName }}</div>
|
||
<div>产权人:{{ print_form.residentName }}</div>
|
||
<div>No.</div>
|
||
</div>
|
||
<div class="tableBox" style="font-size: 10px">
|
||
<table class="printTable" style="border-collapse: collapse; border: 1px solid #000; width: 90%">
|
||
<thead>
|
||
<tr>
|
||
<th style="min-width: 50px">收费项目</th>
|
||
<th>收费标准</th>
|
||
<th>账单时间</th>
|
||
<th style="min-width: 50px">面积</th>
|
||
<th style="min-width: 50px">应收金额</th>
|
||
<th style="min-width: 50px">优免金额</th>
|
||
<th style="min-width: 50px">实收金额</th>
|
||
<th>收款方式</th>
|
||
<th style="min-width: 100px">备注</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr v-for="(item, index) in print_form.detailsList" :key="index">
|
||
<td>{{ item.chargeItemName }}</td>
|
||
<td>{{ item.billName }}</td>
|
||
<td>{{ item.detailsTime }}</td>
|
||
<td>{{ item.useCount }}</td>
|
||
<td>{{ item.account }}</td>
|
||
<td>{{ item.singleDiscountAmount }}</td>
|
||
<td>{{ item.actualAccount }}</td>
|
||
<td>{{ item.payType }}</td>
|
||
<td style="text-wrap: wrap; white-space: wrap">{{ item.remark }}</td>
|
||
</tr>
|
||
<tr>
|
||
<td>合计</td>
|
||
<td></td>
|
||
<td></td>
|
||
<td></td>
|
||
<td>{{ print_form.totalAccount }}</td>
|
||
<td>{{ print_form.totalDiscountAmount }}</td>
|
||
<td>{{ print_form.totalActualAccount }}</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p style="font-size: 10px">说明:本收据收款单位和收款具签章方为有效,本收据手写无效</p>
|
||
<div style="font-size: 12px; margin-bottom: 0; display: flex; align-items: center">
|
||
<div style="flex: 1">交款人:</div>
|
||
<div style="flex: 1; display: flex; align-items: center">
|
||
<span style="white-space: nowrap">收款人: </span>
|
||
<el-input v-model="inHomelyUse" v-if="!isPrint" placeholder="请输入收款人姓名" style="width: 150px"></el-input>
|
||
<span style="white-space: nowrap" v-else> {{ inHomelyUse }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import PageHeader from '@/components/Pageheader/index.vue';
|
||
import pagination from '@/components/Pagination/index.vue';
|
||
import DictTag from '@/components/DictTag/index.vue';
|
||
import { getBuildinglistAPI, getHouselistAPI } from '@/api/system/house';
|
||
import { getCommunitylistAPI } from '@/api/system/community';
|
||
import { billEdit, billlistType, billPrint, BillPrintType, billQuery } from '@/api/system/SdbCashier';
|
||
import { listChargeItem } from '@/api/system/SdbChargeItem';
|
||
import { ref } from 'vue';
|
||
import { add, div, eq, eqMoney, gtMoney, ltMoney, minMoney, moneyAdd, mul, sub, sum, toBig } from '@/utils/money';
|
||
import { BuildingUnitlist, BuildingVo, FloorsType } from '@/api/system/house/type';
|
||
import { ChargeItemVO } from '@/api/system/SdbChargeItem/type';
|
||
import { communitylist_rows_type } from '@/api/system/community/type';
|
||
import { debounce } from '@/utils';
|
||
import { listHouseUseType_add_house } from '@/api/system/houseUse';
|
||
import { CirclePlus, Delete, QuestionFilled } from '@element-plus/icons-vue';
|
||
import { useUserStore } from '@/store/modules/user';
|
||
|
||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||
const { com_pay_method, com_charge_item_unit } = toRefs<any>(proxy?.useDict('com_pay_method', 'com_charge_item_unit'));
|
||
|
||
const userStore = useUserStore();
|
||
const loading = ref(false);
|
||
const ids = ref<Array<billlistType>>([]);
|
||
const total = ref(0);
|
||
const queryFormRef = ref<ElFormInstance>();
|
||
const activeTabs = ref(null);
|
||
const tabs = [
|
||
{
|
||
value: null,
|
||
type: '全部'
|
||
},
|
||
{
|
||
value: 0,
|
||
type: '待缴纳'
|
||
},
|
||
{
|
||
value: 1,
|
||
type: '已缴纳'
|
||
},
|
||
{
|
||
value: 3,
|
||
type: '部分缴纳'
|
||
}
|
||
];
|
||
const villageId = localStorage.getItem('villageid') ?? undefined;
|
||
const queryParams = ref({
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
// 收款状态
|
||
payStatus: null,
|
||
// 小区id
|
||
villageId: villageId,
|
||
// 楼栋id
|
||
buildingId: undefined,
|
||
// 单元id
|
||
unitNoId: undefined,
|
||
// 房屋id
|
||
houseId: undefined,
|
||
// 缴费周期
|
||
chargePeriod: undefined,
|
||
// 房屋类型id
|
||
houseUseTypeId: undefined,
|
||
// 缴费时间
|
||
payTime: undefined,
|
||
// 缴费人
|
||
residentName: undefined,
|
||
// 缴费项目id
|
||
chargeItemId: undefined,
|
||
period: undefined,
|
||
// 缴费时间开始
|
||
payTimeBegin: undefined,
|
||
// 缴费时间结束
|
||
payTimeEnd: undefined,
|
||
// 开始时间
|
||
startDate: undefined,
|
||
// 结束时间
|
||
endDate: undefined
|
||
});
|
||
|
||
// 缴费周期
|
||
const chargePeriod = ref([]);
|
||
|
||
// 缴费时间
|
||
const payTime = ref([]);
|
||
const villageList = ref<communitylist_rows_type[]>([]); // 小区列表
|
||
const buildingList = ref<BuildingVo[]>([]); // 楼栋列表
|
||
const unitList = ref<BuildingUnitlist[]>([]); // 单元列表
|
||
const houseList = ref<FloorsType[]>([]); // 房屋列表
|
||
const chargeItems = ref<ChargeItemVO[]>([]);
|
||
const tableData = ref([]);
|
||
const dialog = reactive<DialogOption>({
|
||
visible: false,
|
||
title: ''
|
||
});
|
||
const houseUseTypeList = ref([]);
|
||
function getHouseTypeList() {
|
||
listHouseUseType_add_house().then((res) => {
|
||
houseUseTypeList.value = res.data;
|
||
});
|
||
}
|
||
// 切换 账单类型
|
||
function changeTabs(value: number) {
|
||
activeTabs.value = value;
|
||
queryParams.value.payStatus = value;
|
||
getList();
|
||
}
|
||
// 选择小区
|
||
function handleChangeVillage(val: string) {
|
||
queryParams.value.unitNoId = undefined;
|
||
queryParams.value.buildingId = undefined;
|
||
queryParams.value.chargeItemId = undefined;
|
||
queryParams.value.houseId = undefined;
|
||
buildingList.value = [];
|
||
unitList.value = [];
|
||
if (val) {
|
||
getBuildinglistAPI({
|
||
villageId: val
|
||
}).then((res) => {
|
||
buildingList.value = res.data;
|
||
handleChargeItem(val);
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
// 获取收费项目
|
||
function handleChargeItem(id: string) {
|
||
listChargeItem({
|
||
villageId: id,
|
||
status: '0'
|
||
}).then((res) => {
|
||
chargeItems.value = res.rows;
|
||
});
|
||
}
|
||
// 选择楼栋
|
||
function handleChangeBuilding(val: string): void {
|
||
queryParams.value.unitNoId = undefined;
|
||
queryParams.value.houseId = undefined;
|
||
unitList.value = [];
|
||
getHouselistAPI(val).then((res) => {
|
||
unitList.value = res.data.units;
|
||
});
|
||
}
|
||
// 选择 单元
|
||
function handleChangeUnit(val: string) {
|
||
const find = unitList.value.find((item) => item.unitNoId === val);
|
||
houseList.value = [];
|
||
if (find) {
|
||
houseList.value = find.floors;
|
||
}
|
||
}
|
||
// 选择房屋
|
||
function handleChangeHouseNo() {}
|
||
|
||
// 清空缴费时间
|
||
function handleClearPayTime() {
|
||
payTime.value = [];
|
||
}
|
||
// 清空缴费周期
|
||
function handleClearChargePeriod() {
|
||
chargePeriod.value = [];
|
||
}
|
||
// 获取列表
|
||
function getList() {
|
||
loading.value = true;
|
||
queryParams.value.payTimeBegin = payTime.value[0] ? payTime.value[0] : undefined;
|
||
queryParams.value.payTimeEnd = payTime.value[1] ? payTime.value[1] : undefined;
|
||
|
||
queryParams.value.startDate = chargePeriod.value[0] ? chargePeriod.value[0] : undefined;
|
||
queryParams.value.endDate = chargePeriod.value[1] ? chargePeriod.value[1] : undefined;
|
||
billQuery(queryParams.value)
|
||
.then((res) => {
|
||
tableData.value = res.rows;
|
||
total.value = res.total;
|
||
handleSelectBill(res.rows);
|
||
})
|
||
.finally(() => {
|
||
loading.value = false;
|
||
});
|
||
}
|
||
/** 搜索按钮操作 */
|
||
const handleQuery = () => {
|
||
queryParams.value.pageNum = 1;
|
||
getList();
|
||
};
|
||
|
||
/** 重置按钮操作 */
|
||
const resetQuery = () => {
|
||
queryFormRef.value?.resetFields();
|
||
payTime.value = [];
|
||
chargePeriod.value = [];
|
||
queryParams.value = {
|
||
chargePeriod: undefined,
|
||
payTime: undefined,
|
||
pageNum: 1,
|
||
pageSize: 20,
|
||
payStatus: null,
|
||
villageId: undefined,
|
||
buildingId: undefined,
|
||
unitNoId: undefined,
|
||
houseId: undefined,
|
||
chargeItemId: undefined,
|
||
period: undefined,
|
||
houseUseTypeId: undefined,
|
||
residentName: undefined,
|
||
payTimeBegin: undefined,
|
||
payTimeEnd: undefined,
|
||
startDate: undefined,
|
||
endDate: undefined
|
||
};
|
||
queryParams.value.villageId = villageId;
|
||
handleQuery();
|
||
};
|
||
// 控制收费 按钮 不能有已缴纳的(后端会校验)
|
||
const single = ref(true);
|
||
// 控制打印票据的 按钮 不能有收费的
|
||
const printSingle = ref(true);
|
||
/** 多选框选中数据 */
|
||
const handleSelectionChange = (selection: billlistType[]) => {
|
||
ids.value = selection.map((item) => item);
|
||
// 不能全部都是已缴纳的 0待缴纳 1已缴纳 2缴纳失败 3混合缴纳
|
||
single.value = ids.value.every((item) => item.payStatus === '0' || item.payStatus === '3');
|
||
// 必须都要缴费后打印
|
||
printSingle.value = ids.value.every((item) => item.payStatus === '1');
|
||
};
|
||
const buttonLoading = ref(false);
|
||
// 是否多选
|
||
let isMore = false;
|
||
|
||
const inComeFrom = ref({
|
||
allCost: null, // 金额
|
||
billResidentId: [], // 账单id
|
||
/** 0:未缴 1:已缴 2: 缴纳失败 3: 混合缴纳*/
|
||
payStatus: '1',
|
||
/** 0:微信 1:支付宝 2 线下 */
|
||
payType: '0', //
|
||
remark: '', // 备注
|
||
/**优惠方式 0 不优惠 1 比例 2 金额*/
|
||
discountMethod: 0, //
|
||
discountRate: '0', // 优惠比例 10 === 10%
|
||
discount: '0', // 优惠金额
|
||
residentName: '' // 缴费人
|
||
});
|
||
// 总计算优惠金额
|
||
const totalDiscountAmount = ref('0.00');
|
||
// 总实际优惠金额
|
||
const totalReadDiscount = ref('0.00');
|
||
// 总实际支付金额
|
||
const totalPayAmount = ref('0.00');
|
||
|
||
// 初始化
|
||
function initInComeFrom() {
|
||
inComeFrom.value = {
|
||
allCost: 0, // 总金额
|
||
billResidentId: [], // 账单id
|
||
payStatus: '1', // 0:未缴 1:已缴 2: 缴纳失败 3: 部分缴纳
|
||
payType: '2', // 0:微信 1:支付宝 2 线下
|
||
remark: '',
|
||
discountMethod: 0, // 优惠方式 0 不优惠 1 比例 2 金额
|
||
discountRate: '0', // 优惠比例 10 === 10%
|
||
discount: '0', // 优惠金额
|
||
residentName: '' // 缴费人
|
||
};
|
||
totalAll.value = {
|
||
totalDiscountAmount: 0,
|
||
TotalPaymentAmount: 0,
|
||
totalAccount: 0
|
||
};
|
||
payList.value = [
|
||
{
|
||
payType: '',
|
||
payAmount: null
|
||
}
|
||
];
|
||
totalDiscountAmount.value = '0.00';
|
||
totalPayAmount.value = '0.00';
|
||
totalReadDiscount.value = '0.00';
|
||
isMore = false;
|
||
}
|
||
// 改变优惠方式
|
||
function handleChangeDisCountMethod(val: number) {
|
||
inComeFrom.value.discountRate = '0'; // 优惠比例
|
||
inComeFrom.value.discount = '0.00'; // 优惠金额
|
||
totalReadDiscount.value = '0.00'; // 实际优惠金额
|
||
totalDiscountAmount.value = '0.00'; // 总优惠金额
|
||
totalPayAmount.value = inComeFrom.value.allCost; // 总实际付款金额
|
||
if (val === 0) return;
|
||
if (val === 2) {
|
||
// 金额
|
||
handleChangeDiscountMoney(inComeFrom.value.discount);
|
||
} else {
|
||
// 比例
|
||
handleChangeDiscountRate(inComeFrom.value.discount);
|
||
}
|
||
}
|
||
// 输入折扣固定金额
|
||
function handleChangeDiscountMoney(val: string) {
|
||
// 1. 清洗输入:空、纯符号、非数字兜底为0
|
||
const cleanVal = val.trim();
|
||
if (!checkMoney(cleanVal)) {
|
||
return ElMessage.warning('金额格式错误');
|
||
}
|
||
let discount = toBig(cleanVal).toNumber();
|
||
if (Number.isNaN(discount)) discount = 0;
|
||
const allCost = inComeFrom.value.allCost ?? 0;
|
||
if (discount < 0) {
|
||
ElMessage.warning('优惠金额不能为负数');
|
||
return;
|
||
}
|
||
// 折扣为0直接赋值原总价,无需计算
|
||
if (eq(discount, 0)) {
|
||
totalDiscountAmount.value = '0.00';
|
||
totalReadDiscount.value = '0.00';
|
||
totalPayAmount.value = allCost.toString();
|
||
return;
|
||
}
|
||
|
||
if (isMore) {
|
||
// 过滤:只保留未支付账单,已支付直接丢弃
|
||
const unPaidList = ids.value.filter((item) => {
|
||
return item.payStatus !== '1';
|
||
});
|
||
|
||
// 计算优惠总额
|
||
const allDiscount = mul(unPaidList.length, discount);
|
||
if (gtMoney(allDiscount, inComeFrom.value.allCost)) {
|
||
ElMessage.warning('优惠总金额不能超过总费用');
|
||
}
|
||
// 实际优惠总额
|
||
let readDiscount = 0;
|
||
unPaidList.forEach((item) => {
|
||
readDiscount = add(readDiscount, minMoney(item.needPayAmount, discount));
|
||
});
|
||
totalDiscountAmount.value = `${allDiscount}`;
|
||
totalReadDiscount.value = `${readDiscount}`;
|
||
totalPayAmount.value = sub(allCost, readDiscount).toString();
|
||
} else {
|
||
// 单笔优惠不能超过整体总费用
|
||
if (gtMoney(discount, allCost)) {
|
||
ElMessage.warning('单笔优惠金额不能超过总费用');
|
||
}
|
||
totalDiscountAmount.value = discount.toString();
|
||
totalReadDiscount.value = `${discount}`;
|
||
totalPayAmount.value = sub(allCost, discount).toString();
|
||
}
|
||
validatePayAmountSufficiency();
|
||
}
|
||
|
||
const debouncedHandleDiscountMoney = debounce(handleChangeDiscountMoney, 550);
|
||
// 输入折扣固定比例
|
||
function handleChangeDiscountRate(val: string) {
|
||
const inputStr = val.trim();
|
||
let discountPercent = toBig(inputStr).toNumber();
|
||
if (Number.isNaN(discountPercent)) discountPercent = 0;
|
||
|
||
// 百分比校验
|
||
if (discountPercent < 0 || discountPercent > 100) {
|
||
ElMessage.warning('请输入0-100之间的优惠打折百分比');
|
||
return;
|
||
}
|
||
const allCost = inComeFrom.value.allCost ?? 0;
|
||
const rate = div(discountPercent, 100);
|
||
// 1. 输入0:优惠总额为0,全价支付
|
||
if (eq(rate, 0)) {
|
||
totalDiscountAmount.value = '0.00';
|
||
totalReadDiscount.value = '0.00';
|
||
totalPayAmount.value = allCost;
|
||
return;
|
||
}
|
||
// 2. 输入100:全免价格,免费送
|
||
if (eq(rate, 1)) {
|
||
totalDiscountAmount.value = allCost;
|
||
totalReadDiscount.value = allCost;
|
||
totalPayAmount.value = '0.00';
|
||
return;
|
||
}
|
||
// 批量多选模式
|
||
if (isMore) {
|
||
const unPaidList = ids.value.filter((item) => {
|
||
return item.payStatus !== '1';
|
||
});
|
||
// 总价格
|
||
const sourceTotal = sum(unPaidList.map((item) => item.needPayAmount ?? 0));
|
||
// 优惠总额 = 未付原价总和 - 打折后实付总和
|
||
const discountTotal = mul(sourceTotal, rate);
|
||
// 优惠总额
|
||
totalDiscountAmount.value = discountTotal.toString();
|
||
totalReadDiscount.value = `${discountTotal}`;
|
||
totalPayAmount.value = mul(sourceTotal, 1 - rate).toString();
|
||
} else {
|
||
// 单选单条账单
|
||
totalDiscountAmount.value = mul(allCost, rate).toString();
|
||
totalReadDiscount.value = mul(allCost, rate).toString();
|
||
totalPayAmount.value = mul(allCost, 1 - rate).toString();
|
||
}
|
||
validatePayAmountSufficiency();
|
||
}
|
||
const debounceDiscountRate = debounce(handleChangeDiscountRate);
|
||
|
||
function validatePayAmountSufficiency() {
|
||
if (payList.value.length > 0) {
|
||
if (gtMoney(payListAllAmount.value, 0)) {
|
||
payList.value.forEach((item) => (item.payAmount = 0));
|
||
ElMessage.warning(`优惠变更,请重新填写支付金额`);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 收费 --------------------------------------------------------------
|
||
/** 收费 */
|
||
function handleIncome(row: billlistType | false) {
|
||
initInComeFrom();
|
||
if (row) {
|
||
inComeFrom.value.allCost = row.needPayAmount;
|
||
inComeFrom.value.billResidentId = [row];
|
||
inComeFrom.value.remark = row.remark;
|
||
inComeFrom.value.residentName = row.residentName;
|
||
totalPayAmount.value = row.needPayAmount;
|
||
} else {
|
||
if (ids.value.length <= 0) return ElMessage.warning('请选择账单');
|
||
const set = new Set();
|
||
ids.value.forEach((item) => {
|
||
set.add(item.residentId);
|
||
});
|
||
if (ids.value.some((item) => item.payStatus === '1')) {
|
||
return ElMessage.warning('存在已支付账单,请重新选择');
|
||
}
|
||
if (set.size > 1) {
|
||
ElMessage.warning('缴费人不一致,重新选择');
|
||
return;
|
||
} else if (set.size === 1) {
|
||
inComeFrom.value.remark = '';
|
||
inComeFrom.value.residentName = ids.value[0].residentName;
|
||
ids.value.forEach((item) => {
|
||
inComeFrom.value.billResidentId.push(item);
|
||
if (item.payStatus === '0' || item.payStatus === '3') {
|
||
inComeFrom.value.allCost = moneyAdd(inComeFrom.value.allCost || 0, item.needPayAmount);
|
||
}
|
||
});
|
||
totalPayAmount.value = inComeFrom.value.allCost;
|
||
isMore = true;
|
||
}
|
||
}
|
||
dialog.visible = true;
|
||
}
|
||
// 关闭模态框
|
||
const closer = () => {
|
||
dialog.visible = false;
|
||
dialog.title = '';
|
||
initInComeFrom();
|
||
};
|
||
// 提交
|
||
const submitForm = () => {
|
||
if (!handlePayListIsEmpt()) {
|
||
ElMessage.warning('请填写完整支付方式和支付金额');
|
||
return;
|
||
}
|
||
buttonLoading.value = true;
|
||
// 部分缴纳时 不管
|
||
// 已缴纳时 判断 支付金额 和 预计支付金额 是否相等
|
||
if (inComeFrom.value.payStatus === '1') {
|
||
if (!eqMoney(totalPayAmount.value, payListAllAmount.value)) {
|
||
buttonLoading.value = false;
|
||
return ElMessage.warning('支付金额不足,可选择 部分缴纳 方式');
|
||
}
|
||
}
|
||
const obj = {
|
||
'detailsId': inComeFrom.value.billResidentId.map((item) => item.detailsId),
|
||
'payType': inComeFrom.value.payType,
|
||
'payStatus': inComeFrom.value.payStatus,
|
||
discountMethod: inComeFrom.value.discountMethod, //优惠方式: 0不优惠 1 比例 2 金额
|
||
discountRate: inComeFrom.value.discountRate, // 优惠比例(优惠方式为比例时使用,如 10 表示 10%
|
||
singleDiscountAmount: inComeFrom.value.discount, // 单笔优惠金额(优惠方式为金额时使用
|
||
remark: inComeFrom.value.remark,
|
||
payItems: payList.value
|
||
};
|
||
billEdit(obj)
|
||
.then(() => {
|
||
ElMessage.success('缴费成功');
|
||
getList();
|
||
closer();
|
||
})
|
||
.finally(() => {
|
||
buttonLoading.value = false;
|
||
});
|
||
};
|
||
//
|
||
// 打印票据--------------------------------------------------------------
|
||
const isPrint = ref(false);
|
||
const dialog_print = reactive<DialogOption>({
|
||
visible: false,
|
||
title: '票据打印'
|
||
});
|
||
// 收款人
|
||
const inHomelyUse = ref('');
|
||
// 票据表单
|
||
const print_form = ref<BillPrintType>({
|
||
totalDiscountAmount: '',
|
||
totalActualAccount: '',
|
||
'totalAccount': '',
|
||
'residentName': '',
|
||
'detailsList': [],
|
||
'printDate': '',
|
||
'HouseName': '',
|
||
'title': ''
|
||
});
|
||
// 打印票据
|
||
function printPIaoJuByOnly(row: billlistType | false) {
|
||
isPrint.value = false;
|
||
inHomelyUse.value = userStore.nickname;
|
||
let query = null;
|
||
if (row) {
|
||
query = {
|
||
'residentId': row.residentId,
|
||
'detailsIds': [row.detailsId]
|
||
};
|
||
} else {
|
||
if (ids.value.length <= 0) {
|
||
return ElMessage.warning('请选择账单!');
|
||
}
|
||
let residentId = null;
|
||
const set = new Set();
|
||
ids.value.forEach((item) => {
|
||
set.add(item.residentId);
|
||
});
|
||
if (set.size > 1) {
|
||
ElMessage.warning('缴费人不一致,重新选择');
|
||
return;
|
||
} else if (set.size === 1) {
|
||
residentId = Array.from(set).at(0);
|
||
query = {
|
||
'residentId': residentId,
|
||
'detailsIds': ids.value.map((item) => item.detailsId)
|
||
};
|
||
}
|
||
}
|
||
billPrint(query).then((res) => {
|
||
print_form.value = res.data;
|
||
dialog_print.visible = true;
|
||
});
|
||
}
|
||
const isLoading = ref(false);
|
||
const printOption = {
|
||
id: 'printBox-Bill',
|
||
popTitle: '票据打印',
|
||
printStyle: `
|
||
@page {
|
||
size: 25cm 10cm;
|
||
margin: 0;
|
||
}
|
||
* {
|
||
box-sizing: border-box;
|
||
margin: 0 !important;
|
||
padding: 0 !important;
|
||
}
|
||
@media print {
|
||
html {
|
||
height: 10cm !important;
|
||
overflow: hidden !important;
|
||
}
|
||
body {
|
||
height: 10cm !important;
|
||
overflow: hidden !important;
|
||
position: absolute;
|
||
left:0;
|
||
top:0;
|
||
transform-origin: top left;
|
||
transform: scale(0.999);
|
||
}
|
||
#printBox-Bill {
|
||
width: 25cm !important;
|
||
height: 10cm !important;
|
||
}
|
||
table {
|
||
border-collapse: collapse;
|
||
width: 100% !important;
|
||
table-layout: auto;
|
||
}
|
||
table th, table td {
|
||
border: 1px solid #333;
|
||
font-size: 10px;
|
||
min-height: 32px;
|
||
text-align: center;
|
||
padding: 1px 2px;
|
||
line-height: 1.1;
|
||
white-space: normal;
|
||
}
|
||
}
|
||
`,
|
||
afterCloseCallback: () => {
|
||
isPrint.value = false;
|
||
isLoading.value = false;
|
||
}
|
||
};
|
||
// 打印状态恢复函数
|
||
function resetPrintState() {
|
||
isPrint.value = false;
|
||
isLoading.value = false;
|
||
}
|
||
function conFimPrint() {
|
||
isLoading.value = true;
|
||
isPrint.value = true;
|
||
setTimeout(() => {
|
||
// printTicketDiv('printBox-Bill', '票据打印', () => {
|
||
// console.log('打印完成');
|
||
// isPrint.value = false;
|
||
// isLoading.value = false;
|
||
// });
|
||
// printTicket('printBox-Bill', '票据打印', () => {
|
||
// console.log('打印完成');
|
||
// isPrint.value = false;
|
||
// isLoading.value = false;
|
||
// });
|
||
resetPrintState();
|
||
}, 100);
|
||
}
|
||
|
||
onMounted(() => {
|
||
queryParams.value.villageId = villageId;
|
||
getList();
|
||
getHouseTypeList();
|
||
// 全部小区
|
||
getCommunitylistAPI().then((res) => {
|
||
villageList.value = res.rows;
|
||
handleChangeVillage(queryParams.value.villageId);
|
||
});
|
||
});
|
||
|
||
// 总 表单
|
||
const totalAll = ref({
|
||
totalDiscountAmount: 0,
|
||
TotalPaymentAmount: 0,
|
||
totalAccount: 0
|
||
});
|
||
// 多选时 统计总金额,优惠总金额,实付总金额
|
||
function handleSelectBill(val: billlistType[]) {
|
||
totalAll.value.totalAccount = sum(val.map((item) => item.amount ?? 0));
|
||
totalAll.value.TotalPaymentAmount = sum(val.map((item) => item.actualAccount ?? 0));
|
||
totalAll.value.totalDiscountAmount = sum(val.map((item) => item.singleDiscountAmount ?? 0));
|
||
}
|
||
function handleChangePayTypeId(val: string, index: number) {
|
||
// 【可选兜底校验】防止异常数据出现重复
|
||
const repeatCount = usedPayValues.value.filter((v) => v === val).length;
|
||
if (repeatCount > 1) {
|
||
payList.value[index].payType = null;
|
||
}
|
||
}
|
||
const usedPayValues = computed(() => {
|
||
return payList.value.map((item) => item.payType).filter((v) => v !== null && v !== undefined && v !== '');
|
||
});
|
||
const isOptionDisabled = (optVal: string, currentVal: any) => {
|
||
// 当前行自己选中的,不禁用;其他行占用的,禁用
|
||
if (optVal === currentVal) return false;
|
||
return usedPayValues.value.includes(optVal);
|
||
};
|
||
|
||
// 混合支付 列表
|
||
const payList = ref([
|
||
{
|
||
payType: '',
|
||
payAmount: null
|
||
}
|
||
]);
|
||
// 混合支付 总金额
|
||
const payListAllAmount = computed(() => {
|
||
return sum(payList.value.map((item) => item.payAmount ?? 0));
|
||
});
|
||
// 添加支付方式
|
||
function addPayList() {
|
||
payList.value.push({
|
||
payType: '',
|
||
payAmount: null
|
||
});
|
||
}
|
||
// 移除支付方式
|
||
function removePayList(index: number) {
|
||
payList.value.splice(index, 1);
|
||
}
|
||
// 数据框改变时 检测数据是否大于 总金额
|
||
function handleChangePay(val: string, index: number = -1) {
|
||
if (!checkMoney(val)) {
|
||
ElMessage.warning('金额格式错误');
|
||
payList.value[index].payAmount = null;
|
||
return;
|
||
}
|
||
if (gtMoney(payListAllAmount.value, totalPayAmount.value)) {
|
||
ElMessage.warning('输入金额 总和 不能大于 总实缴金额');
|
||
if (index > -1) {
|
||
payList.value[index].payAmount = 0;
|
||
// 自动回填
|
||
payList.value[index].payAmount = sub(totalPayAmount.value, payListAllAmount.value);
|
||
}
|
||
}
|
||
// 已缴纳状态时,输入金额 总和 不能小于 总实缴金额
|
||
if (inComeFrom.value.payStatus === '1') {
|
||
if (ltMoney(payListAllAmount.value, totalPayAmount.value)) {
|
||
ElMessage.warning('输入金额 总和 不能小于 总实缴金额');
|
||
}
|
||
}
|
||
}
|
||
|
||
function handlePayListIsEmpt() {
|
||
if (payList.value.length === 0) {
|
||
ElMessage.warning('请添加支付方式');
|
||
return false;
|
||
}
|
||
const invalidIndex = payList.value.findIndex(
|
||
(item) =>
|
||
item.payType === null ||
|
||
item.payType === undefined ||
|
||
item.payType === '' ||
|
||
item.payAmount === null ||
|
||
item.payAmount === undefined ||
|
||
item.payAmount === ''
|
||
);
|
||
if (invalidIndex !== -1) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 校验数字
|
||
function checkMoney(value: string) {
|
||
if (!value) return false;
|
||
const reg = /^(0|[1-9]\d*)(\.\d{1,2})?$/;
|
||
return reg.test(value);
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.DiscountColorRed {
|
||
color: red;
|
||
}
|
||
|
||
.el-table {
|
||
height: calc(100% - 80px);
|
||
}
|
||
.actionsBox {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
background-color: #fff;
|
||
height: 50px;
|
||
box-sizing: border-box;
|
||
padding: 0 20px;
|
||
margin-bottom: 10px;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.tabs-box {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.tabs-items {
|
||
width: 70px;
|
||
height: 40px;
|
||
line-height: 40px;
|
||
border-bottom: 2px solid transparent;
|
||
text-align: center;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
margin-right: 10px;
|
||
|
||
&:hover {
|
||
opacity: 0.5;
|
||
color: #1a75ff;
|
||
border-bottom-color: #1a75ff;
|
||
}
|
||
&.active {
|
||
border-bottom-color: #1a75ff;
|
||
color: #1a75ff;
|
||
}
|
||
}
|
||
}
|
||
.payInfo {
|
||
color: rgba(0, 0, 0, 1);
|
||
margin-top: 20px;
|
||
padding-bottom: 10px;
|
||
margin-bottom: 30px;
|
||
border-bottom: 1px solid #d2d2d2;
|
||
& > div {
|
||
margin-bottom: 10px;
|
||
}
|
||
}
|
||
|
||
.printBox {
|
||
.tableBox {
|
||
.printTable {
|
||
th,
|
||
td {
|
||
text-align: center;
|
||
height: 40px;
|
||
border: 1px solid #000;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.footerBox {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
.totalBox {
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
</style>
|