初始版本,目前线上可用

This commit is contained in:
2025-11-19 12:49:16 +08:00
commit cb7f1c45e8
178 changed files with 30336 additions and 0 deletions

View File

@@ -0,0 +1,304 @@
<!-- PrintTemplate.vue -->
<template>
<div>
<base-dialog v-model="showPrint" title="打印预览" wdith="210mm">
<div v-loading="showLoading" element-loading-text="正在准备打印数据...">
<div ref="printContainer" class="print-container" id="print-container">
<!-- 告知书部分 -->
<div class="title">文明节俭治丧告知书</div>
<div class="content">尊敬的服务对象</div>
<div class="content" style="text-indent: 7rem">
您好感谢您的信任选择到我司办理治丧业务为深化殡葬改革推进移风易俗现就推行文明节俭治丧有关事宜向您倡导如下
</div>
<div
class="content"
style="text-indent: 5rem; padding-right: 15px"
id="first-content">
文明治丧节俭办事革除陈规陋习抵制封建迷信提倡厚养薄葬弘扬精神美德
</div>
<div class="content" style="text-indent: 5rem; padding-right: 15px">
我司为满足个性化需求提供优质的非基本服务和丧葬用品请您在自主选择时杜绝铺张浪费树立文明新风
</div>
<!-- 服务清单表格 -->
<div class="title">殡仪服务项目清单</div>
<table class="service-table service-table-header">
<tr>
<td style="width: 60pt">逝者姓名</td>
<td style="width: 90pt">
{{ deceased.name || deceased.deceased?.name }}
</td>
<td style="width: 60pt">逝者年龄</td>
<td style="width: 70pt">
{{ deceased.age ?? deceased.deceased?.age }}
</td>
<td style="width: 50pt">购买人</td>
<td style="width: 80pt">
{{ deceased.familyName || deceased.deceased?.familyName }}
</td>
<td style="width: 80pt">购买人电话</td>
<td>
{{ deceased.familyPhone ?? deceased.deceased?.familyPhone }}
</td>
</tr>
</table>
<table class="service-table">
<thead>
<tr>
<th style="width: 40pt">序号</th>
<th style="width: 80pt">服务项目</th>
<th style="width: 35pt">单位</th>
<th style="width: 35pt">数量</th>
<th style="width: 60pt">收费标准</th>
<th style="width: 60pt">小计</th>
<th colspan="3">备注</th>
</tr>
</thead>
<tr v-for="(item, index) in services" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
<td>{{ item.unit }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }}</td>
<td>{{ (item.quantity * item.price).toFixed(2) }}</td>
<td colspan="3">{{ item.remark }}</td>
</tr>
<tr>
<td colspan="5">总计{{ total }}</td>
<td colspan="2">服务引导员</td>
<td style="width: 125pt">
{{ deceased.guide || deceased.deceased?.guide }}
</td>
<td style="width: 125px">家属签字</td>
</tr>
</table>
<table class="service-table service-table-footer">
<tr>
<td style="width: 60pt">消费确认</td>
<td>
<div>
<span
class="confirm-text no-border"
v-for="text in confirmText">
{{ text }}
</span>
</div>
<div>
<span class="confirm-text" v-for="text in confirmText2">
{{ text }}
</span>
<span class="confirm-text"></span>
<span
class="confirm-text"
style="position: relative; top: 5px"></span>
<span
class="confirm-text"
style="position: relative; top: 5px"></span>
<span
class="confirm-text"
style="position: relative; top: 5px"></span>
<span class="confirm-text"></span>
</div>
</td>
<td style="width: 125px"></td>
</tr>
</table>
<div style="width: 100%; text-align: right">
服务时间{{ deceased.retail.checkoutDate.split(" ")[0] }}
</div>
<!-- 打印按钮 -->
</div>
<button class="print-btn" v-print="print">打印单据</button>
</div>
</base-dialog>
</div>
</template>
<script setup lang="ts">
import { defaultRetail } from "@/defaultForm/defaultRetail";
import { computed, nextTick, onMounted, ref, watch } from "vue";
import api from "@/lib/request";
let printContainer = ref();
let showLoading = ref(true);
const print = {
id: "print-container",
beforeOpenCallback: () => {
showLoading.value = true;
},
closeCallback() {
showLoading.value = false;
},
};
let services = ref([]);
let total = computed(() => {
const sum = services.value.reduce((sum, item) => {
return sum + parseFloat(parseFloat(item.price).toFixed(2)) * item.quantity;
}, 0);
return parseFloat(sum.toFixed(2)).toFixed(2); // 最终结果保留两位小数
});
let confirmText = "以上消费项目我已经认真审核,无异议。";
let confirmText2 = "以上消费项目我已经认真审核";
let props = withDefaults(
defineProps<{
deceased: RegisForm;
serviceUrl: string;
}>(),
{
deceased: () => defaultRetail(),
serviceUrl: "/deceased-retail/selected-service",
}
);
let showPrint = defineModel();
watch(
() => showPrint.value,
() => {
showLoading.value = true;
api()
.get(props.serviceUrl)
.then((res) => {
if (res.code === 200) {
showLoading.value = false;
services.value = res.data.list;
}
});
},
{
deep: true,
immediate: true,
}
);
</script>
<style scoped lang="scss">
.service-table-header {
tr td {
border-bottom: none !important;
page-break-inside: avoid;
}
margin-bottom: -10pt !important;
}
.service-table-footer {
tr td {
border-top: none !important;
page-break-inside: avoid;
}
margin-top: -10pt !important;
}
/* 基础样式 */
.print-container {
width: 230mm;
margin: 0 auto;
font-size: 14pt;
color: #000 !important;
font-family: Microsoft YaHei, "SimSun", serif !important;
padding: 0 5mm;
box-sizing: border-box; /* 包含边框计算 */
size: auto;
/* 移除可能引起居中的属性 */
display: block !important;
align-items: unset !important;
justify-content: unset !important;
}
.title {
font-size: 20pt;
text-align: center;
margin-top: 5pt;
font-weight: bold;
}
.service-table {
width: 100%;
border-collapse: collapse;
margin: 10pt 0;
td,
th {
border: 1pt solid #000; // 使用pt单位
padding: 0.8mm 1.2mm; // 使用mm单位
font-size: 10.5pt;
line-height: 1.5;
text-align: center;
}
}
.total {
font-weight: bold;
margin: 20px 0;
text-align: right;
}
.print-btn {
display: block;
width: 120px;
margin: 30px auto;
padding: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* 打印媒体查询 */
@media print {
/* 重置body和html的布局方式 */
body,
html {
display: block !important;
height: auto !important;
margin: 0 !important;
padding: 0 !important;
}
/* 确保打印容器从顶部开始 */
.print-container {
min-height: 297mm; /* A4纸高度 */
display: block !important;
vertical-align: top !important;
position: relative;
top: 0;
transform: none !important;
}
@page {
padding: 0 !important;
margin: 0 !important;
}
/* 移除可能存在的flex布局影响 */
.el-dialog__wrapper,
.el-dialog,
.el-dialog__body {
display: block !important;
height: auto !important;
}
/* 移除对话框的padding */
:deep(.el-dialog__body) {
padding: 0 !important;
}
}
.confirm-text {
border: 1px solid #000;
margin: 0 3px;
display: inline-block;
width: 20px;
height: 20px;
line-height: 18px;
}
.no-border {
border: 1px solid #fff;
}
:deep(.base-dialog .el-dialog__header) {
padding-bottom: none;
}
</style>