vue3-print-nb的使用,点击回调
1. 安装
npm install vue3-print-nb --save
2. main.js引入
import print from 'vue3-print-nb' // 打印插件
app.use(print)
main引入报ts错误,可在env.d.ts里配置以下代码
declare module "vue3-print-nb";
3. 页面使用(代码可直接复制)
- 注意:打印匹配纸张需要以百分比进行匹配,即设计稿元素里子元素占父级的百分比
<template>
<el-dialog v-model="isShowPrint" destroy-on-close top="5vh" width="700" :before-close="cancelClick">
<div class="print">
<el-tabs tab-position="top" type="card" class="demo-tabs" v-model="activeTab">
<el-tab-pane label="男生模板" :name="1">
<div id="template1" v-loading="printLoading">
<div class="template_1">
<div class="profile-card">
<img class="" src="@/assets/images/posterMaleBg.png" alt="" srcset="">
<div class="card-content">
<img v-show="radio == 1" class="avatar" :src="logo" alt="logo" />
<img v-show="radio == 2" class="avatar" :src="male" alt="卡通头像" />
<img v-show="radio == 3" class="avatar real-avatar" :src="userDetail.avatar"
alt="真人头像" />
<div class="user-info">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab nick-name-lab">昵称</div>
<div class="details-val nick-name"> {{ userDetail.nick_name }} </div>
</div>
<div class="details row-right">
<div class="details-lab">年龄</div>
<div class="details-val">
<span>{{ userDetail.age }}岁</span>
<span class="birthday">({{ userDetail.birthday }}年)</span>
</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab">学历</div>
<div class="details-val">{{ userDetail.qualification }}</div>
</div>
<div class="details row-right">
<div class="details-lab"> 身高</div>
<div class="details-val">{{ userDetail.height }}</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab">职业</div>
<div class="details-val">{{ userDetail.occupation }}</div>
</div>
<div class="details row-right">
<div class="details-lab">年收入</div>
<div class="details-val">{{ userDetail.income }}</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div v-if="userDetail.city_name && userDetail.city_name.length > 7 ? true : false"
class="details row-left ">
<div class="details-lab city-lab">期望城市</div>
<div class="details-val city-val">{{ userDetail.city_name }}</div>
</div>
<div v-else class="details row-left">
<div class="details-lab">期望城市</div>
<div class="details-val">{{ userDetail.city_name }}</div>
</div>
<!-- 家乡 -->
<div v-if="userDetail.home_city_name && userDetail.home_city_name.length > 6 ? true : false"
class="details row-right">
<div class="details-lab hometown-lab">家乡</div>
<div class="details-val hometown-val">{{ userDetail.home_city_name }}
</div>
</div>
<div v-else-if="userDetail.home_city_name" class="details row-right">
<div class="details-lab">家乡</div>
<div class="details-val">{{ userDetail.home_city_name }}</div>
</div>
</div>
</div>
<div class="expectations">
<div>{{ userDetail.age_min }}-{{ userDetail.age_max }}岁</div>
<div>身高{{ userDetail.height_min }}-{{ userDetail.height_max }}cm</div>
<div> {{ userDetail.m_qualification }}</div>
</div>
<div class="code_container">
<img class="code_img" :src="qrCodeUrl" alt="二维码" />
<div class="qr_code_content">微信扫一扫,立刻认识ta</div>
</div>
</div>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="女生模板" :name="2">
<div id="template2" v-loading="printLoading">
<div class="template_1">
<div class="profile-card">
<img class="" src="@/assets/images/posterFemaleBg.png" alt="" srcset="">
<div class="card-content">
<img v-show="radio == 1" class="avatar" :src="logo" alt="logo" />
<img v-show="radio == 2" class="avatar" :src="female" alt="卡通头像" />
<img v-show="radio == 3" class="avatar real-avatar" :src="userDetail.avatar"
alt="真人头像" />
<div class="user-info">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab nick-name-lab">昵称</div>
<div class="details-val nick-name"> {{ userDetail.nick_name }} </div>
</div>
<div class="details row-right">
<div class="details-lab">年龄</div>
<div class="details-val">
<span>{{ userDetail.age }}岁</span>
<span class="birthday">({{ userDetail.birthday }}年)</span>
</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab">学历</div>
<div class="details-val">{{ userDetail.qualification }}</div>
</div>
<div class="details row-right">
<div class="details-lab"> 身高</div>
<div class="details-val">{{ userDetail.height }}</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div class="details row-left">
<div class="details-lab">职业</div>
<div class="details-val">{{ userDetail.occupation }}</div>
</div>
<div class="details row-right">
<div class="details-lab">年收入</div>
<div class="details-val">{{ userDetail.income }}</div>
</div>
</div>
<img class="line" src="@/assets/images/line.png" alt="">
<div class="user-info-row">
<div v-if="userDetail.city_name && userDetail.city_name.length > 7 ? true : false"
class="details row-left ">
<div class="details-lab city-lab">期望城市</div>
<div class="details-val city-val">{{ userDetail.city_name }}</div>
</div>
<div v-else class="details row-left">
<div class="details-lab">期望城市</div>
<div class="details-val">{{ userDetail.city_name }}</div>
</div>
<!-- 家乡 -->
<div v-if="userDetail.home_city_name && userDetail.home_city_name.length > 6 ? true : false"
class="details row-right">
<div class="details-lab hometown-lab">家乡</div>
<div class="details-val hometown-val">{{ userDetail.home_city_name }}
</div>
</div>
<div v-else-if="userDetail.home_city_name" class="details row-right">
<div class="details-lab">家乡</div>
<div class="details-val">{{ userDetail.home_city_name }}</div>
</div>
</div>
</div>
<div class="expectations">
<div>{{ userDetail.age_min }}-{{ userDetail.age_max }}岁</div>
<div>身高{{ userDetail.height_min }}-{{ userDetail.height_max }}cm</div>
<div> {{ userDetail.m_qualification }}</div>
</div>
<div class="code_container">
<img class="code_img" :src="qrCodeUrl" alt="二维码" />
<div class="qr_code_content">微信扫一扫,立刻认识ta</div>
</div>
</div>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
<div class="footer">
<div class="footer-left">
<el-radio-group v-model="radio" @change="radioChange">
<el-radio :value="1">logo</el-radio>
<el-radio :value="2">卡通头像</el-radio>
<el-radio :value="3">真人头像</el-radio>
</el-radio-group>
</div>
<div class="footer-right">
<el-button v-show="activeTab == 1" type="primary" size="small" v-print="printMaleObj">去打印</el-button>
<el-button v-show="activeTab == 2" type="primary" size="small" v-print="printFemaleObj">去打印</el-button>
<el-button size="small" @click="cancelClick">取消</el-button>
</div>
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import { userQrCode, getUserDetail } from '@/api/userManage/user';
import useLayOutSettingStore from '@/stores/modules/setting'
import { getChoose } from '@/utils/choose'
const props = defineProps({
id: {
type: String,
required: true
},
logo: {
type: String,
required: true
},
male: {
type: String,
required: true
},
female: {
type: String,
required: true
},
gender: {
type: Number,
required: true
}
});
let settingStore = useLayOutSettingStore();
const isShowPrint = ref(true);
const activeTab = ref(props.gender);
const emit = defineEmits(['cancel']);
const radio = ref(1)
const userDetail = reactive<any>({});
// 获取用户详情
const Choose = new getChoose();
const getDetail = async () => {
settingStore.loading = true
const { data } = await getUserDetail({ user_id: props.id });
Object.assign(userDetail, data)
userDetail.height = Choose.getHeightList(userDetail.height)
userDetail.income = Choose.getAllStatus(userDetail.income, Choose.income)
userDetail.qualification = Choose.getAllStatus(userDetail.qualification, Choose.qualification)
if (!userDetail.m_qualification) {
userDetail.m_qualification = '学历不限'
} else if (userDetail.m_qualification == '1') {
userDetail.m_qualification = Choose.getAllStatus(userDetail.m_qualification, Choose.qualification)
} else {
userDetail.m_qualification = Choose.getAllStatus(userDetail.m_qualification, Choose.qualification) + '及以上'
}
if (userDetail.nick_name.length > 8) {
userDetail.nick_name = userDetail.nick_name.slice(0, 8) + '...'
}
userDetail.birthday = userDetail.birthday.slice(2, 4)
};
// 获取二维码
const qrCodeUrl = ref<any>('');
const getCodeData = async () => {
const { data }: any = await userQrCode({ user_id: props.id });
qrCodeUrl.value = data.qr_code_to_user;
};
const cancelClick = () => {
emit('cancel');
};
onMounted(() => {
getDetail();
getCodeData();
});
const radioChange = (val: number) => {
radio.value = val;
};
// 打印
const printLoading = ref(false)
const printMaleObj = ref({
id:'template1',
popTitle: 'good print',
extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
beforeOpenCallback(vue:any) {
printLoading.value = true
},
openCallback(vue:any) {
printLoading.value = false
},
})
const printFemaleObj = ref({
id:'template2',
popTitle: 'good print',
extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
beforeOpenCallback(vue:any) {
printLoading.value = true
},
openCallback(vue:any) {
printLoading.value = false
},
})
</script>
<style scoped lang="scss">
@page {
size: auto;
margin: 0mm;
}
@mixin template_1 {
display: flex;
align-items: center;
justify-content: center;
.profile-card {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-between;
.poster-bg {
width: 100%;
height: 100%;
object-fit: contain;
}
.card-content {
width: 100%;
height: 100%;
.avatar {
position: absolute;
top: 19%;
left: 15%;
width: 25%;
height: 17%;
border-radius: 8%;
}
.real-avatar {
object-fit: cover;
}
.user-info {
position: absolute;
top: 35%;
left: 12%;
width: 75.6%;
height: 26.6%;
padding: 0 5%;
display: flex;
flex-direction: column;
.user-info-row {
width: 100%;
display: flex;
justify-content: space-between;
margin: 4% 0;
font-family: PingFangSC, PingFang SC;
.details {
display: flex;
line-height: 100%;
.details-lab {
font-size: 14px;
color: #666;
}
.details-val {
flex: 1;
font-size: 14px;
color: #333;
font-weight: 580;
.birthday {
color: #666666;
margin-left: 5%;
font-weight: 400;
}
}
.nick-name-lab {
width: 17.1%;
}
.city-lab {
width: 34.1%;
}
.city-val {
line-height: 100%;
}
.hometown-lab {
width: 22%;
}
}
.row-left {
width: 55.7% !important;
.details-val {
margin-left: 4%;
}
}
.row-right {
flex: 1;
.details-val {
margin-left: 6%;
}
}
}
.user-info-row:nth-child(1) {
margin-top: 7.3%;
}
.user-info-row:nth-child(4) {
margin-bottom: 0;
}
.line {
width: 100%;
height: 1px;
}
}
.expectations {
position: absolute;
left: 16.8%;
bottom: 15.7%;
width: 34.4%;
height: 11.8%;
display: flex;
flex-direction: column;
justify-content: space-around;
font-size: 14px;
font-weight: 400;
color: #333;
}
.code_container {
position: absolute;
height: 20.7%;
width: 25%;
bottom: 13.5%;
right: 16%;
display: flex;
flex-direction: column;
text-align: center;
.code_img {
height: 77%;
width: 93%;
}
.qr_code_content {
font-size: 10px;
font-weight: 580;
margin-top: 10%;
color: #333333;
}
}
}
}
}
@mixin template_2 {}
.print {
.template_1 {
@include template_1;
.profile-card {
position: relative;
width: 450px;
height: 636px;
}
}
}
.footer {
display: flex;
justify-content: space-between;
padding: 15px;
}
@media print {
.template_1 {
@include template_1;
.profile-card {
position: relative;
width: 1800px;
height: 100vh;
.user-info {
top: 36% !important;
.user-info-row {
margin: 5% 0 !important;
.details-lab {
font-size: 1.5rem !important;
}
.details-val {
font-size: 1.5rem !important;
}
.city-lab {
width: 34% !important;
}
.city-val {
line-height: 120% !important;
margin-left: 3.5% !important;
transform: translateY(-12%);
}
.hometown-val {
line-height: 120% !important;
transform: translateY(-10%);
}
}
}
.expectations {
font-size: 1.5rem !important;
}
.qr_code_content {
font-size: 1rem !important;
}
}
}
}
</style>
4. 父级组件使用
<template>
<PrintUser v-if="isShowPrint" :id="id" :logo :male :female :gender="gender" @cancel="printCancel"/>
</template>
<script setup lang="ts">
import logo from '@/assets/images/logo.png'
import male from '@/assets/images/male.png'
import female from '@/assets/images/female.png'
const id = ref<string>('')
const isShowPrint = ref<boolean>(false)
const gender = ref<any>(1)
const showPrintUser = (row: any) => {
isShowPrint.value = true
id.value = row.user_id
gender.value = row.gender
}
const printCancel = ()=>{
isShowPrint.value = false
}
</script>