|
|
@@ -11,6 +11,7 @@ const isGuest = computed(() => {
|
|
|
const emit = defineEmits(["show-login"]);
|
|
|
|
|
|
const showUpgradeDialog = ref(false);
|
|
|
+const showMembershipDialog = ref(false);
|
|
|
const upgradeForm = ref({
|
|
|
name: null,
|
|
|
password: null,
|
|
|
@@ -19,6 +20,20 @@ const upgradeForm = ref({
|
|
|
});
|
|
|
const isLoading = ref(false);
|
|
|
|
|
|
+// 会员购买选项
|
|
|
+const membershipPlans = [
|
|
|
+ { key: "hourly", label: "一小时", price: "1", duration: "1小时" },
|
|
|
+ { key: "daily", label: "一天", price: "10", duration: "1天" },
|
|
|
+ { key: "weekly", label: "一周", price: "60", duration: "7天" },
|
|
|
+ { key: "monthly", label: "一个月", price: "200", duration: "30天" },
|
|
|
+ { key: "quarterly", label: "三个月", price: "500", duration: "90天" },
|
|
|
+ { key: "yearly", label: "一年", price: "1000", duration: "365天" },
|
|
|
+ { key: "lifetime", label: "终身", price: "1500", duration: "永久" },
|
|
|
+];
|
|
|
+
|
|
|
+const selectedPlan = ref("");
|
|
|
+const selectedPayment = ref("alipay");
|
|
|
+
|
|
|
const handleLogout = () => {
|
|
|
userStore.logout();
|
|
|
};
|
|
|
@@ -27,6 +42,24 @@ const showLoginDialog = () => {
|
|
|
emit("show-login");
|
|
|
};
|
|
|
|
|
|
+const handleMembershipPurchase = () => {
|
|
|
+ if (!selectedPlan.value) {
|
|
|
+ alert("请选择会员套餐");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const plan = membershipPlans.find((p) => p.key === selectedPlan.value);
|
|
|
+ console.log("购买会员:", plan, "支付方式:", selectedPayment.value);
|
|
|
+
|
|
|
+ // TODO: 调用支付API
|
|
|
+ alert(
|
|
|
+ `即将跳转到支付页面\n套餐: ${plan?.label}\n价格: ${plan?.price}\n支付方式: 支付宝`
|
|
|
+ );
|
|
|
+
|
|
|
+ showMembershipDialog.value = false;
|
|
|
+ selectedPlan.value = "";
|
|
|
+};
|
|
|
+
|
|
|
const handleUpgrade = async () => {
|
|
|
if (!upgradeForm.value.name || !upgradeForm.value.password) {
|
|
|
alert("请填写用户名和密码");
|
|
|
@@ -109,6 +142,7 @@ const handleUpgrade = async () => {
|
|
|
成为正式用户
|
|
|
</button>
|
|
|
<button
|
|
|
+ @click="showMembershipDialog = true"
|
|
|
class="px-3 py-1.5 rounded-lg bg-brand text-slate-900 text-sm font-medium"
|
|
|
:disabled="isGuest"
|
|
|
:class="{ 'opacity-50 cursor-not-allowed': isGuest }"
|
|
|
@@ -125,18 +159,14 @@ const handleUpgrade = async () => {
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="isLoggedIn" class="grid grid-cols-3 gap-3">
|
|
|
- <button class="stat">
|
|
|
- <strong class="text-lg">6</strong>
|
|
|
- <span>已购</span>
|
|
|
- </button>
|
|
|
+ <div v-if="isLoggedIn" class="grid grid-cols-2 gap-3">
|
|
|
<button class="stat">
|
|
|
<strong class="text-lg">12</strong>
|
|
|
<span>收藏</span>
|
|
|
</button>
|
|
|
<button class="stat">
|
|
|
- <strong class="text-lg">34</strong>
|
|
|
- <span>历史</span>
|
|
|
+ <strong class="text-lg">6</strong>
|
|
|
+ <span>已购</span>
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
@@ -167,56 +197,58 @@ const handleUpgrade = async () => {
|
|
|
class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
|
|
|
@click.self="showUpgradeDialog = false"
|
|
|
>
|
|
|
- <div class="bg-white rounded-2xl p-6 w-full max-w-md mx-4">
|
|
|
- <h3 class="text-xl font-semibold text-gray-900 mb-4">成为正式用户</h3>
|
|
|
+ <div
|
|
|
+ class="bg-surface border border-white/10 rounded-2xl p-6 w-full max-w-md mx-4"
|
|
|
+ >
|
|
|
+ <h3 class="text-xl font-semibold text-white/90 mb-4">成为正式用户</h3>
|
|
|
|
|
|
<form @submit.prevent="handleUpgrade" class="space-y-4">
|
|
|
<div>
|
|
|
- <label class="block text-sm font-medium text-gray-700 mb-1">
|
|
|
- 用户名 <span class="text-red-500">*</span>
|
|
|
+ <label class="block text-sm font-medium text-white/70 mb-1">
|
|
|
+ 用户名 <span class="text-red-400">*</span>
|
|
|
</label>
|
|
|
<input
|
|
|
v-model="upgradeForm.name"
|
|
|
type="text"
|
|
|
required
|
|
|
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
+ class="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/40 focus:ring-2 focus:ring-brand focus:border-transparent"
|
|
|
placeholder="请输入用户名"
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="block text-sm font-medium text-gray-700 mb-1">
|
|
|
- 密码 <span class="text-red-500">*</span>
|
|
|
+ <label class="block text-sm font-medium text-white/70 mb-1">
|
|
|
+ 密码 <span class="text-red-400">*</span>
|
|
|
</label>
|
|
|
<input
|
|
|
v-model="upgradeForm.password"
|
|
|
type="password"
|
|
|
required
|
|
|
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
+ class="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/40 focus:ring-2 focus:ring-brand focus:border-transparent"
|
|
|
placeholder="请输入密码"
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="block text-sm font-medium text-gray-700 mb-1">
|
|
|
+ <label class="block text-sm font-medium text-white/70 mb-1">
|
|
|
邮箱
|
|
|
</label>
|
|
|
<input
|
|
|
v-model="upgradeForm.email"
|
|
|
type="email"
|
|
|
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
+ class="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/40 focus:ring-2 focus:ring-brand focus:border-transparent"
|
|
|
placeholder="请输入邮箱(可选)"
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="block text-sm font-medium text-gray-700 mb-1">
|
|
|
+ <label class="block text-sm font-medium text-white/70 mb-1">
|
|
|
手机号
|
|
|
</label>
|
|
|
<input
|
|
|
v-model="upgradeForm.phone"
|
|
|
type="tel"
|
|
|
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
+ class="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white placeholder-white/40 focus:ring-2 focus:ring-brand focus:border-transparent"
|
|
|
placeholder="请输入手机号(可选)"
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -225,14 +257,14 @@ const handleUpgrade = async () => {
|
|
|
<button
|
|
|
type="button"
|
|
|
@click="showUpgradeDialog = false"
|
|
|
- class="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition"
|
|
|
+ class="flex-1 px-4 py-2 border border-white/20 text-white/70 rounded-lg hover:bg-white/5 transition"
|
|
|
>
|
|
|
取消
|
|
|
</button>
|
|
|
<button
|
|
|
type="submit"
|
|
|
:disabled="isLoading"
|
|
|
- class="flex-1 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition disabled:opacity-50"
|
|
|
+ class="flex-1 px-4 py-2 bg-brand text-slate-900 rounded-lg hover:bg-brand/90 transition disabled:opacity-50"
|
|
|
>
|
|
|
{{ isLoading ? "处理中..." : "确认升级" }}
|
|
|
</button>
|
|
|
@@ -240,6 +272,107 @@ const handleUpgrade = async () => {
|
|
|
</form>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 会员购买弹窗 -->
|
|
|
+ <div
|
|
|
+ v-if="showMembershipDialog"
|
|
|
+ class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
|
|
|
+ @click.self="showMembershipDialog = false"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="bg-surface border border-white/10 rounded-2xl p-6 w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto"
|
|
|
+ >
|
|
|
+ <h3 class="text-xl font-semibold text-white/90 mb-6 text-center">
|
|
|
+ 开通会员
|
|
|
+ </h3>
|
|
|
+
|
|
|
+ <!-- 会员套餐选择 -->
|
|
|
+ <div class="space-y-2 mb-4">
|
|
|
+ <h4 class="text-sm font-medium text-white/70 mb-2">选择套餐</h4>
|
|
|
+ <div class="grid grid-cols-1 gap-2">
|
|
|
+ <label
|
|
|
+ v-for="plan in membershipPlans"
|
|
|
+ :key="plan.key"
|
|
|
+ class="relative cursor-pointer"
|
|
|
+ >
|
|
|
+ <input
|
|
|
+ v-model="selectedPlan"
|
|
|
+ :value="plan.key"
|
|
|
+ type="radio"
|
|
|
+ name="membership-plan"
|
|
|
+ class="sr-only"
|
|
|
+ />
|
|
|
+ <div
|
|
|
+ class="border-2 rounded-lg p-2 transition-all"
|
|
|
+ :class="
|
|
|
+ selectedPlan === plan.key
|
|
|
+ ? 'border-brand bg-brand/10'
|
|
|
+ : 'border-white/20 hover:border-white/30'
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <div>
|
|
|
+ <div class="font-medium text-white/90 text-sm">
|
|
|
+ {{ plan.label }}
|
|
|
+ </div>
|
|
|
+ <div class="text-xs text-white/60">{{ plan.duration }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="text-right">
|
|
|
+ <div class="font-semibold text-white/90 text-sm">
|
|
|
+ {{ plan.price }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 支付方式选择 -->
|
|
|
+ <div class="space-y-2 mb-4">
|
|
|
+ <h4 class="text-sm font-medium text-white/70 mb-2">支付方式</h4>
|
|
|
+ <div class="space-y-2">
|
|
|
+ <label
|
|
|
+ class="flex items-center p-2 border border-white/20 rounded-lg cursor-pointer hover:bg-white/5"
|
|
|
+ >
|
|
|
+ <input
|
|
|
+ v-model="selectedPayment"
|
|
|
+ value="alipay"
|
|
|
+ type="radio"
|
|
|
+ name="payment-method"
|
|
|
+ class="sr-only"
|
|
|
+ />
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div
|
|
|
+ class="w-8 h-8 bg-blue-500 rounded flex items-center justify-center mr-3"
|
|
|
+ >
|
|
|
+ <span class="text-white text-sm font-bold">支</span>
|
|
|
+ </div>
|
|
|
+ <span class="text-white/90">支付宝</span>
|
|
|
+ </div>
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <div class="flex gap-3 pt-3 border-t border-white/10">
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ @click="showMembershipDialog = false"
|
|
|
+ class="flex-1 px-4 py-2 border border-white/20 text-white/70 rounded-lg hover:bg-white/5 transition"
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleMembershipPurchase"
|
|
|
+ :disabled="!selectedPlan"
|
|
|
+ class="flex-1 px-4 py-2 bg-brand text-slate-900 rounded-lg hover:bg-brand/90 transition disabled:opacity-50 disabled:cursor-not-allowed"
|
|
|
+ >
|
|
|
+ 立即购买
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</section>
|
|
|
</template>
|
|
|
<style scoped>
|