chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
<link href="/static/member/css/common.css" rel="stylesheet" />
<style>
.uc-wrap { max-width: 900px; }
.plan-card { transition: 0.2s; }
.plan-card:hover { box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12); }
.plan-card .layui-card-body h1 { font-size: 34px; color: #009688; margin: 6px 0 12px; }
.plan-card li { line-height: 28px; color: #666; }
#payMethods { margin: 10px 0; }
</style>
<div class="uc-wrap">
<h2 style="text-align: center">选择适合您的套餐</h2>
<br />
<div class="layui-row layui-col-space20" id="planList">
{volist name="plans" id="plan"}
<div class="layui-col-md4">
<div class="layui-card plan-card">
<div class="layui-card-header">{$plan.title}</div>
<div class="layui-card-body">
<h1>¥{$plan.price}<span style="font-size: 16px">/月</span></h1>
<ul>
<li>{$plan.desc}</li>
</ul>
{if $plan.price == 0}
<button class="layui-btn layui-btn-primary layui-btn-fluid" onclick="pay({$plan.id})">当前版本</button>
{else}
<button class="layui-btn layui-btn-danger layui-btn-fluid" onclick="pay({$plan.id})">立即开通</button>
{/if}
</div>
</div>
</div>
{/volist}
</div>
</div>
<!-- 支付方式选择弹窗 -->
<div id="payModal" style="display: none; padding: 20px">
<div id="payMethods"></div>
<div id="payBox" style="margin-top: 15px; text-align: center"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
<script>
layui.use(['layer', 'http', 'form'], function () {
var layer = layui.layer, http = layui.http, form = layui.form, $ = layui.$;
// 套餐价格映射(用于免费判定)
var PLAN_PRICE = {};
{volist name = "plans" id = "plan" }
PLAN_PRICE[{ $plan.id }] = { $plan.price };
{/volist }
var curPlan = 0; // 当前选择的套餐
// 加载可用支付方式(插件通过 PaymentMethods 事件注入)
function loadMethods(cb) {
http.get('methods').then(function (res) {
if (res.code === 0 && res.data && res.data.length) {
cb(res.data);
} else {
layer.msg('暂无可用支付方式,请先安装支付插件', { icon: 2 });
cb([]);
}
}).catch(function () {
layer.msg('支付方式加载失败', { icon: 2 });
cb([]);
});
}
// 对外暴露:点击套餐按钮触发
window.pay = function (planId) {
curPlan = planId;
if (PLAN_PRICE[planId] == 0) {
http.post('create', { plan_id: planId, method: 'free' }).then(function (res) {
if (res.code === 0) { layer.msg('已开通' + (res.data.plan || ''), { icon: 1 }); }
else { layer.msg(res.message || '开通失败', { icon: 2 }); }
});
return;
}
loadMethods(function (methods) {
if (!methods.length) return;
var html = '<div class="layui-form">';
methods.forEach(function (m, i) {
html += '<input type="radio" name="payMethod" value="' + m.code + '" title="' + m.name + '" ' + (i === 0 ? 'checked' : '') + '>'
+ '<div class="layui-word-aux" style="margin:2px 0 10px;">' + (m.desc || '') + '</div>';
});
html += '</div><button class="layui-btn layui-btn-fluid" id="doPay">确认支付</button>';
$('#payMethods').html(html);
$('#payBox').empty();
form.render();
layer.open({ type: 1, title: '选择支付方式', area: '360px', content: $('#payModal') });
});
};
// 确认支付
$(document).on('click', '#doPay', function () {
var method = $('input[name="payMethod"]:checked').val();
http.post('create', { plan_id: curPlan, method: method }).then(function (res) {
if (res.code !== 0) { layer.msg(res.message || '创建订单失败', { icon: 2 }); return; }
var g = res.data || {};
if (g.type === 'error') {
layer.msg(g.message || '支付未配置完成,无法发起支付', { icon: 2 });
return;
}
if (g.type === 'redirect' && g.redirect_url) {
location.href = g.redirect_url;
} else if (g.type === 'qrcode' && g.qrcode_url) {
$('#payBox').empty().append('<div id="qrcode" style="display:inline-block;"></div><p style="color:#f60;margin-top:8px;">请使用' + (method === 'wechat' ? '微信' : '支付宝') + '扫码支付</p>');
new QRCode(document.getElementById('qrcode'), g.qrcode_url);
startPoll(g.order_sn);
} else if (g.type === 'form' && g.html) {
$('#payBox').html(g.html);
} else if (g.type === 'free') {
layer.msg('开通成功', { icon: 1 });
} else {
layer.msg('已生成支付,请按提示完成', { icon: 1 });
}
}).catch(function () { layer.msg('请求失败', { icon: 2 }); });
});
// 轮询订单支付状态。
// 注意:支付查询由各支付插件提供对应接口(如插件暴露 /user/payment/query),
// 框架不写死第三方路径。下方 demo 调用的 /paydemo/pay/query 为开发占位,
// 已在真实环境移除避免 404;接入支付插件后请在此调用插件提供的查询地址。
function startPoll(orderSn) {
if (window.__payTimer) { clearInterval(window.__payTimer); }
window.__payTimer = setInterval(function () {
// TODO: 替换为支付插件提供的订单查询接口(如 url('user/payment/query')
// $.post(url('user/payment/query'), { order_sn: orderSn }, function (r) {
// if (r && r.code === 0 && r.data && r.data.paid) {
// clearInterval(window.__payTimer);
// window.__payTimer = null;
// layer.msg('支付成功,会员已开通', { icon: 1 });
// setTimeout(function () { location.reload(); }, 1200);
// }
// }, 'json');
}, 2000);
}
});
</script>