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.

716 lines
24 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script>
import Footer from "@/components/Footer.vue";
import FlexView from "@/components/FlexView.vue";
import {
ref,
reactive,
toRefs,
watch,
onBeforeMount,
defineComponent,
} from "vue";
import { updateCusCard } from "@/api";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import axios from "axios";
import _ from "lodash";
import { showToast } from "vant";
import { showLoadingToast,showSuccessToast } from 'vant';
import { Cropper } from "vue-advanced-cropper";
import "vue-advanced-cropper/dist/style.css";
const URL = window.URL || window.webkitURL;
export default defineComponent({
name: "EditCard",
components: {
Footer,
Cropper,
FlexView,
},
async setup() {
const store = useStore();
const router = useRouter();
const showNfc = ref(false);
const showPreview = ref(false);
const showMovie = ref(false);
const showTitleSizePicker = ref(false);
const showDescSizePicker = ref(false);
let flexRef = ref(null);
const showMvPopup = () => {
console.log('test');
showMovie = true;
};
const crop = ref({
show: false,
img: null,
outputType: "jpeg",
autoCrop: true,
autoCropWidth: 200,
autoCropHeight: 200,
});
let state = reactive({
imagePath: "",
previewImage: null,
fileList: [],
showFooter: true,
form: {
page: 1,
title: "商務卡片",
showNfc: true,
json5: {
altText: '',
btnHeight: "md",
descSize: "sm",
titleSize: "xl",
cards: [
{
bgColor: "#ffffff",
desc: "",
descColor: "#000000",
image: "",
link: "",
title: "",
titleSize: "xl",
descSize: "sm",
titleColor: "#000000",
ratio: "20:13",
},
],
},
},
});
const sizeColumns = ref([
{text:'xxs',value:'xxs'},
{text:'xs',value: 'xs'},
{text:'sm',value: 'sm'},
{text:'md',value: 'md'},
{text:'lg',value: 'lg'},
{text:'xl',value: 'xl'},
{text:'xxl',value:'xxl'},
{text:'3xl',value:'3xl'},
{text:'4xl',value:'4xl'},
{text:'5xl',value:'5xl'}
]);
if (
store.state.user.userInfo.cus_card &&
store.state.user.userInfo.cus_card.length > 0
) {
state.form = JSON.parse(_.clone(store.state.user.userInfo.cus_card));
}
watch(()=>state.form.title,(newVal)=>{
state.form.json5.altText = newVal
})
const addCard = () => {
state.form.json5.cards.push({
bgColor: "#ffffff",
desc: "",
descColor: "#000000",
image: "",
// link: "",
title: "",
titleSize: "xl",
descSize: "sm",
titleColor: "#000000",
ratio: "20:13",
});
state.form.page = state.form.json5.cards.length;
};
const delCard = (page) => {
if (page > 1) {
state.form.page = page - 1;
}
state.form.json5.cards.splice(page - 1, 1);
};
const addBtn = (page) => {
if (!state.form.json5.cards[page - 1].btns) {
state.form.json5.cards[page - 1].btns = [];
}
state.form.json5.cards[page - 1].btns.push({
color: "#42659a",
link: "",
style: "primary",
text: "",
btnHeight: "md"
});
};
const addShareBtn = (page) => {
if (!state.form.json5.cards[page - 1].btns) {
state.form.json5.cards[page - 1].btns = [];
}
state.form.json5.cards[page - 1].btns.push({
color: "#42659a",
link: `${import.meta.env.VITE_APP_SEND_URL}?userid=${sessionStorage.getItem(
"uid"
)}&cardid=2`,
style: "primary",
text: "分享好友",
btnHeight: "md"
});
};
const moveCard = (type, page) => {
if (type === 0) {
if (page !== 1) {
[state.form.json5.cards[page - 1], state.form.json5.cards[page - 2]] =
[
state.form.json5.cards[page - 2],
state.form.json5.cards[page - 1],
];
state.form.page = page - 1;
}
} else {
if (page !== state.form.json5.cards.length) {
[state.form.json5.cards[page], state.form.json5.cards[page - 1]] = [
state.form.json5.cards[page - 1],
state.form.json5.cards[page],
];
state.form.page = page + 1;
}
}
};
const delBtn = (index) => {
state.form.json5.cards[state.form.page - 1].btns.splice(index, 1);
if (state.form.json5.cards[state.form.page - 1].btns.length === 0) {
delete state.form.json5.cards[state.form.page - 1].btns;
}
};
const moveBtn = (type, index) => {
if (type === 0) {
if (index !== 0) {
[
state.form.json5.cards[state.form.page - 1].btns[index],
state.form.json5.cards[state.form.page - 1].btns[index - 1],
] = [
state.form.json5.cards[state.form.page - 1].btns[index - 1],
state.form.json5.cards[state.form.page - 1].btns[index],
];
}
} else {
if (
index + 1 !==
state.form.json5.cards[state.form.page - 1].btns.length
) {
[
state.form.json5.cards[state.form.page - 1].btns[index + 1],
state.form.json5.cards[state.form.page - 1].btns[index],
] = [
state.form.json5.cards[state.form.page - 1].btns[index],
state.form.json5.cards[state.form.page - 1].btns[index + 1],
];
}
}
};
const afterRead = async (file, name) => {
// crop.value.show = true
// const ofile = file.file
// crop.value.img = URL.createObjectURL(ofile);
const imgFile = new FormData();
imgFile.append("fileType", "IMAGE");
imgFile.append("file", file.file);
showLoadingToast({
duration: 0,
message: "圖片上傳中...",
forbidClick: true,
});
let res = await axios.post(
`${import.meta.env.VITE_APP_API_URL}/card/uploadfile`,
imgFile,
{}
);
if (res.data.code == 200) {
state.form.json5.cards[state.form.page - 1].image = res.data.data;
showSuccessToast("上傳成功");
} else {
showToast.fail("上傳失敗");
}
return;
};
const handleDelete = () => {
state.form.json5.cards[state.form.page - 1].image = "";
};
const handlePreview = () => {
router.push({
name: "CardPreview",
params: { content: JSON.stringify(state.form) },
});
};
const onTitleSizeConfirm = ({ selectedOptions }) => {
showTitleSizePicker.value = false;
state.form.json5.cards[state.form.page - 1].titleSize = selectedOptions[0].text;
};
const onDescSizeConfirm = ({ selectedOptions }) => {
showDescSizePicker.value = false;
state.form.json5.cards[state.form.page - 1].descSize = selectedOptions[0].text;
};
const handleSubmit = async () => {
let user_id = sessionStorage.getItem("uid");
showLoadingToast({
duration: 0,
message: "名片上傳中...",
forbidClick: true,
});
let res = await updateCusCard({
user_id: user_id,
card_title: state.form.title,
show_cus: state.form.showNfc,
cus_card: JSON.stringify(state.form),
});
if (res.code === 200) {
store.commit("user/setCusCard", JSON.stringify(state.form));
showSuccessToast("建立成功");
} else {
showToast.fail("建立失敗");
}
router.push("/");
};
return {
...toRefs(state),
sizeColumns,
showPreview,
showMovie,
showMvPopup,
showTitleSizePicker,
showDescSizePicker,
flexRef,
crop,
addCard,
delCard,
moveCard,
addBtn,
addShareBtn,
delBtn,
moveBtn,
afterRead,
handlePreview,
handleDelete,
onTitleSizeConfirm,
onDescSizeConfirm,
handleSubmit,
};
},
});
</script>
<template>
<div class="edit page">
<van-form @submit="handleSubmit">
<van-nav-bar class="bg-skyBlue py-1" left-arrow @click-left="$router.push('/')">
<template #title>
<h5 class="text-white mb-1"><strong>商務卡片設定</strong></h5>
</template>
<template #left>
<h4><i class="fa-solid fa-angle-left text-white" :style="{opacity:0.5}"></i></h4>
</template>
</van-nav-bar>
<div class="content">
<van-cell-group inset class="">
<van-cell class="bg-lightPink">
<template #title>
<h6 class="text-darkBlue"><strong>卡片設定</strong></h6>
</template>
<template #value>
<!-- <van-button size="small" class="ml-1 btn-moBlue" icon="tv-o" hairline @click="$router.push('/card/video')"></van-button> -->
<van-button size="small" class="ml-1 btn-moBlue" icon="tv-o" hairline @click="showMovie = true">教學影片</van-button>
<van-button size="small" class="ml-1 btn-skyBlue" icon="eye-o" hairline @click="handlePreview"></van-button>
</template>
</van-cell>
<van-popup v-model:show="showMovie" class="p-3" closeable>
<iframe width="375" height="215" src="https://www.youtube.com/embed/fjZsQ0Rh6yk" title="Utel電子名片教學"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
</van-popup>
<van-field
v-model="form.title"
label="標題文字"
name=""
input-align="right"
error-message-align="right"
placeholder="請輸入您在名片切換時顯示的文字"
:rules="[{ required: true, message: '標題文字必填' }]"
/>
<van-field label="是否顯示於感應名片" class="longText" input-align="right">
<template #input>
<van-switch
v-model="form.showNfc"
size="18px"
active-color="#345068"
inactive-color="#888888"
/>
</template>
</van-field>
</van-cell-group>
<van-cell-group inset class="mt-3">
<keep-alive>
<div id="app">
<!-- tab -->
<div class="bg-lightPink px-2 pt-3">
<ul class="nav nav-tabs">
<li
class="nav-item"
v-for="(card, index) in form.json5.cards"
:key="index"
@click="form.page = index + 1"
>
<button
type="button"
class="nav-link"
:class="{ active: form.page === index + 1 }"
>
{{ index + 1 }}
</button>
</li>
<li
class="nav-item"
@click="addCard"
v-if="form.json5.cards.length < 10"
>
<button type="button" class="nav-link">
<i class="fa fa-plus-circle"></i> 新增
</button>
</li>
</ul>
</div>
<!-- /tab -->
<div class="py-2">
<van-field label="調整卡片順序" :border="false" v-if="form.json5.cards.length > 1">
<template #button>
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow-left" @click="moveCard(0, form.page)">前移</van-button>
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow" @click="moveCard(1, form.page)">後移</van-button>
<van-button size="small" class="ml-1 btn-tomatoRed" icon="delete-o" @click="delCard(form.page)"></van-button>
</template>
</van-field>
<van-divider :style="{ color: '#345068', borderColor: '#345068', padding: '0 16px' }"><strong>卡片設定</strong></van-divider>
<van-field
v-model="form.json5.cards[form.page - 1].ratio"
label="卡片長寬比"
id="vcard-ratio"
input-align="right"
placeholder="請輸入圖片長寬比比如20:13、1:1、6:8"
/>
<van-field
v-model="form.json5.cards[form.page - 1].bgColor"
label="卡片底色"
id="vcard-bgColor"
input-align="right"
placeholder="請輸入卡片底色的色碼,如:#333333"
:border="false"
:rules="[{ required: true, message: '卡片底色色碼必填' }]"
>
<template #button>
<input
v-model="form.json5.cards[form.page - 1].bgColor"
type="color" class="form-control-color"
/>
</template>
</van-field>
<van-divider :style="{ color: '#345068', borderColor: '#345068', padding: '0 16px' }"><strong>內容圖片設定</strong></van-divider>
<van-field
v-model="form.json5.cards[form.page - 1].ratio"
:border="false"
>
<template #input>
<van-uploader
:after-read="afterRead"
:max-count="1"
name="cardimage"
@delete="handleDelete"
>
<template
v-if="form.json5.cards[form.page - 1].image.length > 0"
>
<div class="upload-main">
<img
class="upload-img"
:src="form.json5.cards[form.page - 1].image"
alt=""
/>
<p class="ml-3 px-2 py-1 text-white bg-skyBlue rounded-pill">
<i class="fa-solid fa-arrow-left"></i> 點擊更換圖片
</p>
</div>
</template>
<template v-else>
<div class="upload-main">
<img
class="upload-img"
src="@/assets/images/upload.jpg"
/>
<p class="ml-3">請上傳圖片</p>
<p class="ml-3 px-2 py-1 text-white bg-skyBlue rounded-pill">
請上傳圖片
</p>
</div>
</template>
</van-uploader>
</template>
</van-field>
<!-- <van-field
v-model="form.json5.cards[form.page - 1].link"
label="圖片網址連結"
id="vcard-link"
input-align="right"
placeholder="連結(需輸入完整網址,http://..,https://...)"
/> -->
<van-divider :style="{ color: '#345068', borderColor: '#345068', padding: '0 16px' }"><strong>卡片標題</strong></van-divider>
<van-field
v-model="form.json5.cards[form.page - 1].title"
label="標題文字"
id="vcard-title"
input-align="right"
placeholder="連結(需輸入完整網址,http://..,https://...)"
:rules="[{ required: true, message: '請填寫卡片標題文字' }]"
/>
<van-field
v-model="form.json5.cards[form.page - 1].titleSize"
is-link
readonly
label="標題文字大小"
id="vcard-titleSize"
input-align="right"
placeholder="請輸入標題文字的色碼,如:#333333"
@click="showTitleSizePicker = true"
/>
<van-popup v-model:show="showTitleSizePicker" round position="bottom">
<van-picker
:columns="sizeColumns"
@cancel="showTitleSizePicker = false"
@confirm="onTitleSizeConfirm"
/>
</van-popup>
<van-field
v-model="form.json5.cards[form.page - 1].titleColor"
label="標題文字顏色"
id="vcard-titleColor"
placeholder="請輸入標題文字的色碼,如:#333333"
:border="false"
:rules="[{ required: true, message: '標題文字色碼必填' }]"
>
<template #button>
<input
v-model="form.json5.cards[form.page - 1].titleColor"
type="color" class="form-control-color"
/>
</template>
</van-field>
<van-divider :style="{ color: '#345068', borderColor: '#345068', padding: '0 16px' }"><strong>卡片說明文字</strong></van-divider>
<van-field
v-model="form.json5.cards[form.page - 1].desc"
label="說明文字"
label-align="top"
id="vcard-desc"
type="textarea"
maxlength="50"
placeholder="請填寫卡片說明文字"
show-word-limit
:rules="[{ required: true, message: '請填寫卡片說明文字' }]"
/>
<van-field
v-model="form.json5.cards[form.page - 1].descSize"
is-link
readonly
label="說明文字大小"
id="vcard-descSize"
input-align="right"
placeholder="請輸入說明文字的色碼,如:#333333"
@click="showDescSizePicker = true"
/>
<van-popup v-model:show="showDescSizePicker" round position="bottom">
<van-picker
:columns="sizeColumns"
@cancel="showDescSizePicker = false"
@confirm="onDescSizeConfirm"
/>
</van-popup>
<van-field
v-model="form.json5.cards[form.page - 1].descColor"
label="說明文字顏色"
id="vcard-descColor"
placeholder="請輸入說明文字的色碼,如:#333333"
:rules="[{ required: true, message: '說明文字色碼必填' }]"
>
<template #button>
<input
v-model="form.json5.cards[form.page - 1].descColor"
type="color" class="form-control-color"
/>
</template>
</van-field>
</div>
<van-divider :style="{ color: '#345068', borderColor: '#345068', padding: '0 16px' }"><strong>按鈕連結設定</strong></van-divider>
<van-field
label="新增按鈕"
input-align="right"
:border="false"
>
<template #button>
<van-button size="small" class="ml-1 btn-outline-skyBlue" icon="add-o" @click="addBtn(form.page)"><h6>新增按鈕</h6></van-button>
<van-button size="small" class="ml-1 btn-outline-skyBlue" icon="share-o" @click="addShareBtn(form.page)"><h6>新增分享按鈕</h6></van-button>
</template>
</van-field>
<div class="p-3">
<div class="card shadow-sm" v-for="(btn, index) in form.json5.cards[form.page - 1].btns" :key="index">
<div class="card-header" :style="{backgroundColor:btn.color}">
<van-field :label="`控制按鈕 ${ index + 1 }`" :border="false" class="bg-transparent">
<template #button>
<van-button size="small" class="bg-transparent border-0" icon="arrow-up" @click="moveBtn(0, index)" v-if="form.json5.cards[form.page - 1].btns.length > 1"></van-button>
<van-button size="small" class="bg-transparent border-0" icon="arrow-down" @click="moveBtn(1, index)" v-if="form.json5.cards[form.page - 1].btns.length > 1"></van-button>
<van-button size="small" class="bg-transparent border-0" icon="delete-o" @click="delBtn(index)"></van-button>
</template>
</van-field>
</div>
<div class="card-body">
<van-field
v-model="btn.text"
:label="`按鈕 ${ index + 1 } 文字`"
id="cardbtn-text-0"
input-align="right"
placeholder="請填寫按鈕文字"
:rules="[{ required: true, message: '請填寫按鈕文字' }]"
/>
<van-field
v-model="btn.link"
:label="`按鈕 ${ index + 1 } 連結`"
id="cardbtn-link-0"
input-align="right"
type="url"
placeholder="連結(需輸入完整網址,http://..,https://...)"
:rules="[{ required: true, message: '請填寫按鈕連結' }]"
/>
<van-field
v-model="btn.color"
label="按鈕背景顏色"
id="vcard-titleColor"
input-align="right"
placeholder="請輸入標題文字的色碼,如:#333333"
:rules="[{ required: true, message: '標題文字色碼必填' }]"
>
<template #button>
<input
v-model="btn.color"
type="color" class="form-control-color"
/>
</template>
</van-field>
<van-field
v-model="btn.color"
label="按鈕背景顏色"
id="vcard-titleColor"
input-align="right"
placeholder="請輸入標題文字的色碼,如:#333333"
:border="false"
:rules="[{ required: true, message: '標題文字色碼必填' }]"
>
<template #input>
<van-radio-group direction="horizontal" v-model="btn.btnHeight" checked-color="#345068">
<van-radio name="sm" @click="btn.btnHeight='sm'">sm</van-radio>
<van-radio name="md" @click="btn.btnHeight='md'">md</van-radio>
</van-radio-group>
</template>
</van-field>
</div>
</div>
</div>
<div class="px-5 pb-4">
<van-button block class="btn-darkBlue" native-type="submit">
<h6>名片確認 & 建立</h6>
</van-button>
</div>
</div>
</keep-alive>
</van-cell-group>
</div>
</van-form>
</div>
</template>
<style lang="less" scoped>
.form-control-color,.form-control-color:valid {
appearance: none;
background: 0 0;
border: 1px solid #ced4da;
height: 30px;
padding: 0 2px;
border-radius: 5px;
}
.flex-section {
width: 100%;
}
.upload-main{
.upload-img{
margin: 5px 0;
width:250px;
}
}
</style>