|
@@ -0,0 +1,456 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, reactive, computed } from "vue";
|
|
|
+import type { YTViewsUserData } from "@/interfaces";
|
|
|
+import { useMainStore } from "@/stores/main";
|
|
|
+
|
|
|
+const mainStore = useMainStore();
|
|
|
+const fieldRules = [(value: string) => !!value || "此欄位為必填項目"];
|
|
|
+
|
|
|
+const items = reactive([
|
|
|
+ { title: "100% 真人觀看" },
|
|
|
+ { title: "包含影片設定費" },
|
|
|
+ { title: "開發票" },
|
|
|
+ { title: "包含成效報表" },
|
|
|
+]);
|
|
|
+
|
|
|
+const cardItems = reactive([
|
|
|
+ { view: "5,000", price: "2,700", originalPrice: "3,500", param: 2700 },
|
|
|
+ { view: "10,000", price: "4,400", originalPrice: "5,000", param: 4400 },
|
|
|
+ { view: "30,000", price: "12,400", originalPrice: "13,000", param: 12400 },
|
|
|
+ { view: "50,000", price: "20,400", originalPrice: "21,000", param: 20400 },
|
|
|
+]);
|
|
|
+
|
|
|
+const ageOptions = [
|
|
|
+ { label: "18 - 24 歲" },
|
|
|
+ { label: "25 - 34 歲" },
|
|
|
+ { label: "35 - 44 歲" },
|
|
|
+ { label: "45 - 54 歲" },
|
|
|
+ { label: "55 - 64 歲" },
|
|
|
+ { label: "65 歲以上" },
|
|
|
+];
|
|
|
+
|
|
|
+const objectOptions = [
|
|
|
+ { label: "交通工具與運輸" },
|
|
|
+ { label: "媒體和娛樂" },
|
|
|
+ { label: "家居與園藝" },
|
|
|
+ { label: "新聞與政治" },
|
|
|
+ { label: "旅遊" },
|
|
|
+ { label: "生活型態與興趣" },
|
|
|
+ { label: "科技" },
|
|
|
+ { label: "美容與健康" },
|
|
|
+ { label: "美食與餐飲" },
|
|
|
+ { label: "購物愛好者" },
|
|
|
+ { label: "運動與健身" },
|
|
|
+ { label: "銀行與金融" },
|
|
|
+];
|
|
|
+
|
|
|
+const themeOptions = [
|
|
|
+ { label: "人文與社會" },
|
|
|
+ { label: "保健" },
|
|
|
+ { label: "全球地點(各地區)" },
|
|
|
+ { label: "參考資料(圖書館、博物館與目錄、清單等)" },
|
|
|
+ { label: "圖書與文學" },
|
|
|
+ { label: "家居與園藝" },
|
|
|
+ { label: "寵物與動物" },
|
|
|
+ { label: "工作與教育" },
|
|
|
+ { label: "工商業" },
|
|
|
+ { label: "房地產" },
|
|
|
+ { label: "新聞" },
|
|
|
+ { label: "旅遊與交通" },
|
|
|
+ { label: "汽車與交通工具" },
|
|
|
+ { label: "法律與政府" },
|
|
|
+ { label: "科學" },
|
|
|
+ { label: "網路社群" },
|
|
|
+ { label: "網際網路與電信" },
|
|
|
+ { label: "美容與健身" },
|
|
|
+ { label: "美食佳飲" },
|
|
|
+ { label: "興趣與休閒" },
|
|
|
+ { label: "藝術與娛樂" },
|
|
|
+ { label: "購物" },
|
|
|
+ { label: "遊戲" },
|
|
|
+ { label: "運動" },
|
|
|
+ { label: "金融" },
|
|
|
+ { label: "電腦和電子產品" },
|
|
|
+];
|
|
|
+
|
|
|
+let chooseError = ref(false);
|
|
|
+let assignView = ref();
|
|
|
+let assignPrice = ref();
|
|
|
+
|
|
|
+function activeBtn(view: string, param: number) {
|
|
|
+ assignView.value = view;
|
|
|
+ assignPrice.value = param;
|
|
|
+ chooseError.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+let userData = reactive({
|
|
|
+ email: "",
|
|
|
+ name: "",
|
|
|
+ company: "",
|
|
|
+ url: "",
|
|
|
+ area: "",
|
|
|
+ language: "",
|
|
|
+ age: [],
|
|
|
+ object: "",
|
|
|
+ theme: "",
|
|
|
+ tax: "",
|
|
|
+});
|
|
|
+
|
|
|
+// 其他選項
|
|
|
+let object = ref("");
|
|
|
+let theme = ref("");
|
|
|
+let otherObject = ref("");
|
|
|
+let otherTheme = ref("");
|
|
|
+
|
|
|
+// 檢查必填欄位
|
|
|
+const isSubmitDisabled = computed(() => {
|
|
|
+ return (
|
|
|
+ !userData.email ||
|
|
|
+ !userData.name ||
|
|
|
+ !userData.url ||
|
|
|
+ !userData.area ||
|
|
|
+ !userData.language ||
|
|
|
+ !object.value ||
|
|
|
+ !theme.value
|
|
|
+ );
|
|
|
+});
|
|
|
+
|
|
|
+async function ECPaySubmit() {
|
|
|
+ if (!assignPrice.value) {
|
|
|
+ chooseError.value = true;
|
|
|
+ window.scrollTo({ top: 0, behavior: "smooth" });
|
|
|
+ } else {
|
|
|
+ chooseError.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (object.value === "其他" && otherObject.value !== "") {
|
|
|
+ userData.object = otherObject.value;
|
|
|
+ } else {
|
|
|
+ userData.object = object.value;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (theme.value === "其他" && otherTheme.value !== "") {
|
|
|
+ userData.theme = otherTheme.value;
|
|
|
+ } else {
|
|
|
+ userData.theme = theme.value;
|
|
|
+ }
|
|
|
+
|
|
|
+ let data: YTViewsUserData = {
|
|
|
+ email: userData.email,
|
|
|
+ name: userData.name,
|
|
|
+ company: userData.company,
|
|
|
+ url: userData.url,
|
|
|
+ area: userData.area,
|
|
|
+ language: userData.language,
|
|
|
+ age: userData.age.join("、"),
|
|
|
+ object: userData.object,
|
|
|
+ theme: userData.theme,
|
|
|
+ tax: userData.tax,
|
|
|
+ };
|
|
|
+
|
|
|
+ await mainStore.uploadPayment(data, assignView.value, assignPrice.value);
|
|
|
+
|
|
|
+ const originalHTML = await mainStore.ecpayPaymentHTML(assignPrice.value);
|
|
|
+ let formHTML = originalHTML?.replace(
|
|
|
+ '<script type="text/javascript">document.getElementById("data_set").submit();</scr',
|
|
|
+ ""
|
|
|
+ );
|
|
|
+ formHTML = formHTML?.replace("ipt>", "");
|
|
|
+ const payFormElement = document.getElementById("pay-form");
|
|
|
+ payFormElement!.innerHTML = formHTML!;
|
|
|
+ const ecpayForm: HTMLFormElement = <HTMLFormElement>(
|
|
|
+ document.getElementById("data_set")
|
|
|
+ );
|
|
|
+ console.log(ecpayForm);
|
|
|
+ ecpayForm.submit();
|
|
|
+}
|
|
|
+
|
|
|
+// 資料存進 Google Sheets
|
|
|
+// async function saveData() {
|
|
|
+// const scriptURL =
|
|
|
+// "https://script.google.com/macros/s/AKfycbxCcfiOQ695DaxIa3peClqRRTWNj2aUNLbx7ty8U2wKlyU7wreQLioHG-sls5MPKBdlRQ/exec";
|
|
|
+
|
|
|
+// let formdata = new FormData();
|
|
|
+// formdata.append("email", userData.email);
|
|
|
+// formdata.append("name", userData.name);
|
|
|
+// formdata.append("company", userData.company);
|
|
|
+// formdata.append("url", userData.url);
|
|
|
+// formdata.append("area", userData.area);
|
|
|
+// formdata.append("language", userData.language);
|
|
|
+// formdata.append("age", userData.age.join("、"));
|
|
|
+// formdata.append("object", userData.object);
|
|
|
+// formdata.append("theme", userData.theme);
|
|
|
+// formdata.append("tax", userData.tax);
|
|
|
+
|
|
|
+// axios
|
|
|
+// .post(scriptURL, formdata)
|
|
|
+// .then(function (response) {
|
|
|
+// console.log(response.data);
|
|
|
+// })
|
|
|
+// .catch(function (error) {
|
|
|
+// console.log(error);
|
|
|
+// });
|
|
|
+// }
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <v-container fluid>
|
|
|
+ <v-card class="ma-3 pa-3">
|
|
|
+ <v-card-title primary-title class="mb-3">
|
|
|
+ <h3 class="headline primary--text">YouTube 觀看數</h3>
|
|
|
+ </v-card-title>
|
|
|
+ <v-card-text>
|
|
|
+ <p class="ms-3">請選擇方案:</p>
|
|
|
+ <v-row no-gutters class="pay-card">
|
|
|
+ <v-col
|
|
|
+ xs="12"
|
|
|
+ sm="6"
|
|
|
+ lg="3"
|
|
|
+ v-for="(item, index) in cardItems"
|
|
|
+ :key="index"
|
|
|
+ >
|
|
|
+ <button @click="activeBtn(item.view, item.param)" class="w-100">
|
|
|
+ <v-card
|
|
|
+ class="ma-3 py-3"
|
|
|
+ :class="{ active: assignPrice === item.param }"
|
|
|
+ >
|
|
|
+ <v-card-title primary-title class="pa-0">
|
|
|
+ <div class="d-flex flex-column">
|
|
|
+ <section class="d-flex mx-auto">
|
|
|
+ <img
|
|
|
+ width="30"
|
|
|
+ height="30"
|
|
|
+ src="@/assets/img/icon/play-button.png"
|
|
|
+ alt=""
|
|
|
+ class="me-2"
|
|
|
+ />
|
|
|
+ <h5 class="m-0">{{ item.view }}</h5>
|
|
|
+ </section>
|
|
|
+ <span class="text-center" style="color: #7c8ba7"
|
|
|
+ >Views</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <p class="price">
|
|
|
+ NT${{ item.price }} <br />
|
|
|
+ <small>NT${{ item.originalPrice }}</small>
|
|
|
+ </p>
|
|
|
+ </v-card-title>
|
|
|
+
|
|
|
+ <v-card-text class="d-flex align-center justify-center mt-3">
|
|
|
+ <ul>
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in items"
|
|
|
+ :key="index"
|
|
|
+ class="d-flex align-center"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ width="30"
|
|
|
+ src="@/assets/img/icon/check.png"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ {{ item.title }}
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </v-card-text>
|
|
|
+
|
|
|
+ <!-- <v-card-actions class="d-flex justify-center">
|
|
|
+ <v-btn @click="ECPaySubmit(item.param)"> Buy Now </v-btn>
|
|
|
+ </v-card-actions> -->
|
|
|
+ </v-card>
|
|
|
+ </button>
|
|
|
+ </v-col>
|
|
|
+ <p class="ms-3 error" v-show="chooseError">尚未選擇方案</p>
|
|
|
+ </v-row>
|
|
|
+
|
|
|
+ <v-sheet max-width="500" class="mx-auto mt-10">
|
|
|
+ <v-form @submit.prevent class="ECPay-form">
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.email"
|
|
|
+ :rules="fieldRules"
|
|
|
+ label="電子郵件"
|
|
|
+ required
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.name"
|
|
|
+ :rules="fieldRules"
|
|
|
+ label="姓名"
|
|
|
+ required
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.company"
|
|
|
+ label="公司 / 所屬產業"
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.url"
|
|
|
+ :rules="fieldRules"
|
|
|
+ label="YouTube 影片網址"
|
|
|
+ required
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.area"
|
|
|
+ :rules="fieldRules"
|
|
|
+ label="影片放送地區(國家 / 縣市)"
|
|
|
+ required
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ v-model="userData.language"
|
|
|
+ :rules="fieldRules"
|
|
|
+ label="受眾語言"
|
|
|
+ required
|
|
|
+ ></v-text-field>
|
|
|
+
|
|
|
+ <p class="mt-5">客層(未選擇的話視為全部)</p>
|
|
|
+ <div class="checkbox ms-5">
|
|
|
+ <v-checkbox
|
|
|
+ v-for="option in ageOptions"
|
|
|
+ v-model="userData.age"
|
|
|
+ :key="option.label"
|
|
|
+ :label="option.label"
|
|
|
+ :value="option.label"
|
|
|
+ color="primary"
|
|
|
+ ></v-checkbox>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p class="mt-10 mb-3">
|
|
|
+ 目標對象區隔(興趣、習慣)<span class="text-red-darken-1">*</span>
|
|
|
+ </p>
|
|
|
+ <div class="ms-5">
|
|
|
+ <v-radio-group v-model="object">
|
|
|
+ <v-radio
|
|
|
+ v-for="option in objectOptions"
|
|
|
+ :key="option.label"
|
|
|
+ :label="option.label"
|
|
|
+ :value="option.label"
|
|
|
+ color="primary"
|
|
|
+ ></v-radio>
|
|
|
+ <v-radio label="其他" value="其他" color="primary"></v-radio>
|
|
|
+ <input v-model="otherObject" type="text" class="other" />
|
|
|
+ </v-radio-group>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p class="mt-5 mb-3">
|
|
|
+ 影片主題 <span class="text-red-darken-1">*</span>
|
|
|
+ </p>
|
|
|
+ <div class="ms-5">
|
|
|
+ <v-radio-group v-model="theme">
|
|
|
+ <v-radio
|
|
|
+ v-for="option in themeOptions"
|
|
|
+ :key="option.label"
|
|
|
+ :label="option.label"
|
|
|
+ :value="option.label"
|
|
|
+ color="primary"
|
|
|
+ ></v-radio>
|
|
|
+
|
|
|
+ <v-radio label="其他" value="其他" color="primary"></v-radio>
|
|
|
+ <input v-model="otherTheme" type="text" class="other" />
|
|
|
+ </v-radio-group>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <v-text-field
|
|
|
+ type="number"
|
|
|
+ label="是否需要統編(可填寫統編號碼)"
|
|
|
+ v-model="userData.tax"
|
|
|
+ ></v-text-field>
|
|
|
+
|
|
|
+ <v-btn
|
|
|
+ @click="ECPaySubmit()"
|
|
|
+ type="submit"
|
|
|
+ block
|
|
|
+ class="mt-2 submit-btn"
|
|
|
+ :disabled="isSubmitDisabled"
|
|
|
+ >送出</v-btn
|
|
|
+ >
|
|
|
+ </v-form>
|
|
|
+ </v-sheet>
|
|
|
+ </v-card-text>
|
|
|
+ </v-card>
|
|
|
+ </v-container>
|
|
|
+
|
|
|
+ <div id="pay-form"></div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.pay-card {
|
|
|
+ .v-card-title {
|
|
|
+ h5 {
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+ span {
|
|
|
+ font-size: 16px;
|
|
|
+ letter-spacing: 1px;
|
|
|
+ }
|
|
|
+ .price {
|
|
|
+ padding: 10px 0;
|
|
|
+ font-size: 26px;
|
|
|
+ font-weight: 600;
|
|
|
+ text-align: center;
|
|
|
+ color: #fff;
|
|
|
+ background-color: var(--main-color);
|
|
|
+ letter-spacing: 2px;
|
|
|
+ small {
|
|
|
+ display: block;
|
|
|
+ margin-top: -3px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 100;
|
|
|
+ text-decoration: line-through;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-card-text {
|
|
|
+ ul {
|
|
|
+ padding: 0;
|
|
|
+ list-style: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .v-card-actions {
|
|
|
+ button {
|
|
|
+ padding: 5px 15px;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 100px;
|
|
|
+ background-color: var(--main-color);
|
|
|
+ border: 1px solid transparent;
|
|
|
+ &:hover {
|
|
|
+ color: var(--main-color);
|
|
|
+ background-color: #fff;
|
|
|
+ border: 1px solid var(--main-color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .active {
|
|
|
+ border: 3px solid var(--main-color);
|
|
|
+ }
|
|
|
+
|
|
|
+ .error {
|
|
|
+ color: #b00020;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.ECPay-form {
|
|
|
+ font-size: 16px;
|
|
|
+ .checkbox {
|
|
|
+ margin-left: 5px;
|
|
|
+ list-style: none;
|
|
|
+ .v-input {
|
|
|
+ height: 40px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .v-input__details {
|
|
|
+ padding-top: 0;
|
|
|
+ padding-bottom: 3px;
|
|
|
+ }
|
|
|
+ .other {
|
|
|
+ margin-left: 40px;
|
|
|
+ border-bottom: 1px solid #333;
|
|
|
+ &:focus-visible {
|
|
|
+ outline: none !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .submit-btn {
|
|
|
+ color: #fff;
|
|
|
+ background-color: var(--main-color);
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|