alipay-emulator/pages/other/card/card.vue

588 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 自定义头部导航栏 -->
<ZdyNavbar @right-click="edit" isRightButton rightButtonText="编辑" :title="data.navbar.title"
:bgColor="data.navbar.bgColor" :isBack="true" />
<image :src="data.code" mode="widthFix" style="width: 100vw;" @click="previewImage"></image>
<view class="button-container">
<button class="btn-save-image" @click="saveImage">保存图片</button>
</view>
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress" hidden
:css="`width:${data.width}px;height:${data.height }px;background-color:#fff;`">
<l-painter-view
:css="`margin-top:116px;margin-left:75px;position: relative;width:650px;height:360px;background-image: url('/static/image/other/card/cardBGImg.png');background-size:650px 360px;`">
<!-- 头部年月 -->
<l-painter-view :css="`position: absolute;left:122px;top:28px;`">
<l-painter-text :css="data.textCss+data.textCssLeft" :text="data.form.name" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:122px;top:78px;`">
<l-painter-text :css="data.textCss2+data.textCssLeft" :text="data.form.gender" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:254px;top:78px;`">
<l-painter-text :css="data.textCss2+data.textCssLeft" :text="data.form.nation" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:122px;top:126px;`">
<l-painter-text v-for="(item,index) in data.form.year.toString()" :css="data.textCss3+data.textCssLeft" :text="item" :key="index" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:184px;top:126px;`">
<l-painter-text :css="data.textCss2+data.textCssCenter" :text="data.form.month.toString()" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:244px;top:126px;`">
<l-painter-text :css="data.textCss2+data.textCssCenter" :text="data.form.day.toString()" />
</l-painter-view>
<l-painter-view :css="`position: absolute;left:122px;top:177px;width:274px;`">
<l-painter-text v-for="(item,index) in data.form.address" :css="data.textCss3+data.textCssLeft" :text="item" :key="index"/>
</l-painter-view>
<l-painter-view :css="`position: absolute;left:223px;top:300px;`">
<l-painter-text v-for="(item,index) in data.form.idNumber" :css="data.textCss4+data.textCssLeft" :text="item" :key="index"/>
</l-painter-view>
<l-painter-view :css="`position: absolute;right:48px;top:55px;`">
<l-painter-image v-if="data.form.photo" :src="data.form.photo" css="width: 196px; height: 230px;"/>
<l-painter-view v-else css="width: 196px; height: 230px;background-color:#fff;">
</l-painter-view>
</l-painter-view>
<l-painter-view v-if="$isVip()" :css="`position: absolute;left:535px;bottom:-78px;`">
<l-painter-image src="/static/image/other/card/shuiyin2.png" css="width: 170px;height: 50px;" />
</l-painter-view>
</l-painter-view>
</l-painter>
<!-- 编辑弹窗 -->
<view v-if="showEditPopup" class="popup-overlay">
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">编辑身份证</text>
<text class="popup-close" @click="closeEditPopup">×</text>
</view>
<view class="popup-body">
<view class="form-row">
<text class="form-label">姓名:</text>
<input class="form-input" v-model="editForm.name" type="text" />
</view>
<view class="form-row">
<text class="form-label">性别:</text>
<input class="form-input" v-model="editForm.gender" type="text" />
</view>
<view class="form-row">
<text class="form-label">民族:</text>
<input class="form-input" v-model="editForm.nation" type="text" />
</view>
<view class="form-row">
<text class="form-label">出生日期:</text>
<input class="form-input" v-model="editForm.year" type="number" style="width: 100px;" />
<text class="form-separator">-</text>
<input class="form-input" v-model="editForm.month" type="number" style="width: 80px;" />
<text class="form-separator">-</text>
<input class="form-input" v-model="editForm.day" type="number" style="width: 80px;" />
</view>
<view class="form-row">
<text class="form-label">住址:</text>
<input class="form-input" v-model="editForm.address" type="text" />
</view>
<view class="form-row">
<text class="form-label">身份证号:</text>
<input class="form-input" v-model="editForm.idNumber" type="text" />
</view>
<view class="form-row">
<text class="form-label">照片:</text>
<view class="upload-container">
<image v-if="editForm.photo" :src="editForm.photo" class="upload-image" @click="chooseImage" />
<view v-else class="upload-btn" @click="chooseImage">
<text class="upload-text">点击上传照片</text>
</view>
</view>
</view>
</view>
<view class="popup-footer">
<button class="btn-cancel" @click="closeEditPopup">取消</button>
<button class="btn-save" @click="saveEditForm">保存</button>
</view>
</view>
</view>
</view>
</template>
<script setup>
// 自定义头部
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
import {
ref,
reactive,
watch,
nextTick,
getCurrentInstance
} from "vue";
import {
onLoad,
onShow,
onReady,
onPullDownRefresh,
onReachBottom
} from "@dcloudio/uni-app";
const {
appContext,
proxy
} = getCurrentInstance();
const data = reactive({
navbar: {
title: "身份证",
bgColor: '#EDEDED',
},
width: 800,
height: 600,
code: '',
form: {
name: '李某',
gender: '男',
nation: '汉',
year: 2025,
month: 2,
day: 1,
address: '翻斗大街翻斗花园二号楼1001室',
idNumber: '500000000000000000',
photo: '',
},
textCss: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:100px;color:#3D3D3D;font-size:24px; mix-blend-mode: overlay;',
textCss2: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:100px;text-align: left;color:#3D3D3D;font-size:22px;mix-blend-mode: overlay;',
textCss3: 'word-spacing: 10px;letter-spacing: 10px;margin-right:2px;font-family: "SimHei", "Microsoft YaHei", sans-serif;text-align: left;color:#3D3D3D;font-size:22px;mix-blend-mode: overlay;',
textCss4: 'word-spacing: 10px;margin-right:3px;letter-spacing: 10px;font-family: "card", "Microsoft YaHei", sans-serif;text-align: left;color:#1a1a1a;font-size:28px;mix-blend-mode: overlay;display:flex;',
textCssLeft:'text-align: left;',
textCssCenter:'text-align: center;'
})
// 弹窗相关
const showEditPopup = ref(false);
const editForm = ref({});
//
function successImage(e){
data.code=e
}
function progress(e){
if(e<0.03){
uni.showLoading({
title:"生成中"
})
}
if(e==1){
uni.hideLoading()
}
console.log(e)
}
// 打开编辑弹窗
function edit() {
console.log(data.form)
// 复制当前表单数据到编辑表单
editForm.value = JSON.parse(JSON.stringify(data.form));
// 显示弹窗
showEditPopup.value = true;
}
// 关闭编辑弹窗
function closeEditPopup() {
showEditPopup.value = false;
}
// 保存编辑表单
function saveEditForm() {
// 将编辑后的数据复制回原始表单
data.form = JSON.parse(JSON.stringify(editForm.value));
// 关闭弹窗
showEditPopup.value = false;
}
// 选择图片
function chooseImage() {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
editForm.value.photo = res.tempFilePaths[0];
},
fail: (err) => {
console.log('选择图片失败', err);
}
});
}
// 预览图片
function previewImage() {
if (data.code) {
uni.previewImage({
urls: [data.code],
current: 0
});
}
}
// 保存图片
function saveImage() {
if (data.code) {
console.log(data.code)
uni.showLoading({
title: '保存中...'
});
try {
// 检查是否为base64格式
if (data.code.startsWith('data:image')) {
// 处理base64格式图片
console.log('开始处理base64图片');
uni.base64ToTempFile({
base64: data.code.split(',')[1], // 去除base64前缀
success: (res) => {
console.log('base64转换成功', res);
if (res.tempFilePath) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
console.log('保存图片成功');
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success'
});
},
fail: (err) => {
console.log('保存图片失败', err);
uni.hideLoading();
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
});
} else {
console.log('base64转换失败无临时文件路径');
uni.hideLoading();
uni.showToast({
title: '转换失败',
icon: 'none'
});
}
},
fail: (err) => {
console.log('base64转换失败', err);
uni.hideLoading();
uni.showToast({
title: '转换失败',
icon: 'none'
});
}
});
} else if (data.code.startsWith('_') || data.code.includes('temp') || data.code.includes('cache') || data
.code.includes('_doc') || data.code.includes('_tmp')) {
// 处理本地临时文件
console.log('开始处理本地临时文件');
uni.saveImageToPhotosAlbum({
filePath: data.code,
success: () => {
console.log('保存本地文件成功');
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success'
});
},
fail: (err) => {
console.log('保存本地文件失败', err);
uni.hideLoading();
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
});
} else {
// 处理网络图片
console.log('开始处理网络图片');
uni.downloadFile({
url: data.code,
success: (res) => {
console.log('下载图片成功', res);
if (res.statusCode === 200 && res.tempFilePath) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
console.log('保存图片成功');
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success'
});
},
fail: (err) => {
console.log('保存图片失败', err);
uni.hideLoading();
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
});
} else {
console.log('下载图片失败,状态码:', res.statusCode);
uni.hideLoading();
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
},
fail: (err) => {
console.log('下载图片失败', err);
uni.hideLoading();
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
});
}
} catch (error) {
console.log('保存图片异常', error);
uni.hideLoading();
uni.showToast({
title: '保存失败',
icon: 'none'
});
}
} else {
uni.showToast({
title: '暂无图片可保存',
icon: 'none'
});
}
}
onLoad((option) => {
// 进入身份证页面埋点
proxy.$apiUserEvent('all', {
type: 'event',
key: 'idcard',
prefix: '.uni.other.',
value: "身份证"
})
})
onReady(() => {
})
onShow(() => { })
onPullDownRefresh(() => {
setTimeout(() => {
uni.stopPullDownRefresh();
}, 1000);
})
onReachBottom(() => {
})
</script>
<style lang="scss" scoped>
@font-face {
font-family: "card";
src: url("/static/font/card.ttf");
}
* {
box-sizing: content-box;
}
.aadadad {
text-align: center;
}
.heiti {
font-family: "SimHei", "Microsoft YaHei", sans-serif;
}
/* 弹窗样式 */
.popup-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.popup-content {
background-color: #fff;
border-radius: 10px;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
.popup-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.popup-close {
font-size: 48rpx;
color: #999;
cursor: pointer;
}
.popup-body {
padding: 20rpx;
}
.form-section {
margin-bottom: 30rpx;
padding: 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
}
.section-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: block;
}
.form-row {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.form-label {
width: 200rpx;
font-size: 26rpx;
color: #333;
}
.form-input {
flex: 1;
padding: 15rpx;
border: 1rpx solid #ddd;
border-radius: 4rpx;
font-size: 26rpx;
}
.form-separator {
margin: 0 10rpx;
font-size: 26rpx;
color: #333;
}
.form-total {
margin-top: 10rpx;
padding-top: 10rpx;
border-top: 1rpx dashed #ddd;
}
.form-total-input {
background-color: #f9f9f9;
color: #ff6b35;
font-weight: bold;
}
/* 上传图片样式 */
.upload-container {
flex: 1;
position: relative;
}
.upload-btn {
width: 120rpx;
height: 160rpx;
border: 1rpx dashed #ddd;
border-radius: 8rpx;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f5f5;
}
.upload-text {
font-size: 22rpx;
color: #999;
text-align: center;
}
.upload-image {
width: 120rpx;
height: 160rpx;
border-radius: 8rpx;
object-fit: cover;
}
.popup-footer {
display: flex;
justify-content: space-between;
padding: 20rpx;
border-top: 1rpx solid #eee;
}
.btn-cancel,
.btn-save {
width: 48%;
padding: 20rpx;
border-radius: 4rpx;
font-size: 28rpx;
}
.btn-cancel {
background-color: #f5f5f5;
color: #333;
border: 1rpx solid #ddd;
}
.btn-save {
background-color: #ff6b35;
color: #fff;
border: none;
}
/* 保存图片按钮 */
.button-container {
display: flex;
justify-content: center;
padding: 30rpx 0;
}
.btn-save-image {
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
color: #fff;
border: none;
padding: 18rpx 60rpx;
border-radius: 40rpx;
font-size: 26rpx;
font-weight: bold;
box-shadow: 0 3rpx 10rpx rgba(7, 66, 193, 0.3);
transition: all 0.3s ease;
text-align: center;
min-width: 160rpx;
}
.btn-save-image:hover {
transform: translateY(-2rpx);
box-shadow: 0 4rpx 12rpx rgba(7, 72, 193, 0.4);
}
.btn-save-image:active {
transform: translateY(0);
box-shadow: 0 2rpx 6rpx rgba(7, 140, 193, 0.3);
}
</style>