save
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -65,6 +65,7 @@ declare module 'vue' {
|
||||
IconFluentEyeOff16Regular: typeof import('~icons/fluent/eye-off16-regular')['default']
|
||||
IconFluentHome20Regular: typeof import('~icons/fluent/home20-regular')['default']
|
||||
IconFluentKeyboardLayoutFloat20Regular: typeof import('~icons/fluent/keyboard-layout-float20-regular')['default']
|
||||
IconFluentMail20Regular: typeof import('~icons/fluent/mail20-regular')['default']
|
||||
IconFluentMyLocation20Regular: typeof import('~icons/fluent/my-location20-regular')['default']
|
||||
IconFluentPaddingLeft20Regular: typeof import('~icons/fluent/padding-left20-regular')['default']
|
||||
IconFluentPerson20Regular: typeof import('~icons/fluent/person20-regular')['default']
|
||||
|
||||
22687
package-lock.json
generated
22687
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"file-saver": "^2.0.5",
|
||||
"idb-keyval": "^6.2.2",
|
||||
"lucide-vue-next": "^0.553.0",
|
||||
"md5": "^2.2.1",
|
||||
"mitt": "^3.0.1",
|
||||
"nanoid": "^5.1.5",
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -32,6 +32,9 @@ importers:
|
||||
idb-keyval:
|
||||
specifier: ^6.2.2
|
||||
version: 6.2.2
|
||||
lucide-vue-next:
|
||||
specifier: ^0.553.0
|
||||
version: 0.553.0(vue@3.5.18(typescript@5.9.2))
|
||||
md5:
|
||||
specifier: ^2.2.1
|
||||
version: 2.3.0
|
||||
@@ -2594,6 +2597,11 @@ packages:
|
||||
lru-cache@5.1.1:
|
||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||
|
||||
lucide-vue-next@0.553.0:
|
||||
resolution: {integrity: sha512-0tg9XT+VCElTT+7EXXbBRhWe1nU7Doa32Xv/dHP5/LCleFVgV6cAqziM3C7AetqmsYIsfAtNwRYdtvs4Ds7aUg==}
|
||||
peerDependencies:
|
||||
vue: '>=3.0.1'
|
||||
|
||||
magic-string-ast@0.7.1:
|
||||
resolution: {integrity: sha512-ub9iytsEbT7Yw/Pd29mSo/cNQpaEu67zR1VVcXDiYjSFwzeBxNdTd0FMnSslLQXiRj8uGPzwsaoefrMD5XAmdw==}
|
||||
engines: {node: '>=16.14.0'}
|
||||
@@ -6504,6 +6512,10 @@ snapshots:
|
||||
dependencies:
|
||||
yallist: 3.1.1
|
||||
|
||||
lucide-vue-next@0.553.0(vue@3.5.18(typescript@5.9.2)):
|
||||
dependencies:
|
||||
vue: 3.5.18(typescript@5.9.2)
|
||||
|
||||
magic-string-ast@0.7.1:
|
||||
dependencies:
|
||||
magic-string: 0.30.17
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import http from '@/utils/http.ts'
|
||||
import {CodeType} from "@/types/types.ts";
|
||||
import { CodeType } from "@/types/types.ts";
|
||||
|
||||
// 用户登录接口
|
||||
export interface LoginParams {
|
||||
@@ -86,3 +86,8 @@ export function refreshToken() {
|
||||
export function getUserInfo() {
|
||||
return http<LoginResponse['user']>('user/userInfo', null, null, 'get')
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
export function setPassword(password: string) {
|
||||
return http('user/setPassword', {password}, null, 'post')
|
||||
}
|
||||
|
||||
@@ -219,12 +219,12 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link{
|
||||
.link {
|
||||
color: var(--color-link);
|
||||
@apply hover:opacity-80;
|
||||
}
|
||||
|
||||
.cp{
|
||||
.cp {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
@@ -422,6 +422,8 @@ a {
|
||||
.line {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--color-item-border);
|
||||
@apply hover:text-blue-700;
|
||||
|
||||
}
|
||||
|
||||
.line-white {
|
||||
|
||||
@@ -62,7 +62,7 @@ defineEmits(['click'])
|
||||
color: white;
|
||||
|
||||
& + .base-button {
|
||||
margin-left: var(--space);
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
||||
@@ -33,7 +33,7 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'input', 'change', 'focus', 'blur', 'validation']);
|
||||
const emit = defineEmits(['update:modelValue', 'input', 'change', 'focus', 'blur', 'validation', 'enter']);
|
||||
const attrs = useAttrs();
|
||||
|
||||
const inputValue = ref(props.modelValue);
|
||||
@@ -78,6 +78,10 @@ const onBlur = (e: FocusEvent) => {
|
||||
emit('blur', e);
|
||||
};
|
||||
|
||||
const onEnter = (e: KeyboardEvent) => {
|
||||
emit('enter', e);
|
||||
};
|
||||
|
||||
const clearInput = () => {
|
||||
inputValue.value = '';
|
||||
emit('update:modelValue', '');
|
||||
@@ -112,6 +116,7 @@ const vFocus = {
|
||||
@change="onChange"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@keydown.enter="onEnter"
|
||||
class="inner"
|
||||
v-focus="autofocus"
|
||||
:maxlength="maxLength"
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import {computed, ref} from 'vue'
|
||||
import {Calendar, ChevronRight, CreditCard, Crown, Mail, User} from 'lucide-vue-next'
|
||||
import {useAuthStore} from '@/stores/auth.ts'
|
||||
import {useRouter} from 'vue-router'
|
||||
import { computed, ref } from 'vue'
|
||||
import { Calendar, CreditCard, Crown } from 'lucide-vue-next'
|
||||
import { useAuthStore } from '@/stores/auth.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import BaseInput from '@/components/base/BaseInput.vue'
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {APP_NAME, GITHUB} from "@/config/env.ts";
|
||||
import { APP_NAME, GITHUB } from "@/config/env.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import { PASSWORD_CONFIG } from "@/config/auth.ts";
|
||||
import { setPassword } from "@/apis/user.ts";
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const router = useRouter()
|
||||
@@ -33,11 +35,6 @@ const isEditingUsername = ref(false)
|
||||
const isEditingEmail = ref(false)
|
||||
const showPasswordSection = ref(false)
|
||||
|
||||
// Handlers
|
||||
const handleLogin = () => {
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
authStore.logout()
|
||||
router.push('/login')
|
||||
@@ -82,227 +79,214 @@ const contactSupport = () => {
|
||||
const leaveTrustpilotReview = () => {
|
||||
window.open(GITHUB + '/issues', '_blank')
|
||||
}
|
||||
|
||||
async function changePassword(e) {
|
||||
let res = await setPassword(e.target.value)
|
||||
//todo
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasePage>
|
||||
<!-- Unauthenticated View -->
|
||||
<div v-if="!isLoggedIn" class="w-full max-w-md">
|
||||
<div class="bg-white rounded-2xl shadow-lg p-8 text-center">
|
||||
<div class="mb-8">
|
||||
<div class="w-20 h-20 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<User class="w-10 h-10 text-blue-600"/>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">欢迎使用</h1>
|
||||
<p class="text-gray-600">请登录以管理您的账户</p>
|
||||
<div v-if="isLoggedIn" class="center h-screen">
|
||||
<div class="card shadow-lg text-center flex-col gap-6 w-100 ">
|
||||
<div class="w-20 h-20 bg-blue-100 rounded-full center mx-auto">
|
||||
<IconFluentPerson20Regular class="text-3xl text-blue-600"/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click="handleLogin"
|
||||
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-6 rounded-xl transition-colors duration-200 mb-4"
|
||||
<h1 class="text-2xl font-bold">欢迎使用</h1>
|
||||
<p class="">请登录以管理您的账户</p>
|
||||
<BaseButton
|
||||
@click="router.push('/login')"
|
||||
size="large"
|
||||
class="w-full mt-4"
|
||||
>
|
||||
登录
|
||||
</button>
|
||||
|
||||
</BaseButton>
|
||||
<p class="text-sm text-gray-500">
|
||||
还没有账户?
|
||||
<a href="#" class="text-blue-600 hover:text-blue-700 font-medium">立即注册</a>
|
||||
<router-link to="/login" class="line">立即注册</router-link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Authenticated View -->
|
||||
<div v-else class="w-full max-w-4xl">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<!-- Main Account Settings -->
|
||||
<div class="lg:col-span-2">
|
||||
<div class="card">
|
||||
<!-- Header -->
|
||||
<div class="px-6 border-b border-gray-200">
|
||||
<h1 class="text-xl font-bold text-gray-900">帐户</h1>
|
||||
</div>
|
||||
|
||||
<!-- Username Section -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">用户名</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<User class="w-4 h-4 text-gray-500"/>
|
||||
<BaseInput
|
||||
v-if="isEditingUsername"
|
||||
v-model="username"
|
||||
type="text"
|
||||
size="normal"
|
||||
@blur="saveUsername"
|
||||
@keyup.enter="saveUsername"
|
||||
class="flex-1 max-w-xs"
|
||||
autofocus
|
||||
/>
|
||||
<span v-else class="text-gray-900">{{ username }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<IconFluentTextEditStyle20Regular
|
||||
@click="isEditingUsername ? saveUsername() : editUsername()"
|
||||
class="text-xl"/>
|
||||
</div>
|
||||
<div class="border-t border-gray-200"></div>
|
||||
|
||||
<!-- Email Section -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">电子邮箱</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<Mail class="w-4 h-4 text-gray-500"/>
|
||||
<BaseInput
|
||||
v-if="isEditingEmail"
|
||||
v-model="email"
|
||||
type="email"
|
||||
size="normal"
|
||||
@blur="saveEmail"
|
||||
@keyup.enter="saveEmail"
|
||||
class="flex-1 max-w-xs"
|
||||
autofocus
|
||||
/>
|
||||
<span v-else class="text-gray-900">{{ email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<IconFluentTextEditStyle20Regular
|
||||
@click="isEditingEmail ? saveEmail() : editEmail()"
|
||||
class="text-xl"/>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-200"></div>
|
||||
|
||||
<!-- Password Section -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">设置密码</div>
|
||||
<div class="text-sm text-gray-500">在此输入密码</div>
|
||||
</div>
|
||||
<IconFluentChevronLeft28Filled @click="showPasswordSection = !showPasswordSection"
|
||||
class="transition-transform"
|
||||
:class="['rotate-270','rotate-180'][showPasswordSection?0:1]"/>
|
||||
</div>
|
||||
<div class="border-t border-gray-200"></div>
|
||||
|
||||
<!-- Notification Toggle -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">同意接收优惠信息</div>
|
||||
<div class="text-sm text-gray-500">第一时间掌握 Lingvist 的各种优惠及最新消息。</div>
|
||||
</div>
|
||||
<button
|
||||
@click="toggleNotifications"
|
||||
class="relative inline-flex h-6 w-11 items-center rounded-full transition-colors"
|
||||
:class="receiveNotifications ? 'bg-blue-600' : 'bg-gray-200'"
|
||||
>
|
||||
<span
|
||||
class="inline-block h-4 w-4 transform rounded-full bg-white transition-transform"
|
||||
:class="receiveNotifications ? 'translate-x-6' : 'translate-x-1'"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="border-t border-gray-200"></div>
|
||||
|
||||
|
||||
<!-- Contact Support -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors cursor-pointer"
|
||||
@click="contactSupport">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">联系{{ APP_NAME }}客服</div>
|
||||
</div>
|
||||
<ChevronRight class="w-5 h-5 text-gray-400"/>
|
||||
</div>
|
||||
<div class="border-t border-gray-200"></div>
|
||||
|
||||
<!-- Trustpilot Review -->
|
||||
<div class="px-6 py-4 flex items-center justify-between hover:bg-gray-50 transition-colors cursor-pointer"
|
||||
@click="leaveTrustpilotReview">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">在 {{ APP_NAME }} 上留下评论</div>
|
||||
</div>
|
||||
<ChevronRight class="w-5 h-5 text-gray-400"/>
|
||||
</div>
|
||||
|
||||
<!-- Logout Button -->
|
||||
<div class="px-6 py-6 border-t border-gray-200">
|
||||
<button
|
||||
@click="handleLogout"
|
||||
class="w-full bg-gray-800 hover:bg-gray-900 text-white font-semibold py-3 px-6 rounded-xl transition-colors duration-200"
|
||||
>
|
||||
登出
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Footer Links -->
|
||||
<div class="px-6 py-4 border-t border-gray-200 text-center">
|
||||
<div class="text-sm text-gray-500">
|
||||
<a href="/user-agreement.html" class="text-gray-500 hover:text-gray-700 underline">用户协议</a>
|
||||
、
|
||||
<a href="/privacy-policy.html" class="text-gray-500 hover:text-gray-700 underline">隐私政策</a>
|
||||
</div>
|
||||
<div v-else class="w-full flex items-start gap-4">
|
||||
<!-- Main Account Settings -->
|
||||
<div class="card flex-1 flex flex-col gap-2 px-8">
|
||||
<h1 class="text-xl font-bold">帐户</h1>
|
||||
<!-- Username Section -->
|
||||
<div class="flex items-center justify-between ">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">用户名</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<IconFluentPerson20Regular class="text-base text-gray-500"/>
|
||||
<BaseInput
|
||||
v-if="isEditingUsername"
|
||||
v-model="username"
|
||||
type="text"
|
||||
size="normal"
|
||||
@blur="saveUsername"
|
||||
@keyup.enter="saveUsername"
|
||||
class="flex-1 max-w-xs"
|
||||
autofocus
|
||||
/>
|
||||
<span v-else class="text-gray-900">{{ username }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<IconFluentTextEditStyle20Regular
|
||||
@click="isEditingUsername ? saveUsername() : editUsername()"
|
||||
class="text-xl"/>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
|
||||
<!-- Email Section -->
|
||||
<div class="flex items-center justify-between ">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">电子邮箱</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<IconFluentMail20Regular class="text-base text-gray-500"/>
|
||||
<BaseInput
|
||||
v-if="isEditingEmail"
|
||||
v-model="email"
|
||||
type="email"
|
||||
size="normal"
|
||||
@blur="saveEmail"
|
||||
@keyup.enter="saveEmail"
|
||||
class="flex-1 max-w-xs"
|
||||
autofocus
|
||||
/>
|
||||
<span v-else class="text-gray-900">{{ email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<IconFluentTextEditStyle20Regular
|
||||
@click="isEditingEmail ? saveEmail() : editEmail()"
|
||||
class="text-xl"/>
|
||||
</div>
|
||||
|
||||
<!-- Subscription Information -->
|
||||
<div class="lg:col-span-1">
|
||||
<div class="card">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<Crown class="w-6 h-6 text-yellow-500"/>
|
||||
<h2 class="text-lg font-bold text-gray-900">订阅信息</h2>
|
||||
<div class="line"></div>
|
||||
|
||||
<!-- Password Section -->
|
||||
<div class="flex items-center justify-between cp"
|
||||
@click="showPasswordSection = !showPasswordSection"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">设置密码</div>
|
||||
<div class="text-xs text-gray-500">在此输入密码</div>
|
||||
</div>
|
||||
<IconFluentChevronLeft28Filled
|
||||
class="transition-transform"
|
||||
:class="['rotate-270','rotate-180'][showPasswordSection?0:1]"/>
|
||||
</div>
|
||||
<div v-if="showPasswordSection">
|
||||
<BaseInput placeholder="新密码"
|
||||
type="password"
|
||||
autofocus
|
||||
:min="PASSWORD_CONFIG.minLength"
|
||||
:max="PASSWORD_CONFIG.maxLength"/>
|
||||
<div class="text-align-end mt-4">
|
||||
<BaseButton type="info" @click="showPasswordSection = !showPasswordSection">取消</BaseButton>
|
||||
<BaseButton @click="changePassword">保存</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
<!-- Contact Support -->
|
||||
<div class="flex py-2 items-center justify-between cp"
|
||||
@click="contactSupport">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">联系 {{ APP_NAME }} 客服</div>
|
||||
</div>
|
||||
<IconFluentChevronLeft28Filled class="rotate-180"/>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
<!-- Trustpilot Review -->
|
||||
<div class="flex py-2 items-center justify-between cp"
|
||||
@click="leaveTrustpilotReview">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium text-gray-700 mb-1">在 {{ APP_NAME }} 上留下评论</div>
|
||||
</div>
|
||||
<IconFluentChevronLeft28Filled class="rotate-180"/>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
<!-- Logout Button -->
|
||||
<div class="center w-full">
|
||||
<BaseButton
|
||||
@click="handleLogout"
|
||||
size="large"
|
||||
class="w-[80%]"
|
||||
>
|
||||
登出
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
<div class="text-xs text-center">
|
||||
<a href="/user-agreement.html" target="_blank" class="text-gray-500 hover:text-gray-700">用户协议</a>
|
||||
、
|
||||
<a href="/privacy-policy.html" target="_blank" class="text-gray-500 hover:text-gray-700">隐私政策</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Subscription Information -->
|
||||
<div class="card w-80">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<Crown class="w-6 h-6 text-yellow-500"/>
|
||||
<h2 class="text-lg font-bold text-gray-900">订阅信息</h2>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">当前计划</div>
|
||||
<div class="text-lg font-semibold text-gray-900">{{ subscriptionData.plan }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">状态</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||
<span class="text-sm font-medium text-green-700">{{
|
||||
subscriptionData.status === 'active' ? '活跃' : '已过期'
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">当前计划</div>
|
||||
<div class="text-lg font-semibold text-gray-900">{{ subscriptionData.plan }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">到期时间</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Calendar class="w-4 h-4 text-gray-400"/>
|
||||
<span class="text-sm font-medium text-gray-900">{{ subscriptionData.expiresAt }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">状态</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||
<span class="text-sm font-medium text-green-700">{{
|
||||
subscriptionData.status === 'active' ? '活跃' : '已过期'
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">到期时间</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Calendar class="w-4 h-4 text-gray-400"/>
|
||||
<span class="text-sm font-medium text-gray-900">{{ subscriptionData.expiresAt }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">自动续费</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-2 h-2" :class="subscriptionData.autoRenew ? 'bg-blue-500' : 'bg-gray-400'"
|
||||
rounded-full></div>
|
||||
<span class="text-sm font-medium"
|
||||
:class="subscriptionData.autoRenew ? 'text-blue-700' : 'text-gray-600'">
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">自动续费</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-2 h-2" :class="subscriptionData.autoRenew ? 'bg-blue-500' : 'bg-gray-400'"
|
||||
rounded-full></div>
|
||||
<span class="text-sm font-medium"
|
||||
:class="subscriptionData.autoRenew ? 'text-blue-700' : 'text-gray-600'">
|
||||
{{ subscriptionData.autoRenew ? '已开启' : '已关闭' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">付款方式</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<CreditCard class="w-4 h-4 text-gray-400"/>
|
||||
<span class="text-sm font-medium text-gray-900">{{ subscriptionData.paymentMethod }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4 border-t border-gray-200">
|
||||
<BaseButton class="w-full">管理订阅</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-500 mb-1">付款方式</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<CreditCard class="w-4 h-4 text-gray-400"/>
|
||||
<span class="text-sm font-medium text-gray-900">{{ subscriptionData.paymentMethod }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4 border-t border-gray-200">
|
||||
<BaseButton class="w-full">管理订阅</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user