This commit is contained in:
张成
2025-12-22 16:26:59 +08:00
parent aa2d03ee30
commit e17d5610f5
54 changed files with 11735 additions and 3 deletions

501
app/views/PurchasePage.vue Normal file
View 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>