1
This commit is contained in:
501
app/views/PurchasePage.vue
Normal file
501
app/views/PurchasePage.vue
Normal file
@@ -0,0 +1,501 @@
|
||||
<template>
|
||||
<div class="page-purchase">
|
||||
<h2 class="page-title">如何购买</h2>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<div class="contact-section">
|
||||
<Card class="contact-card">
|
||||
<template #title>联系购买</template>
|
||||
<template #content>
|
||||
<p class="contact-desc">扫描下方二维码或添加微信号联系我们</p>
|
||||
<div class="contact-content">
|
||||
<div class="qr-code-wrapper">
|
||||
<div class="qr-code-placeholder">
|
||||
<img v-if="wechatQRCode" :src="wechatQRCode" alt="微信二维码" class="qr-code-image" />
|
||||
<div v-else class="qr-code-placeholder-text">
|
||||
<span>微信二维码</span>
|
||||
<small>请上传二维码图片</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-info">
|
||||
<div class="info-item">
|
||||
<span class="info-label">微信号:</span>
|
||||
<span class="info-value">{{ wechatNumber }}</span>
|
||||
<Button label="复制" size="small" @click="handleCopyWechat" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<!-- 价格套餐 -->
|
||||
<div class="pricing-section">
|
||||
<h3 class="section-title">价格套餐</h3>
|
||||
<div class="pricing-grid">
|
||||
<Card
|
||||
v-for="plan in pricingPlans"
|
||||
:key="plan.id"
|
||||
:class="['pricing-card', { 'featured': plan.featured }]"
|
||||
>
|
||||
<template #header>
|
||||
<Badge v-if="plan.featured" value="推荐" severity="success" />
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="plan-header">
|
||||
<h4 class="plan-name">{{ plan.name }}</h4>
|
||||
<div class="plan-duration">{{ plan.duration }}</div>
|
||||
</div>
|
||||
<div class="plan-price">
|
||||
<div v-if="plan.originalPrice && plan.originalPrice > plan.price" class="original-price">
|
||||
<span class="original-price-text">原价 ¥{{ plan.originalPrice }}</span>
|
||||
</div>
|
||||
<div class="current-price">
|
||||
<span class="price-symbol">¥</span>
|
||||
<span class="price-amount">{{ plan.price }}</span>
|
||||
<span class="price-unit" v-if="plan.unit">{{ plan.unit }}</span>
|
||||
</div>
|
||||
<Badge v-if="plan.discount" :value="plan.discount" severity="danger" class="discount-badge" />
|
||||
</div>
|
||||
<div class="plan-features">
|
||||
<div class="feature-item" v-for="feature in plan.features" :key="feature">
|
||||
<span class="feature-icon">✓</span>
|
||||
<span>{{ feature }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plan-action">
|
||||
<Button label="立即购买" @click="handleContact(plan)" class="btn-full-width" />
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 购买说明 -->
|
||||
<div class="notice-section">
|
||||
<Card class="notice-card">
|
||||
<template #title>购买说明</template>
|
||||
<template #content>
|
||||
<ul class="notice-list">
|
||||
<li>购买后请联系客服激活账号</li>
|
||||
<li>终生套餐享受永久使用权限</li>
|
||||
<li>如有疑问,请添加微信号咨询</li>
|
||||
</ul>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<!-- 成功提示 -->
|
||||
<Message
|
||||
v-if="showSuccess"
|
||||
severity="success"
|
||||
:closable="true"
|
||||
@close="showSuccess = false"
|
||||
class="success-message"
|
||||
>
|
||||
{{ successMessage }}
|
||||
</Message>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import configAPI from '../api/config.js';
|
||||
import { Card, Button, Badge, Message } from '../components/PrimeVue';
|
||||
import logMixin from '../mixins/logMixin.js';
|
||||
|
||||
export default {
|
||||
name: 'PurchasePage',
|
||||
mixins: [logMixin],
|
||||
components: {
|
||||
Card,
|
||||
Button,
|
||||
Badge,
|
||||
Message
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
wechatNumber: '', // 从配置中获取
|
||||
wechatQRCode: '', // 从配置中获取
|
||||
showSuccess: false,
|
||||
successMessage: '',
|
||||
loading: false,
|
||||
pricingPlans: [] // 从接口获取
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.loadWechatConfig();
|
||||
this.loadPricingPlans();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 加载微信配置
|
||||
*/
|
||||
async loadWechatConfig() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const config = await configAPI.getWechatConfig();
|
||||
if (config.wechatNumber) {
|
||||
this.wechatNumber = config.wechatNumber;
|
||||
}
|
||||
if (config.wechatQRCode) {
|
||||
this.wechatQRCode = config.wechatQRCode;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载微信配置失败:', error);
|
||||
if (this.addLog) {
|
||||
this.addLog('error', '加载微信配置失败: ' + (error.message || '未知错误'));
|
||||
}
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 加载价格套餐列表
|
||||
*/
|
||||
async loadPricingPlans() {
|
||||
try {
|
||||
const plans = await configAPI.getPricingPlans();
|
||||
if (plans && plans.length > 0) {
|
||||
this.pricingPlans = plans;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载价格套餐失败:', error);
|
||||
if (this.addLog) {
|
||||
this.addLog('error', '加载价格套餐失败: ' + (error.message || '未知错误'));
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 复制微信号
|
||||
*/
|
||||
async handleCopyWechat() {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.clipboard) {
|
||||
await window.electronAPI.clipboard.writeText(this.wechatNumber);
|
||||
this.showSuccessMessage('微信号已复制到剪贴板');
|
||||
} else {
|
||||
throw new Error('electronAPI 不可用,无法复制');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('复制失败:', error);
|
||||
if (this.addLog) {
|
||||
this.addLog('error', '复制失败: ' + (error.message || '未知错误'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 联系购买
|
||||
*/
|
||||
handleContact(plan) {
|
||||
const message = `我想购买【${plan.name}】(${plan.duration}),价格:¥${plan.price}${plan.unit}`;
|
||||
this.showSuccessMessage(`请添加微信号 ${this.wechatNumber} 并发送:"${message}"`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示成功消息
|
||||
*/
|
||||
showSuccessMessage(message) {
|
||||
this.successMessage = message;
|
||||
this.showSuccess = true;
|
||||
setTimeout(() => {
|
||||
this.showSuccess = false;
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page-purchase {
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin: 0 0 20px 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contact-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.contact-desc {
|
||||
text-align: center;
|
||||
margin: 0 0 15px 0;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.contact-content {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.qr-code-wrapper {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.qr-code-placeholder {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: 2px dashed #ddd;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fafafa;
|
||||
|
||||
.qr-code-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.qr-code-placeholder-text {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
small {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 6px;
|
||||
|
||||
.info-label {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
min-width: 70px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.pricing-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
.pricing-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 15px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.pricing-card {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
&.featured {
|
||||
border: 2px solid #4CAF50;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
margin-bottom: 15px;
|
||||
|
||||
.plan-name {
|
||||
margin: 0 0 6px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.plan-duration {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-price {
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
position: relative;
|
||||
|
||||
.original-price {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.original-price-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.current-price {
|
||||
.price-symbol {
|
||||
font-size: 18px;
|
||||
color: #4CAF50;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.price-amount {
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
color: #4CAF50;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.price-unit {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.discount-badge {
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-features {
|
||||
margin-bottom: 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
|
||||
.feature-icon {
|
||||
color: #4CAF50;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-action {
|
||||
:deep(.p-button) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-section {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
// Card 组件已包含样式
|
||||
}
|
||||
|
||||
.notice-list {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
margin-bottom: 8px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
font-size: 13px;
|
||||
|
||||
&::before {
|
||||
content: '•';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #4CAF50;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-message {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contact-content {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pricing-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.pricing-card.featured {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user