wip
This commit is contained in:
@@ -255,16 +255,15 @@
|
||||
"id": "vu6q2t",
|
||||
"title": "Making a bookcase",
|
||||
"titleTranslate": "做书架",
|
||||
"text": "DAN:You're working hard, George. \n\nWhat are you doing? \n\nGEORGE:I'm making a bookcase. \n\nGEORGE:Give me that hammer please, Dan. \n\nDAN:Which hammer? \n\nThis one? \n\nGEORGE:No, not that one. \n\nThe big one. \n\nDAN:Here you are. \n\nGEORGE:Thanks, Dan. \n\nDAN:What are you doing to do now, George? \n\nGEORGE:I'm going to paint it. \n\nDAN:What colour are you going to pain it? \n\nGEORGE:I'm going to paint it pink. \n\nDAN:Pink! \n\nGEORGE:This bookcase isn't for me. \n\nIt's for my daughter, Susan. \n\nPink's her favourite colour.",
|
||||
"text": "DAN:You're working hard, George.\n\nWhat are you doing?\n\nGEORGE:I'm making a bookcase.\n\nGEORGE:Give me that hammer please, Dan.\n\nDAN:Which hammer?\n\nThis one?\n\nGEORGE:No, not that one.\n\nThe big one.\n\nDAN:Here you are.\n\nGEORGE:Thanks, Dan.\n\nDAN:What are you doing to do now, George?\n\nGEORGE:I'm going to paint it.\n\nDAN:What colour are you going to pain it?\n\nGEORGE:I'm going to paint it pink.\n\nDAN:Pink!\n\nGEORGE:This bookcase isn't for me.\n\nIt's for my daughter, Susan.\n\nPink's her favourite colour.",
|
||||
"textTranslate": "丹 :你干得真辛苦,乔治。 \n\n你在干什么呢? \n\n乔治:我正在做书架。 \n\n乔治:请把那把锤子拿给我。丹。 \n\n丹 :哪一把? \n\n是这把吗? \n\n乔治:不,不是那把。 \n\n是那把大的。 \n\n丹 :给你。 \n\n乔治:谢谢。丹。 \n\n丹 :你现在打算干什么,乔治? \n\n乔治:我打算把它漆一下。 \n\n丹 :你打算把它漆成什么颜色? \n\n乔治:我想漆成粉红色。 \n\n丹 :粉红色! \n\n乔治:这个书架不是为我做的, \n\n是为我的女儿苏珊做的。 \n\n粉红色是她最喜欢的颜色。",
|
||||
"newWords": [],
|
||||
"textAllWords": [],
|
||||
"sections": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "D1hOTuRbegEsU5klGK9Oe",
|
||||
"lrcPosition": [[17.03,20.14],[20.65,22.69],[23.29,26.14],[26.54,29.75],[30.79,32.65],[32.65,33.82],[33.86,36.48],[36.48,38.51],[38.51,40.65],[40.65,42.16],[43.16,47.31],[47.35,50.29],[50.89,54.67],[55.27,58.52],[59.22,60.68],[60.68,63.66],[63.68,67.03],[66.63,70.24]],
|
||||
"questions": [],
|
||||
"nameList": ["DAN", "George", "SUSAN"]
|
||||
"nameList": ["DAN", "George", "SUSAN"],
|
||||
"textAllWords": []
|
||||
},
|
||||
{
|
||||
"id": "_t46T4",
|
||||
@@ -274,8 +273,8 @@
|
||||
"textTranslate": "萨姆:你打算如何处理那花瓶,彭妮? \n\n彭妮:我打算把它放在这张桌子上,萨姆。 \n\n萨姆:不要放在那儿,把它给我。 \n\n彭妮:你打算怎么办? \n\n萨姆:我准备把它入在这儿,放在窗前。 \n\n彭妮:小心点!别摔了! \n\n彭妮:别放在那儿,萨姆。 \n\n放在这儿,这个架子上。 \n\n萨姆:这只漂亮的花瓶。 \n\n彭妮:这些花也很漂亮啊。",
|
||||
"newWords": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "gUTZU6hSEEshwxvnCaIql",
|
||||
"lrcPosition": [[18.13,23.35],[23.5,28.33],[28.7,33.21],[33.26,37.04],[37.24,42.59],[42.77,47.01],[47.01,50.63],[49.93,53.95],[53.95,59.21],[59.21,63.12]],
|
||||
"questions": [],
|
||||
"nameList": ["SAM", "Penny"],
|
||||
"textAllWords": []
|
||||
@@ -288,8 +287,8 @@
|
||||
"textTranslate": "萨姆:那个提包重吗,彭妮? \n\n彭妮:不太重。 \n\n萨姆:放在这儿。 \n\n把它放在这把椅子上。 \n\n里面是什么东西? \n\n彭妮:一块乳酪、 \n\n一块面包、 \n\n一块肥皂、 \n\n一块巧克力、 \n\n一瓶牛奶、 \n\n一磅糖、 \n\n半磅咖啡、 \n\n1/4 磅茶叶、 \n\n和一听烟丝。 \n\n萨姆:那听烟丝是给我的吗? \n\n彭妮:噢,当然不会给我的!",
|
||||
"newWords": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "-sx_DKTLak5k44_rCyvly",
|
||||
"lrcPosition": [[17.89,20.83],[20.83,22.48],[22.48,23.95],[24.3,27.12],[27.12,29.27],[29.27,31.23],[32.14,33.95],[34.77,36.64],[37.52,39.71],[40.19,42],[42.77,44.83],[45.44,48.17],[48.87,52.16],[52.56,56.26],[57.57,62.07],[62.07,65.98]],
|
||||
"questions": [],
|
||||
"nameList": ["SAN", "Penny"],
|
||||
"textAllWords": []
|
||||
@@ -302,8 +301,8 @@
|
||||
"textTranslate": "彭妮:你会沏茶吗,萨姆? \n\n萨姆:会的,我当然会,彭妮。 \n\n萨姆:这水壶里有水吗? \n\n彭妮:有水。 \n\n萨姆:茶叶在哪儿? \n\n彭妮:就在那儿,茶壶后面。 \n\n彭妮:你看见了吗? \n\n萨姆:茶壶我看见了,但茶叶没看到。 \n\n彭妮:那不是么! 就在你眼前。 \n\n萨姆:噢,是啊,我现在看到了。 \n\n萨姆:茶杯在哪儿呢? \n\n彭妮:碗橱里有几只。 \n\n彭妮:你找得到吗? \n\n萨姆:找得到。就在这儿呢。 \n\n彭妮:快,萨姆。水开了!",
|
||||
"newWords": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "TOGa6HB5T2ZBwTKnfP8Cv",
|
||||
"lrcPosition": [[18.21,22.14],[22.14,25.77],[26.87,30.43],[31.01,33.61],[33.61,35.39],[35.39,40.99],[40.99,43.56],[43.56,49.45],[49.73,53.45],[53.56,58.79],[58.79,61.23],[61.23,63.77],[63.8,66.22],[66.22,69.13],[69.13,73.24]],
|
||||
"questions": [],
|
||||
"nameList": ["PENNY", "Sam"],
|
||||
"textAllWords": []
|
||||
@@ -316,8 +315,8 @@
|
||||
"textTranslate": "老 板:请你来一下好吗?鲍勃? \n\n鲍 勃: 什么事,先生? \n\n老 板:帕梅拉在哪儿? \n\n鲍 勃: 她在隔壁,在她的办公室里,先生。 \n\n老 板:她能为我打一下这封信吗?请问她。 \n\n鲍 勃: 好的,先生。 \n\n鲍 勃: 请你把这封信给老板打一下可以吗, \n\n帕梅拉? \n\n帕梅拉:可以,当然可以。 \n\n鲍 勃: 给你这信。 \n\n帕梅拉:谢谢你,鲍勃。 \n\n帕梅拉:鲍勃! \n\n鲍 勃: 怎么了?怎么回事? \n\n帕梅拉:我打不了这封信。 \n\n帕梅拉:我看不懂这封信, 老板的书写太糟糕了!",
|
||||
"newWords": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "ztOWX0trsETPGegnm7WPK",
|
||||
"lrcPosition": [[17.66,21.77],[21.77,24.03],[24.03,25.81],[25.81,30.71],[30.71,36.98],[36.92,39.31],[39.31,44.15],[44.15,47.75],[47.75,49.36],[49.36,51.07],[51.07,53.05],[53.05,54.11],[53.94,56.11],[56.11,59.3],[59.3,65.97]],
|
||||
"questions": [],
|
||||
"nameList": ["THE BOSS", "Bob", "Pamela"],
|
||||
"textAllWords": []
|
||||
@@ -330,8 +329,8 @@
|
||||
"textTranslate": "克里斯廷:你喜欢咖啡吗,安? \n\n安:是的,我喜欢。 \n\n克里斯廷:你想要一杯吗? \n\n安:好的,请来一杯,克里斯廷。 \n\n克里斯廷:你要放些糖吗? \n\n安:好的,请放一些。 \n\n克里斯廷:要放些牛奶吗? \n\n安:不了,谢谢。 \n\n我不喜欢咖啡中放牛奶, \n\n我喜欢咖啡。 \n\n克里斯廷:你喜欢饼干吗? \n\n安:是的,我喜欢。 \n\n克里斯廷:你想要一块吗? \n\n安:好的,请来一块。",
|
||||
"newWords": [],
|
||||
"audioSrc": "",
|
||||
"audioFileId": "",
|
||||
"lrcPosition": [],
|
||||
"audioFileId": "AXoaYeBkWYQImSNnKHo9G",
|
||||
"lrcPosition": [[17.15,20.61],[20.61,23.43],[23.43,25.65],[26.4,30.36],[30.36,32.97],[33.58,36.05],[36.05,38.69],[39.18,40.92],[40.92,44.56],[44.56,48.41],[48.41,50.87],[50.87,53.04],[53.04,55.59],[55.59,57.75]],
|
||||
"questions": [],
|
||||
"nameList": ["CHRISTINE", "ANN"],
|
||||
"textAllWords": []
|
||||
|
||||
@@ -53,7 +53,7 @@ export function levelBenefits(params) {
|
||||
}
|
||||
|
||||
export function orderCreate(params) {
|
||||
return http<{ orderNo: string }>('/member/orderCreate', params, null, 'post')
|
||||
return http<{ orderNo: string,result:string, }>('/member/orderCreate', params, null, 'post')
|
||||
}
|
||||
export function testPay() {
|
||||
return http('/member/testPay', null, null, 'get')
|
||||
|
||||
@@ -68,6 +68,7 @@ function onClick() {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
border: 1px solid gainsboro;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import BasePage from '@/components/BasePage.vue'
|
||||
import BaseButton from '@/components/BaseButton.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/user.ts'
|
||||
import { User } from "@/apis/user.ts";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useUserStore} from '@/stores/user.ts'
|
||||
import {User} from "@/apis/user.ts";
|
||||
import {computed, onMounted, onUnmounted, ref, watch} from "vue";
|
||||
import Header from "@/components/Header.vue";
|
||||
import {
|
||||
CouponInfo,
|
||||
@@ -17,9 +17,9 @@ import {
|
||||
} from "@/apis/member.ts";
|
||||
import Radio from "@/components/base/radio/Radio.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
import { APP_NAME } from "@/config/env.ts";
|
||||
import {APP_NAME} from "@/config/env.ts";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
import { _dateFormat, _nextTick } from "@/utils";
|
||||
import {_dateFormat, _nextTick} from "@/utils";
|
||||
import InputNumber from "@/components/base/InputNumber.vue";
|
||||
import dayjs from "dayjs";
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
@@ -38,8 +38,7 @@ interface Plan {
|
||||
}
|
||||
|
||||
let loading = $ref(false);
|
||||
let showPayDialog = $ref(false);
|
||||
let selectedPaymentMethod = $ref('wechat')
|
||||
let selectedPaymentMethod = $ref('alipay')
|
||||
let selectedPlanId = $ref('')
|
||||
let duration = $ref(1)
|
||||
const member = $computed<User['member']>(() => userStore.user?.member ?? {} as any)
|
||||
@@ -80,11 +79,11 @@ const plans: Plan[] = $computed(() => {
|
||||
|
||||
// Payment methods - WeChat and Alipay
|
||||
const paymentMethods = [
|
||||
{
|
||||
id: 'wechat',
|
||||
name: '微信支付',
|
||||
description: '使用微信支付'
|
||||
},
|
||||
// {
|
||||
// id: 'wechat',
|
||||
// name: '微信支付',
|
||||
// description: '使用微信支付'
|
||||
// },
|
||||
{
|
||||
id: 'alipay',
|
||||
name: '支付宝',
|
||||
@@ -118,35 +117,35 @@ const enoughDiscount = $computed(() => {
|
||||
})
|
||||
|
||||
const endPrice = $computed(() => {
|
||||
if (!coupon.is_valid) {
|
||||
return Number(originalPrice.toFixed(2))
|
||||
}
|
||||
|
||||
if (coupon.type === 'free_trial') return 0
|
||||
|
||||
if (!enoughDiscount) {
|
||||
return Number(originalPrice.toFixed(2))
|
||||
}
|
||||
|
||||
let discountAmount = 0
|
||||
if (coupon.type === 'discount') {
|
||||
// Discount coupon: e.g., 0.8 means 20% off
|
||||
const discountRate = Number(coupon.value)
|
||||
discountAmount = originalPrice * (1 - discountRate)
|
||||
|
||||
// Apply max_discount limit if available
|
||||
if (coupon.max_discount) {
|
||||
const maxDiscount = Number(coupon.max_discount)
|
||||
discountAmount = Math.min(discountAmount, maxDiscount)
|
||||
}
|
||||
} else if (coupon.type === 'amount') {
|
||||
// Amount coupon: fixed amount off
|
||||
discountAmount = Number(coupon.value)
|
||||
}
|
||||
|
||||
const finalPrice = Math.max(originalPrice - discountAmount, 0)
|
||||
return finalPrice.toFixed(2)
|
||||
if (!coupon.is_valid) {
|
||||
return Number(originalPrice.toFixed(2))
|
||||
}
|
||||
|
||||
if (coupon.type === 'free_trial') return 0
|
||||
|
||||
if (!enoughDiscount) {
|
||||
return Number(originalPrice.toFixed(2))
|
||||
}
|
||||
|
||||
let discountAmount = 0
|
||||
if (coupon.type === 'discount') {
|
||||
// Discount coupon: e.g., 0.8 means 20% off
|
||||
const discountRate = Number(coupon.value)
|
||||
discountAmount = originalPrice * (1 - discountRate)
|
||||
|
||||
// Apply max_discount limit if available
|
||||
if (coupon.max_discount) {
|
||||
const maxDiscount = Number(coupon.max_discount)
|
||||
discountAmount = Math.min(discountAmount, maxDiscount)
|
||||
}
|
||||
} else if (coupon.type === 'amount') {
|
||||
// Amount coupon: fixed amount off
|
||||
discountAmount = Number(coupon.value)
|
||||
}
|
||||
|
||||
const finalPrice = Math.max(originalPrice - discountAmount, 0)
|
||||
return finalPrice.toFixed(2)
|
||||
}
|
||||
)
|
||||
|
||||
const startDate = $computed(() => {
|
||||
@@ -233,27 +232,14 @@ onUnmounted(() => {
|
||||
})
|
||||
|
||||
async function handlePayment() {
|
||||
// const win = window.open('about:blank');
|
||||
let win = window.open('about:blank')
|
||||
let res1 = await testPay()
|
||||
console.log('re', res1)
|
||||
if (res1.success) {
|
||||
// win.document.write(res1.data as string);
|
||||
// win.document.close();
|
||||
showPayDialog = true
|
||||
_nextTick(() => {
|
||||
// 2. 找到 iframe
|
||||
const iframe = document.getElementById('payFrame');
|
||||
|
||||
// 3. 写入 form 字符串
|
||||
const doc = iframe.contentWindow.document;
|
||||
doc.open();
|
||||
doc.write(res1.data); // 写入 form
|
||||
doc.close(); // form 会自动提交
|
||||
})
|
||||
win.document.write(res1.data as string);
|
||||
win.document.close();
|
||||
}
|
||||
return
|
||||
|
||||
if (loading) return
|
||||
if (loading || startLoop) return
|
||||
loading = true
|
||||
let data = {
|
||||
plan: selectedPlanId,
|
||||
@@ -262,9 +248,17 @@ async function handlePayment() {
|
||||
couponCode: coupon.is_valid ? coupon.code : undefined
|
||||
}
|
||||
let res = await orderCreate(data)
|
||||
console.log('res', res)
|
||||
if (res.success) {
|
||||
_nextTick(() => {
|
||||
const iframe = document.getElementById('payFrame');
|
||||
const doc = iframe.contentWindow.document;
|
||||
doc.open();
|
||||
doc.write(res.data.result); // 写入 form
|
||||
doc.close(); // form 会自动提交
|
||||
startLoop = true
|
||||
})
|
||||
orderNo = res.data.orderNo
|
||||
startLoop = true
|
||||
} else {
|
||||
Toast.error(res.msg || '付款失败')
|
||||
}
|
||||
@@ -275,7 +269,7 @@ let couponLoading = $ref(false)
|
||||
|
||||
async function getCouponInfo() {
|
||||
if (showCouponInput) {
|
||||
if (!coupon.code) return
|
||||
if (!coupon.code) return Toast.info('请输入优惠券')
|
||||
if (couponLoading) return
|
||||
couponLoading = true
|
||||
let res = await couponInfo(coupon)
|
||||
@@ -332,8 +326,8 @@ async function getCouponInfo() {
|
||||
<span>自动续费已开启</span>
|
||||
</div>
|
||||
<PopConfirm
|
||||
title="确认取消?"
|
||||
@confirm="toggleAutoRenew"
|
||||
title="确认取消?"
|
||||
@confirm="toggleAutoRenew"
|
||||
>
|
||||
<BaseButton size="small" type="info" :loading="loading2">关闭</BaseButton>
|
||||
</PopConfirm>
|
||||
@@ -373,28 +367,16 @@ async function getCouponInfo() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<teleport to="body">
|
||||
<div class="pay-dialog center" v-if="showPayDialog">
|
||||
<div class="mask"></div>
|
||||
<div class="z-9999 relative">
|
||||
<iframe id="payFrame" class="w-[205px] h-[205px] bg-red center"></iframe>
|
||||
<IconFluentDismiss20Regular @click="showPayDialog = false"
|
||||
class="close cp text-2xl absolute -top-10 -right-10"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</teleport>
|
||||
|
||||
<div id="pay" class="mb-50" v-if="selectedPlanId">
|
||||
<div id="pay" class="mb-50">
|
||||
<!-- Page Header -->
|
||||
<div class="text-center mb-6">
|
||||
<h1 class="text-xl font-semibold mb-2">安全支付</h1>
|
||||
<p class="">选择支付方式完成订单</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="center">
|
||||
<div class="card-white w-7/10">
|
||||
<div class="card-white w-5/10">
|
||||
<div class="flex items-center justify-between gap-6 ">
|
||||
<div class="center gap-2" v-if="!showCouponInput">
|
||||
<IconStreamlineDiscountPercentCoupon/>
|
||||
@@ -403,6 +385,7 @@ async function getCouponInfo() {
|
||||
<BaseInput v-else v-model="coupon.code"
|
||||
placeholder="请输入优惠券"
|
||||
autofocus
|
||||
clearable
|
||||
@enter="getCouponInfo"
|
||||
/>
|
||||
<BaseButton size="large"
|
||||
@@ -431,9 +414,8 @@ async function getCouponInfo() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div class="grid grid-cols-3 gap-8">
|
||||
<!-- Left Card: Payment Method Selection -->
|
||||
<div class="card-white">
|
||||
<div class="text-lg font-medium mb-4">选择支付方式</div>
|
||||
@@ -512,6 +494,23 @@ async function getCouponInfo() {
|
||||
付款
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
<!-- Right Card: Order Summary -->
|
||||
<div class="card-white flex flex-col">
|
||||
<div class="text-lg font-semibold mb-4">扫码支付</div>
|
||||
<div class="center flex-col relative flex-1">
|
||||
<div class="center h-full w-full absolute left-0 top-0 bg-white z-2" v-if="!startLoop">
|
||||
<div class="w-5/10">
|
||||
请点击左侧付款按钮后,支付二维码将自动显示
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iframe id="payFrame" class="w-[205px] h-[205px] center border-none"></iframe>
|
||||
<div class="text-center mt-4">
|
||||
请使用支付宝扫码支付
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user