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
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> |