小程序接入支付功能

This commit is contained in:
Yeomai committed 2026-09-29 01:14:24 +08:00
1 parent edf1e51846
commit 07a90e860d
38 files changed
+3644 -90

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
const SITE_URL = 'https://spineviewer.yeomai.site/'
Page({
data: {
stats: [
{ value: '9', label: '内置运行时版本' },
{ value: '3.4–4.3', label: '覆盖的 Spine 版本' },
{ value: '8', label: '界面语言 · 简繁英日韩俄西德' },
{ value: '400px', label: '缩略图自动生成' },
],
fileChips: ['skel', 'skel.bytes', 'json', 'atlas', 'atlas.txt'],
features: [
{
title: '本地运行时',
desc: '官方运行时全部放在插件本地 lib/ 目录,不依赖 CDN 下载。激活校验需要联网,其余预览过程都在本地完成。',
},
{
title: '跨文件夹自动配对',
desc: 'Eagle 把每个文件拆成独立 item 文件夹,插件扫描同级目录自动关联骨骼、atlas 与贴图,忽略 -pro / -ess / -pma 等后缀。',
},
{
title: '9 个版本自动识别',
desc: '从骨骼数据读取版本号并匹配运行时:3.4 / 3.5 / 3.6 / 3.7 / 3.8 / 4.0 / 4.1 / 4.2 / 4.3,带 -beta 的完整版本号也会显示在水印里。',
},
{
title: '画面与皮肤切换',
desc: '浮动播放列表按需自适应、条目多时独立滚动;切换皮肤后按 setup pose 重建槽位附件,画面立即刷新。',
},
{
title: '完整时间轴',
desc: '拖动定位、显示时长与帧号、秒刻度,蓝色短线标出骨骼 / 插槽 / 约束的关键帧位置,悬停即可查看。',
},
{
title: '缩略图自动化',
desc: '导入即渲染首帧缩略图(400×400),右下角带 Spine 官方 badge、左下角标注版本号;资源暂时缺失时先给回退图,补齐后自动重渲。',
},
],
versions: [
{ ver: '3.4 / 3.5', desc: '使用官方 3.4.02、3.5.51 运行时与匹配的二进制分支,已验证多组官方示例的姿势对比。' },
{ ver: '3.6 / 3.7', desc: '额外带二进制解析兼容层(移植自官方同版本 SkeletonBinary),支持 3.7 的 IK 压缩 / 拉伸与音频事件。' },
{ ver: '3.8 – 4.3', desc: '二进制文件完整支持;4.3 等带 -beta 后缀的完整版本号也会显示在缩略图水印中。' },
],
steps: [
'导入整套文件:把 .skel / .json + .atlas + .png 放在同一个文件夹导入 Eagle',
'自动配对资源:点击任一文件,插件从同级 item 文件夹定位骨骼、atlas 与贴图',
'识别版本:读取骨骼数据里的版本号,加载匹配的本地运行时',
'预览与缩略图:实时播放画面,缩略图自动生成,资源补齐后自动重渲并刷新列表',
],
install: [
'在 Eagle 插件社区获取 SpineViewer 插件包,插件页提供下载与安装说明',
'双击 .eagleplugin 安装;或在 Eagle 插件面板(快捷键 P)右键选择「打包 / 加载插件」',
'把同一套 Spine 导出文件放进同一个文件夹导入 Eagle,点击任意文件即可预览',
],
faqs: [
{ q: '插件会接管普通图片吗?', a: '不会。只接管 skel、skel.bytes、json、atlas、atlas.txt,普通图片仍由 Eagle 原生预览。' },
{
q: '预乘(PMA)设置保存在哪里?',
a: '存在 Eagle 用户数据目录的 SpineViewer/preview-settings/ 下,按素材库与素材 ID 区分;不会修改 metadata.json、标签或注释。',
},
{
q: '3.6 / 3.7 的二进制解析可靠吗?',
a: '解析层移植自官方同版本,已验证多套官方示例;文件损坏、截断或版本不匹配会直接报告解析错误,不会用错误姿势渲染。',
},
{
q: '缩略图是怎么生成的?',
a: '在 Node 里用 @napi-rs/canvas 跨 item 文件夹读取资源渲染首帧,尺寸 400×400,右下角为 Spine 官方 badge,左下角是完整版本号。移除这个依赖只影响缩略图,画面预览不受影响。',
},
{
q: '试用版和插件是什么关系?',
a: '试用版只支持 Spine 4.2 导出的文件,用来快速看一眼效果;3.4–4.3 全版本识别、皮肤切换、时间轴、缩略图这些完整能力都在桌面插件里。',
},
],
},
goPreview() {
wx.switchTab({ url: '/pages/viewer/viewer' })
},
goBuy() {
wx.switchTab({ url: '/pages/buy/buy' })
},
// 个人主体小程序打不开外部网页,只能把网址给用户自己复制
copySite() {
wx.setClipboardData({
data: SITE_URL,
success: () => wx.showToast({ title: '网址已复制', icon: 'none' }),
})
},
})
+4
View File
@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "SpineViewer",
"usingComponents": {}
}
+95
View File
@@ -0,0 +1,95 @@
<view class="page">
<view class="glow"></view>
<!-- ===== 顶部 ===== -->
<view class="hero">
<view class="hero-title">美术师的省心小工具</view>
<view class="hero-title-sub">你的 <text class="hero-accent">Spine 数据资产</text> 可以进 Eagle 啦</view>
<view class="hero-sub">
SpineViewer 接管 skel / skel.bytes / json / atlas / atlas.txt,自动在素材库中配对骨骼、图集与贴图,识别版本并加载本地运行时。点开任意一个文件,就能实时播放、切换皮肤、导出缩略图。
</view>
<view class="hero-cta">
<view class="btn primary" bindtap="goBuy">查看套餐</view>
<view class="btn ghost" bindtap="goPreview">试用版体验</view>
</view>
<view class="stats">
<view class="stat" wx:for="{{stats}}" wx:key="label">
<view class="stat-value">{{item.value}}</view>
<view class="stat-label">{{item.label}}</view>
</view>
</view>
<view class="chips">
<text class="chip on" wx:for="{{fileChips}}" wx:key="*this">{{item}}</text>
</view>
<view class="note">png / jpg / webp 仍由 Eagle 原生预览</view>
</view>
<!-- ===== 小程序定位 ===== -->
<view class="notice">
<view class="notice-title">这里是试用版</view>
<view class="notice-desc">试用版只支持 Spine 4.2 导出的文件;桌面插件的完整能力包括 3.4–4.3 全版本识别、皮肤切换、时间轴、缩略图生成。</view>
<view class="notice-link" bindtap="goPreview">去试用版看看 →</view>
</view>
<!-- ===== 功能特性 ===== -->
<view class="section">
<view class="kicker">FEATURES</view>
<view class="h2">功能特性</view>
<view class="lead">下面每一项都对应插件的真实行为:跨 item 文件夹配对、旧版二进制解析、WebGL 渲染、缩略图补刷……不只是「能打开文件」。</view>
<view class="card" wx:for="{{features}}" wx:key="title">
<view class="card-title">{{item.title}}</view>
<view class="card-desc">{{item.desc}}</view>
</view>
</view>
<!-- ===== 支持版本 ===== -->
<view class="section alt">
<view class="kicker">VERSIONS</view>
<view class="h2">支持版本</view>
<view class="lead">覆盖 Spine 3.4 – 4.3:新版二进制直接支持,旧版二进制由同版本运行时与解析层处理。</view>
<view class="rows">
<view class="row" wx:for="{{versions}}" wx:key="ver">
<view class="row-ver">{{item.ver}}</view>
<view class="row-desc">{{item.desc}}</view>
</view>
</view>
</view>
<!-- ===== 使用流程 ===== -->
<view class="section">
<view class="kicker">WORKFLOW</view>
<view class="h2">从导入到播放</view>
<view class="step" wx:for="{{steps}}" wx:key="*this">
<view class="step-index">{{index + 1}}</view>
<view class="step-text">{{item}}</view>
</view>
</view>
<!-- ===== 安装 ===== -->
<view class="section alt">
<view class="kicker">INSTALL</view>
<view class="h2">安装使用</view>
<view class="lead">在 Eagle 插件社区获取插件包,然后在 Eagle 插件面板(快捷键 P)安装即可。</view>
<view class="step" wx:for="{{install}}" wx:key="*this">
<view class="step-index">{{index + 1}}</view>
<view class="step-text">{{item}}</view>
</view>
<view class="btn ghost wide" bindtap="copySite">复制插件页网址</view>
<view class="note">这里打不开外部网页,复制后在浏览器里打开就行。</view>
</view>
<!-- ===== 常见问题 ===== -->
<view class="section">
<view class="kicker">FAQ</view>
<view class="h2">常见问题</view>
<view class="faq" wx:for="{{faqs}}" wx:key="q">
<view class="faq-q">{{item.q}}</view>
<view class="faq-a">{{item.a}}</view>
</view>
</view>
<view class="foot">小程序版仅支持 4.2 版本</view>
</view>
+313
View File
@@ -0,0 +1,313 @@
.page {
position: relative;
min-height: 100vh;
padding: 0 28rpx 70rpx;
background: var(--bg);
overflow: hidden;
}
/* 顶部两团辉光,对应官网的红 / 青径向光 */
.glow {
position: absolute;
left: -30%;
top: -200rpx;
width: 160%;
height: 1000rpx;
pointer-events: none;
background: radial-gradient(560rpx 340rpx at 30% 38%, rgba(242, 53, 59, 0.22), transparent 66%),
radial-gradient(520rpx 320rpx at 72% 26%, rgba(79, 193, 255, 0.16), transparent 68%);
}
/* ===== 顶部 ===== */
.hero {
position: relative;
padding: 56rpx 4rpx 0;
}
.hero-title {
margin-top: 0;
font-size: 54rpx;
line-height: 1.24;
font-weight: 800;
color: var(--text);
}
.hero-title-sub {
margin-top: 16rpx;
font-size: 38rpx;
line-height: 1.4;
font-weight: 600;
color: var(--text);
}
.hero-accent {
color: var(--accent-2);
}
.hero-sub {
margin-top: 22rpx;
font-size: 25rpx;
line-height: 1.8;
color: var(--text-dim);
}
.hero-cta {
display: flex;
margin-top: 40rpx;
}
.btn {
flex: 1;
height: 92rpx;
line-height: 92rpx;
text-align: center;
border-radius: var(--r-lg);
font-size: 29rpx;
font-weight: 600;
}
.btn.primary {
background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
color: #ffffff;
box-shadow: 0 12rpx 26rpx rgba(242, 53, 59, 0.26);
}
.btn.ghost {
margin-left: 20rpx;
border: 2rpx solid var(--border);
background: var(--panel);
color: var(--text);
}
/* 单独一行的宽按钮 */
.btn.ghost.wide {
display: block;
flex: none;
width: 100%;
margin: 30rpx 0 0;
}
.stats {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-top: 36rpx;
}
.stat {
width: 48%;
margin-bottom: 16rpx;
padding: 22rpx 24rpx;
border: 2rpx solid var(--border);
border-radius: var(--r-lg);
background: rgba(28, 28, 34, 0.74);
}
.stat-value {
font-size: 40rpx;
font-weight: 700;
color: var(--text);
}
.stat-label {
margin-top: 6rpx;
font-size: 21rpx;
line-height: 1.5;
color: var(--text-dim);
}
.chips {
display: flex;
flex-wrap: wrap;
margin-top: 30rpx;
}
.chip {
margin: 0 14rpx 14rpx 0;
padding: 10rpx 22rpx;
border-radius: var(--r-pill);
border: 2rpx solid var(--border);
background: var(--panel);
color: var(--text-dim);
font-size: 21rpx;
}
.chip.on {
color: var(--cyan);
border-color: rgba(79, 193, 255, 0.4);
background: rgba(79, 193, 255, 0.08);
}
.note {
margin-top: 4rpx;
font-size: 22rpx;
line-height: 1.7;
color: var(--text-dim);
}
/* ===== 小程序定位 ===== */
.notice {
margin-top: 46rpx;
padding: 30rpx 32rpx;
border: 2rpx solid var(--border);
border-radius: var(--r-lg);
background: var(--panel);
}
.notice-title {
font-size: 28rpx;
font-weight: 600;
color: var(--accent-2);
}
.notice-desc {
margin-top: 12rpx;
font-size: 24rpx;
line-height: 1.75;
color: var(--text-dim);
}
.notice-link {
margin-top: 18rpx;
font-size: 24rpx;
color: var(--cyan);
}
/* ===== 通用分节 ===== */
.section {
position: relative;
margin-top: 76rpx;
}
.section.alt {
margin: 76rpx -28rpx 0;
padding: 56rpx 28rpx;
background: var(--bg-2);
border-top: 2rpx solid var(--border);
border-bottom: 2rpx solid var(--border);
}
.kicker {
font-size: 20rpx;
font-weight: 700;
letter-spacing: 4rpx;
color: var(--accent);
}
.h2 {
margin-top: 14rpx;
font-size: 40rpx;
font-weight: 700;
color: var(--text);
}
.lead {
margin: 16rpx 0 30rpx;
font-size: 24rpx;
line-height: 1.75;
color: var(--text-dim);
}
.card {
padding: 26rpx 30rpx;
margin-bottom: 18rpx;
border: 2rpx solid var(--border);
border-radius: var(--r-lg);
background: var(--panel);
}
.card-title {
font-size: 28rpx;
font-weight: 600;
color: var(--text);
}
.card-desc {
margin-top: 12rpx;
font-size: 24rpx;
line-height: 1.7;
color: var(--text-dim);
}
/* ===== 版本表 ===== */
.rows {
border: 2rpx solid var(--border);
border-radius: var(--r-lg);
background: var(--panel);
overflow: hidden;
}
.row {
padding: 26rpx 30rpx;
border-bottom: 2rpx solid var(--border);
}
.row:last-child {
border-bottom: none;
}
.row-ver {
font-size: 26rpx;
font-weight: 600;
color: var(--cyan);
}
.row-desc {
margin-top: 10rpx;
font-size: 23rpx;
line-height: 1.7;
color: var(--text-dim);
}
/* ===== 步骤 ===== */
.step {
display: flex;
align-items: flex-start;
margin-bottom: 24rpx;
}
.step-index {
flex-shrink: 0;
width: 48rpx;
height: 48rpx;
line-height: 48rpx;
text-align: center;
border-radius: var(--r-pill);
border: 2rpx solid rgba(242, 53, 59, 0.35);
background: rgba(242, 53, 59, 0.12);
color: var(--accent-2);
font-size: 23rpx;
}
.step-text {
flex: 1;
margin-left: 20rpx;
padding-top: 6rpx;
font-size: 25rpx;
line-height: 1.7;
color: var(--text);
}
/* ===== 常见问题 ===== */
.faq {
margin-bottom: 26rpx;
}
.faq-q {
font-size: 27rpx;
color: var(--text);
}
.faq-a {
margin-top: 10rpx;
font-size: 24rpx;
line-height: 1.75;
color: var(--text-dim);
}
.foot {
margin-top: 60rpx;
font-size: 22rpx;
line-height: 1.7;
color: rgba(157, 157, 168, 0.6);
}