You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
6.9 KiB

<template>
<div>
<ul class="nav nav-pills">
<li class="nav-item">
<a class="nav-link" :class="{ active: !showCardType }" href="javascript:void(0)"
@click="showCardType = 0">正面</a>
</li>
<li class="nav-item">
<a class="nav-link" :class="{ active: showCardType }" href="javascript:void(0)"
@click="showCardType = 1">反面</a>
</li>
</ul>
<div class="card-preview">
<div class="front" v-show="showCardType === 0">
<!-- <img class="front-bg" src="@/assets/images/card/front.png"> -->
<div class="front-cname">{{ form.cname }}</div>
<div class="front-ename">{{ form.ename }}</div>
<img class="front-logo" :src="form.image || defaultLogo">
</div>
<div class="back" v-show="showCardType === 1">
<img src="@/assets/images/card/qrcode.png">
</div>
</div>
<van-cell-group inset>
<van-field v-model="form.cname" type="text" placeholder="任何您想寫的文字" label="中文姓名" />
<van-field v-model="form.ename" type="text" placeholder="任何您想寫的文字" label="英文姓名" />
</van-cell-group>
<div style="margin: 16px 32px;">
圖片<br />
<van-uploader :after-read="afterRead" @delete="handleDelete" accept="image/*" name="logo" class="img-uploader"
:max-count="1" v-model="fileList" />
<!-- <div class="upload-main">
<img class="upload-img" :src="form.avatar" alt="">
<p>上傳圖片</p>
</div> -->
<!-- </van-uploader> -->
</div>
</div>
<!-- crop : Start -->
<van-overlay :show="crop.show" @click="crop.show = false" />
<div class="cropper-section" v-if="crop.show">
<div class="crop-area">
<cropper class="cropper" ref="myCrop" :src="crop.img" :stencil-props="{
aspectRatio: 10 / 10,
}" :auto-zoom="true" />
</div>
<div class="crop-btn">
<van-button type="primary" size="small" plain @click="onClose">取消</van-button>
<van-button type="success" size="small" plain @click="onCrop"></van-button>
</div>
</div>
<!-- crop : End -->
</template>
<script setup>
import { ref, computed } from 'vue'
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
import { uploadFile } from '@/services/card'
import defaultLogo from '@/assets/images/logo/logo.png'
const showCardType = ref(0)
const fileList = ref([])
const props = defineProps({
modelValue: {
type: Object,
default: ()=>({})
}
})
const emit = defineEmits(['update:modelValue'])
const form = computed({
get() {
return props.modelValue
},
set(v) {
console.log('set', v)
emit('update:modelValue', v)
}
})
const afterRead = async (file) => {
crop.value.show = true
crop.value.img = file.content
return
let imgFile = new FormData()
imgFile.append("fileType", 'IMAGE');
imgFile.append("file", file.file);
file.status = 'uploading'
file.message = '上傳中...'
try {
let res = await uploadFile(imgFile)
if (res && res.code === 200) {
form.value.image = res.data
file.status = 'done';
file.message = '上傳完成';
} else {
file.status = 'failed';
file.message = '上傳失敗';
}
} catch (e) {
file.status = 'failed'
file.message = '上傳失敗'
}
}
// crop
const myCrop = ref(null);
const crop = ref({
show: false,
img: null,
outputType: "jpeg",
autoCrop: true,
autoCropWidth: 200,
autoCropHeight: 200,
});
const onCrop = () => {
const { canvas } = myCrop.value.getResult();
if (canvas) {
const imgFile = new FormData();
canvas.toBlob(async (blob) => {
let ufile = new File([blob], "image.jpg");
imgFile.append("fileType", "IMAGE");
imgFile.append("file", ufile);
crop.value.show = false;
// Toast.loading({
// duration: 0,
// message: "圖片上傳中...",
// forbidClick: true,
// });
fileList.value[0] = {
status: 'uploading',
message: '上傳中...'
}
try {
let res = await uploadFile(imgFile)
if (res && res.code === 200) {
form.value.image = res.data
fileList.value[0] = {
url: res.data,
status: 'done',
message: '上傳成功'
}
} else {
fileList.value[0] = {
status: 'failed',
message: '上傳失敗'
}
}
} catch (e) {
fileList.value[0] = {
status: 'failed',
message: '上傳失敗'
}
}
}, "image/jpeg");
}
return;
};
const onClose = () => {
fileList.value = []
crop.value.show = false;
};
const handleDelete = (file) => {
console.log('delete')
console.log('file', file)
form.value.image = ''
}
</script>
<style lang="less" scoped>
.card-preview {
// height: 50%;
width: 345px;
margin-bottom: 10px;
.front {
width: 345px;
height: 220px;
position: relative;
background-image: url(@/assets/images/card/front.png);
background-size: 345px 220px;
.front-logo {
position: relative;
width: 100px;
top: 50px;
left: 20px;
}
.front-cname {
position: absolute;
top: 70px;
left: 180px;
font-size: 20px;
letter-spacing: 5px;
}
.front-ename {
position: absolute;
top: 110px;
left: 180px;
font-size: 12px;
letter-spacing: 5px;
}
}
.back {
width: 345px;
height: 220px;
position: relative;
background-image: url(@/assets/images/card/back.png);
background-size: 345px 220px;
display: flex;
align-items: center;
justify-content: center;
}
}
.cropper-section {
margin: 0 auto;
position: fixed;
text-align: center;
top: 50px;
// left: 0;
height: 350px;
width: 100%;
max-width: 500px;
background: #ddd;
z-index: 8888;
.crop-area {
margin: 5 auto;
width: 100%;
height: 330px;
}
.crop-btn {
background-color: #666;
text-align: center;
}
}
.cropper {
height: 300px;
// width: 300px;
background: #ddd;
}
</style>