统一排行榜对齐星雀UI,页面资源后台配置实时刷新
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
281
miniprogram/pages/haibao/haibao.js
Normal file
281
miniprogram/pages/haibao/haibao.js
Normal file
@@ -0,0 +1,281 @@
|
||||
// pages/haibao/haibao.js
|
||||
import request from '../../utils/request.js';
|
||||
|
||||
const app = getApp();
|
||||
|
||||
Page({
|
||||
data: {
|
||||
qrcodeUrl: '',
|
||||
isLoading: false,
|
||||
showPosterCanvas: false,
|
||||
posterImageTemp: '',
|
||||
avatarUrl: '',
|
||||
uid: '',
|
||||
nickName: '',
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadQRCodeFromCache();
|
||||
this.loadUserInfo();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.registerNotificationComponent();
|
||||
},
|
||||
|
||||
registerNotificationComponent() {
|
||||
const notificationComp = this.selectComponent('#global-notification');
|
||||
if (notificationComp && notificationComp.showNotification) {
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => notificationComp.showNotification(data),
|
||||
hide: () => notificationComp.hideNotification()
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
loadQRCodeFromCache() {
|
||||
try {
|
||||
const relativeUrl = wx.getStorageSync('haibao_url');
|
||||
if (relativeUrl) {
|
||||
const fullUrl = this.getFullImageUrl(relativeUrl);
|
||||
this.setData({ qrcodeUrl: fullUrl });
|
||||
} else {
|
||||
this.setData({ qrcodeUrl: '' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('读取缓存失败', error);
|
||||
}
|
||||
},
|
||||
|
||||
loadUserInfo() {
|
||||
const touxiang = wx.getStorageSync('touxiang');
|
||||
const ossUrl = app.globalData.ossImageUrl || '';
|
||||
const defaultAvatar = ossUrl + (app.globalData.morentouxiang || 'avatar/default.jpg');
|
||||
let avatarUrl = defaultAvatar;
|
||||
if (touxiang && typeof touxiang === 'string' && touxiang.trim() !== '') {
|
||||
avatarUrl = this.getFullImageUrl(touxiang);
|
||||
}
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
let nickName = app.globalData.nicheng || wx.getStorageSync('nicheng') || '管事';
|
||||
this.setData({ avatarUrl, uid, nickName });
|
||||
},
|
||||
|
||||
getFullImageUrl(url) {
|
||||
if (!url) return '';
|
||||
const ossUrl = app.globalData.ossImageUrl || '';
|
||||
return url.startsWith('http') ? url : ossUrl + url;
|
||||
},
|
||||
|
||||
refreshQRCode() {
|
||||
if (this.data.isLoading) return;
|
||||
this.setData({ isLoading: true });
|
||||
request({
|
||||
url: '/peizhi/guanshiewm',
|
||||
method: 'POST',
|
||||
}).then(res => {
|
||||
if (res.data && res.data.code === 0) {
|
||||
const relativeUrl = res.data.data.url;
|
||||
if (relativeUrl) {
|
||||
wx.setStorageSync('haibao_url', relativeUrl);
|
||||
const fullUrl = this.getFullImageUrl(relativeUrl);
|
||||
this.setData({ qrcodeUrl: fullUrl });
|
||||
wx.showToast({ title: '获取成功', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: '返回数据异常', icon: 'none' });
|
||||
}
|
||||
} else {
|
||||
wx.showToast({ title: res.data.msg || '获取失败', icon: 'none' });
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('获取海报失败', err);
|
||||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||||
}).finally(() => {
|
||||
this.setData({ isLoading: false });
|
||||
});
|
||||
},
|
||||
|
||||
// 🔥【修改】保存二维码到相册(先下载网络图片)
|
||||
saveToAlbum() {
|
||||
if (!this.data.qrcodeUrl) {
|
||||
wx.showToast({ title: '暂无二维码', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showLoading({ title: '保存中...', mask: true });
|
||||
wx.downloadFile({
|
||||
url: this.data.qrcodeUrl,
|
||||
success: (res) => {
|
||||
wx.hideLoading();
|
||||
if (res.statusCode === 200) {
|
||||
// 调用已有的保存函数(传入临时路径)
|
||||
this.downloadAndSave(res.tempFilePath);
|
||||
} else {
|
||||
wx.showToast({ title: '下载失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
wx.hideLoading();
|
||||
console.error('下载二维码失败', err);
|
||||
wx.showToast({ title: '下载失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
generateMyPoster() {
|
||||
if (!this.data.qrcodeUrl) {
|
||||
wx.showToast({ title: '请先生成二维码', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showLoading({ title: '生成海报中...', mask: true });
|
||||
|
||||
const ossUrl = app.globalData.ossImageUrl || '';
|
||||
const bgUrl = ossUrl + 'beijing/haibaobeijing.jpg';
|
||||
const urls = [bgUrl, this.data.qrcodeUrl, this.data.avatarUrl];
|
||||
|
||||
const promises = urls.map(url => this.loadImage(url));
|
||||
Promise.all(promises)
|
||||
.then((images) => {
|
||||
wx.hideLoading();
|
||||
this.setData({ showPosterCanvas: true }, () => {
|
||||
setTimeout(() => {
|
||||
this.drawPoster(images[0], images[1], images[2]);
|
||||
}, 200);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
wx.hideLoading();
|
||||
wx.showToast({ title: '图片加载失败', icon: 'none' });
|
||||
console.error('图片加载失败', err);
|
||||
});
|
||||
},
|
||||
|
||||
loadImage(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.getImageInfo({
|
||||
src: url,
|
||||
success: (res) => resolve(res.path),
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
drawPoster(bgPath, qrPath, avatarPath) {
|
||||
const ctx = wx.createCanvasContext('posterCanvas', this);
|
||||
const query = wx.createSelectorQuery().in(this);
|
||||
query.select('.poster-canvas').boundingClientRect(rect => {
|
||||
if (!rect) {
|
||||
wx.showToast({ title: '画布获取失败', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const canvasWidth = rect.width;
|
||||
const canvasHeight = rect.height;
|
||||
|
||||
// 1. 绘制背景
|
||||
ctx.drawImage(bgPath, 0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
const qrSize = 100;
|
||||
const margin = 5;
|
||||
const qrX = canvasWidth - qrSize - margin;
|
||||
const qrY = canvasHeight - qrSize - margin;
|
||||
ctx.drawImage(qrPath, qrX, qrY, qrSize, qrSize);
|
||||
|
||||
const avatarSize = 60;
|
||||
const avatarX = margin + 20;
|
||||
const avatarY = canvasHeight - avatarSize - margin;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.arc(avatarX + avatarSize/2, avatarY + avatarSize/2, avatarSize/2, 0, 2 * Math.PI);
|
||||
ctx.clip();
|
||||
ctx.drawImage(avatarPath, avatarX, avatarY, avatarSize, avatarSize);
|
||||
ctx.restore();
|
||||
|
||||
ctx.setFontSize(16);
|
||||
ctx.setFillStyle('#333333');
|
||||
ctx.setTextAlign('left');
|
||||
|
||||
let nick = this.data.nickName || '管事';
|
||||
if (nick.length > 3) {
|
||||
nick = nick.substring(0, 3) + '...';
|
||||
}
|
||||
const nameText = nick;
|
||||
|
||||
const textX = avatarX + avatarSize + 8;
|
||||
const textY = avatarY + avatarSize/2 + 6;
|
||||
ctx.fillText(nameText, textX, textY);
|
||||
|
||||
ctx.setFontSize(18);
|
||||
ctx.setFillStyle('#ffaa00');
|
||||
ctx.setTextAlign('left');
|
||||
const slogan = '快来加入我们 ✦';
|
||||
const sloganX = avatarX;
|
||||
const sloganY = avatarY - 12;
|
||||
ctx.fillText(slogan, sloganX, sloganY);
|
||||
|
||||
ctx.draw(false, () => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId: 'posterCanvas',
|
||||
success: (res) => {
|
||||
this.setData({ posterImageTemp: res.tempFilePath });
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('生成海报临时文件失败', err);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}).exec();
|
||||
},
|
||||
|
||||
savePoster() {
|
||||
if (!this.data.posterImageTemp) {
|
||||
wx.showToast({ title: '海报尚未生成', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.downloadAndSave(this.data.posterImageTemp);
|
||||
},
|
||||
|
||||
hidePoster() {
|
||||
this.setData({ showPosterCanvas: false, posterImageTemp: '' });
|
||||
},
|
||||
|
||||
downloadAndSave(filePath) {
|
||||
wx.getSetting({
|
||||
success: (res) => {
|
||||
if (!res.authSetting['scope.writePhotosAlbum']) {
|
||||
wx.authorize({
|
||||
scope: 'scope.writePhotosAlbum',
|
||||
success: () => {
|
||||
this._saveImage(filePath);
|
||||
},
|
||||
fail: () => {
|
||||
wx.showModal({
|
||||
title: '提示',
|
||||
content: '需要您授权保存到相册',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.openSetting();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._saveImage(filePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_saveImage(filePath) {
|
||||
wx.saveImageToPhotosAlbum({
|
||||
filePath: filePath,
|
||||
success: () => {
|
||||
wx.showToast({ title: '保存成功', icon: 'success' });
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('保存失败', err);
|
||||
wx.showToast({ title: '保存失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
8
miniprogram/pages/haibao/haibao.json
Normal file
8
miniprogram/pages/haibao/haibao.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"global-notification": "/components/global-notification/global-notification"
|
||||
},
|
||||
"navigationBarTitleText": "推广海报",
|
||||
"navigationBarBackgroundColor": "#0a0e17",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
71
miniprogram/pages/haibao/haibao.wxml
Normal file
71
miniprogram/pages/haibao/haibao.wxml
Normal file
@@ -0,0 +1,71 @@
|
||||
<view class="page-container">
|
||||
<!-- 背景网格(保留机甲风格) -->
|
||||
<view class="grid-bg"></view>
|
||||
<view class="mech-line line-h"></view>
|
||||
<view class="mech-line line-v"></view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 标题区域 -->
|
||||
<view class="title-section">
|
||||
<text class="title">⚡ 推广海报 ⚡</text>
|
||||
<text class="subtitle">邀请打手扫码注册,自动填充邀请码</text>
|
||||
</view>
|
||||
|
||||
<!-- 二维码展示区域(原有) -->
|
||||
<view class="qrcode-section">
|
||||
<view class="qrcode-wrapper" wx:if="{{qrcodeUrl}}">
|
||||
<image class="qrcode-img" src="{{qrcodeUrl}}" mode="widthFix" />
|
||||
<view class="qrcode-glow"></view>
|
||||
</view>
|
||||
<view class="empty-qrcode" wx:else>
|
||||
<text class="empty-icon">⚡</text>
|
||||
<text class="empty-text">点击下方按钮生成您的专属二维码</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 按钮区域(第一行:保存/刷新/生成海报) -->
|
||||
<view class="button-section">
|
||||
<view class="btn-group">
|
||||
<view class="btn save-btn" bindtap="saveToAlbum" wx:if="{{qrcodeUrl}}">
|
||||
<text class="btn-icon">📥</text>
|
||||
<text class="btn-text">保存二维码</text>
|
||||
</view>
|
||||
<view class="btn refresh-btn" bindtap="refreshQRCode" wx:if="{{!isLoading}}">
|
||||
<text class="btn-icon">⟳</text>
|
||||
<text class="btn-text">{{qrcodeUrl ? '重新获取' : '获取二维码'}}</text>
|
||||
</view>
|
||||
<view class="btn loading-btn" wx:else>
|
||||
<view class="loading-spinner-small"></view>
|
||||
<text class="btn-text">生成中...</text>
|
||||
</view>
|
||||
<!-- 🔥【新增】生成我的专属海报按钮 -->
|
||||
<view class="btn poster-btn" bindtap="generateMyPoster" wx:if="{{qrcodeUrl && !showPosterCanvas}}">
|
||||
<text class="btn-icon">🎨</text>
|
||||
<text class="btn-text">生成我的专属海报</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 🔥【新增】专属海报展示区(当 showPosterCanvas 为 true 时显示) -->
|
||||
<view class="poster-section" wx:if="{{showPosterCanvas}}">
|
||||
<canvas canvas-id="posterCanvas" class="poster-canvas"></canvas>
|
||||
<view class="poster-actions">
|
||||
<view class="btn save-poster-btn" bindtap="savePoster">
|
||||
<text class="btn-icon">📥</text>
|
||||
<text class="btn-text">保存海报</text>
|
||||
</view>
|
||||
<view class="btn back-btn" bindtap="hidePoster">
|
||||
<text class="btn-icon">↩️</text>
|
||||
<text class="btn-text">返回</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用说明(保留) -->
|
||||
<view class="instruction">
|
||||
<text class="instruction-text">* 打手扫码后自动进入注册页面,邀请码将自动填充</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
</view>
|
||||
269
miniprogram/pages/haibao/haibao.wxss
Normal file
269
miniprogram/pages/haibao/haibao.wxss
Normal file
@@ -0,0 +1,269 @@
|
||||
/* 机甲风格推广海报页面(含新增专属海报样式) */
|
||||
|
||||
page {
|
||||
background: #0a0e17;
|
||||
min-height: 100vh;
|
||||
font-family: 'Avenir', 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 背景网格 */
|
||||
.grid-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
linear-gradient(rgba(0, 160, 255, 0.05) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(0, 160, 255, 0.05) 1px, transparent 1px);
|
||||
background-size: 50rpx 50rpx;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
min-height: 100vh;
|
||||
padding: 30rpx 25rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 机械装饰线条 */
|
||||
.mech-line {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.line-h {
|
||||
top: 200rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #00a6ff, transparent);
|
||||
}
|
||||
.line-v {
|
||||
right: 50rpx;
|
||||
top: 100rpx;
|
||||
width: 2rpx;
|
||||
height: 300rpx;
|
||||
background: linear-gradient(180deg, transparent, #00a6ff, transparent);
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
/* 标题区域 */
|
||||
.title-section {
|
||||
text-align: center;
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 30rpx #00a6ff;
|
||||
letter-spacing: 2rpx;
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 28rpx;
|
||||
color: #9cf;
|
||||
opacity: 0.9;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
/* 二维码区域(方形,无斜切) */
|
||||
.qrcode-section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
.qrcode-wrapper {
|
||||
position: relative;
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
background: rgba(0, 20, 40, 0.8);
|
||||
border: 4rpx solid #00a6ff;
|
||||
/* 移除 clip-path,保持方形 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 0 80rpx rgba(0, 166, 255, 0.4);
|
||||
animation: qrcodePulse 2s infinite alternate;
|
||||
}
|
||||
.qrcode-img {
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.qrcode-glow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: radial-gradient(circle at 30% 30%, rgba(0, 166, 255, 0.2), transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.empty-qrcode {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
background: rgba(0, 20, 40, 0.8);
|
||||
border: 4rpx dashed #00a6ff;
|
||||
/* 方形 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.empty-icon {
|
||||
font-size: 80rpx;
|
||||
color: #00a6ff;
|
||||
margin-bottom: 20rpx;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.empty-text {
|
||||
font-size: 26rpx;
|
||||
color: #9cf;
|
||||
text-align: center;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
|
||||
/* 按钮区域(机甲斜切风格) */
|
||||
.button-section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.btn-group {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
.btn {
|
||||
width: 220rpx;
|
||||
height: 80rpx;
|
||||
background: rgba(0, 30, 60, 0.8);
|
||||
border: 2rpx solid #00a6ff;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
transition: 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn:active {
|
||||
transform: scale(0.96);
|
||||
box-shadow: 0 0 40rpx #00a6ff;
|
||||
}
|
||||
.save-btn {
|
||||
border-color: #00a6ff;
|
||||
}
|
||||
.refresh-btn {
|
||||
border-color: #ffaa00;
|
||||
}
|
||||
.refresh-btn .btn-icon {
|
||||
color: #ffaa00;
|
||||
}
|
||||
/* 🔥【新增】生成海报按钮样式 */
|
||||
.poster-btn {
|
||||
border-color: #ffaa00;
|
||||
}
|
||||
.poster-btn .btn-icon {
|
||||
color: #ffaa00;
|
||||
}
|
||||
.loading-btn {
|
||||
opacity: 0.7;
|
||||
pointer-events: none;
|
||||
}
|
||||
.btn-icon {
|
||||
font-size: 36rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
.btn-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
.loading-spinner-small {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border: 4rpx solid rgba(255,255,255,0.2);
|
||||
border-top: 4rpx solid #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
/* 🔥【新增】专属海报展示区 */
|
||||
.poster-section {
|
||||
margin-top: 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.poster-canvas {
|
||||
width: 600rpx;
|
||||
height: 900rpx;
|
||||
background: #1a1f2e; /* 占位色 */
|
||||
border: 4rpx solid #00a6ff;
|
||||
box-shadow: 0 0 60rpx #00a6ff;
|
||||
/* 保持方形,无斜切 */
|
||||
}
|
||||
.poster-actions {
|
||||
display: flex;
|
||||
gap: 30rpx;
|
||||
margin-top: 30rpx;
|
||||
justify-content: center;
|
||||
}
|
||||
.save-poster-btn {
|
||||
background: linear-gradient(45deg, #0066cc, #00a6ff);
|
||||
border-color: #00a6ff;
|
||||
}
|
||||
.back-btn {
|
||||
background: rgba(0, 30, 60, 0.8);
|
||||
border-color: #00a6ff;
|
||||
}
|
||||
|
||||
/* 使用说明(保留) */
|
||||
.instruction {
|
||||
margin-top: 30rpx;
|
||||
padding: 20rpx 40rpx;
|
||||
background: rgba(0, 30, 50, 0.5);
|
||||
border-left: 4rpx solid #00a6ff;
|
||||
clip-path: polygon(0 0, 100% 0, 98% 100%, 0 100%);
|
||||
}
|
||||
.instruction-text {
|
||||
font-size: 24rpx;
|
||||
color: #9cf;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 动画 */
|
||||
@keyframes qrcodePulse {
|
||||
0% { box-shadow: 0 0 40rpx rgba(0, 166, 255, 0.3); }
|
||||
100% { box-shadow: 0 0 100rpx rgba(0, 166, 255, 0.6); }
|
||||
}
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
Reference in New Issue
Block a user