feat: add app sharing and enhance UI with animations and revamped coupon display.

This commit is contained in:
邹方成 2025-12-17 01:55:23 +08:00
parent f8b1f57cd7
commit dd12d8e500
6 changed files with 1856 additions and 188 deletions

View File

@ -5,8 +5,8 @@ export function wechatLogin(code, invite_code) {
return request({ url: '/api/app/users/weixin/login', method: 'POST', data })
}
export function getInventory(user_id, page = 1, page_size = 20){
return authRequest({ url: `/api/app/users/${user_id}/inventory`, method: 'GET', data: { page, page_size } })
export function getInventory(user_id, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/inventory`, method: 'GET', data: { page, page_size } })
}
export function bindPhone(user_id, code, extraHeader = {}) {
@ -99,6 +99,18 @@ export function getUserCoupons(user_id, status, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/coupons`, method: 'GET', data })
}
export function getCouponStats(user_id) {
return authRequest({ url: `/api/app/users/${user_id}/coupons/stats`, method: 'GET' })
}
export function getCouponUsage(user_id, user_coupon_id, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/coupons/${user_coupon_id}/usage`, method: 'GET', data: { page, page_size } })
}
export function redeemCouponByPoints(user_id, coupon_id) {
return authRequest({ url: `/api/app/users/${user_id}/points/redeem-coupon`, method: 'POST', data: { coupon_id } })
}
export function redeemCoupon(user_id, code) {
return authRequest({ url: `/api/app/users/${user_id}/coupons/redeem`, method: 'POST', data: { code } })
}
@ -130,3 +142,8 @@ export function getTasks(page = 1, page_size = 20) {
export function getShipments(user_id, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/shipments`, method: 'GET', data: { page, page_size } })
}
// 获取用户邀请记录
export function getUserInvites(user_id, page = 1, page_size = 20) {
return authRequest({ url: `/api/app/users/${user_id}/invites`, method: 'GET', data: { page, page_size } })
}

View File

@ -116,6 +116,27 @@ onLoad((opts) => {
}
loadData()
})
//
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
onShareAppMessage(() => {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: `${title.value || '精彩活动'} - 奇盒潮玩`,
path: `/pages/index/index?invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
})
onShareTimeline(() => {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: `${title.value || '精彩活动'} - 奇盒潮玩`,
query: `invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
})
</script>
<style scoped>
@ -230,4 +251,80 @@ onLoad((opts) => {
color: #999;
font-size: 28rpx;
}
/* ============================================
活动列表 UX/UI 增强
============================================ */
/* 入场动画 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6rpx); }
}
/* 卡片交错入场 */
.activity-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.activity-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.activity-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.activity-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.activity-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.3s both; }
/* 图片加载动画 */
.thumb {
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* 热门标签浮动 */
.tag-hot {
animation: float 3s ease-in-out infinite;
background: linear-gradient(135deg, rgba(255,77,79,0.9), rgba(255,107,53,0.9));
color: #fff;
}
/* 卡片点击效果 */
.activity-item {
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.activity-item:active {
transform: scale(0.96) translateY(4rpx);
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
}
/* GO 按钮脉冲 */
.btn-go {
animation: pulse 2s infinite;
transition: all 0.2s ease;
}
.btn-go:active {
animation: none;
transform: scale(0.9);
}
/* 增强加载器 */
.spinner {
border-width: 6rpx;
border-top-color: #FF6B35;
}
/* 空状态入场 */
.empty {
animation: fadeInUp 0.5s ease-out;
}
</style>

View File

@ -1189,4 +1189,146 @@ async function onShip() {
font-size: 22rpx;
color: #9CA3AF;
}
/* ============================================
盒柜 UX/UI 增强
============================================ */
/* 入场动画 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30rpx); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(100%); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes bounceIn {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
/* Tab 切换动画 */
.tabs {
animation: fadeInUp 0.3s ease-out;
}
.tab-item {
transition: all 0.25s ease;
}
.tab-item:active {
transform: scale(0.96);
}
/* 库存卡片交错入场 */
.inventory-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.inventory-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.inventory-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.inventory-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.inventory-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.3s both; }
/* 发货单卡片交错入场 */
.shipment-card:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.1s both; }
.shipment-card:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.15s both; }
.shipment-card:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.shipment-card:nth-child(n+4) { animation: fadeInUp 0.4s ease-out 0.25s both; }
/* 卡片点击效果 */
.inventory-item {
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.inventory-item:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
}
/* 选中时的高亮效果 */
.inventory-item:has(.checkbox.checked) {
box-shadow: 0 8rpx 32rpx rgba(255, 107, 53, 0.15);
border: 2rpx solid rgba(255, 159, 67, 0.3);
}
/* 复选框动画 */
.checkbox {
transition: all 0.2s ease;
}
.checkbox.checked {
animation: bounceIn 0.3s ease-out;
}
/* 底部操作栏增强 */
.bottom-bar {
animation: slideUp 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
backdrop-filter: blur(20rpx);
-webkit-backdrop-filter: blur(20rpx);
background: rgba(255, 255, 255, 0.95);
}
/* 操作按钮动画 */
.action-btn {
transition: all 0.2s ease;
}
.action-btn:active {
transform: scale(0.95);
}
.btn-redeem {
animation: pulse 2s infinite;
}
.btn-redeem:active {
animation: none;
}
/* 步进器按钮效果 */
.step-btn {
transition: all 0.15s ease;
}
.step-btn:active {
background: #FF9F43 !important;
color: #fff !important;
transform: scale(0.9);
}
/* 全选栏入场 */
.action-bar {
animation: fadeInUp 0.3s ease-out;
}
/* 发货单卡片点击效果 */
.shipment-card {
transition: all 0.25s ease;
}
.shipment-card:active {
transform: scale(0.98);
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
}
/* 复制按钮效果 */
.express-copy {
transition: all 0.2s ease;
}
.express-copy:active {
background: #2563EB;
color: #fff;
transform: scale(0.95);
}
/* 缩略图图片悬浮效果 */
.thumb-img {
transition: all 0.2s ease;
}
.thumb-img:active {
transform: scale(1.05);
}
</style>

View File

@ -314,6 +314,24 @@ export default {
confirmText: '知道了'
})
}
},
//
onShareAppMessage() {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '奇盒潮玩 - 开箱惊喜等你来',
path: `/pages/index/index?invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
},
//
onShareTimeline() {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '奇盒潮玩 - 开箱惊喜等你来',
query: `invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
}
}
</script>
@ -682,4 +700,182 @@ export default {
color: #9CA3AF;
font-size: 28rpx;
}
/* ============================================
UX/UI 增强 - 动画与交互
============================================ */
/* 入场动画 */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8rpx); }
}
/* Banner 入场动画 */
.banner-box {
animation: scaleIn 0.5s ease-out;
}
/* 通知栏滑入 */
.notice-bar {
animation: fadeInUp 0.4s ease-out 0.1s both;
}
/* 玩法卡片交错入场 */
.game-card-large:first-child {
animation: fadeInUp 0.4s ease-out 0.2s both;
}
.game-card-large:last-child {
animation: fadeInUp 0.4s ease-out 0.3s both;
}
.game-card-small:nth-child(1) {
animation: fadeInUp 0.4s ease-out 0.35s both;
}
.game-card-small:nth-child(2) {
animation: fadeInUp 0.4s ease-out 0.4s both;
}
.game-card-small:nth-child(3) {
animation: fadeInUp 0.4s ease-out 0.45s both;
}
/* 活动卡片交错入场 */
.activity-item:nth-child(1) { animation: fadeInUp 0.4s ease-out 0.2s both; }
.activity-item:nth-child(2) { animation: fadeInUp 0.4s ease-out 0.25s both; }
.activity-item:nth-child(3) { animation: fadeInUp 0.4s ease-out 0.3s both; }
.activity-item:nth-child(4) { animation: fadeInUp 0.4s ease-out 0.35s both; }
.activity-item:nth-child(n+5) { animation: fadeInUp 0.4s ease-out 0.4s both; }
/* 玻璃态搜索栏 */
.search-bar {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20rpx);
-webkit-backdrop-filter: blur(20rpx);
border: 1rpx solid rgba(255, 255, 255, 0.6);
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
}
.search-bar:active {
transform: scale(0.98);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
}
/* 卡片点击效果 */
.game-card-large,
.game-card-small {
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
cursor: pointer;
}
.game-card-large:active {
transform: scale(0.97);
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
}
.game-card-small:active {
transform: scale(0.95);
box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.08);
}
/* 活动卡片悬浮效果 */
.activity-item {
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.activity-item:active {
transform: scale(0.97) translateY(4rpx);
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
}
/* GO 按钮脉冲动画 */
.activity-btn-go {
animation: pulse 2s infinite;
transition: all 0.2s ease;
}
.activity-btn-go:active {
animation: none;
transform: scale(0.9);
}
/* 图片加载动画 */
.activity-thumb {
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* 热门标签浮动效果 */
.activity-tag-hot {
animation: float 3s ease-in-out infinite;
}
/* Banner 图片悬浮效果 */
.banner-image {
transition: transform 0.4s ease;
}
.banner-box:active .banner-image {
transform: scale(1.02);
}
/* 通知栏点击效果 */
.notice-bar {
transition: all 0.2s ease;
}
.notice-bar:active {
background: #F0F0F0;
transform: scale(0.99);
}
/* 品牌标志动画 */
.brand-star {
animation: float 2s ease-in-out infinite;
}
/* Section 标题增强 */
.section-header {
animation: fadeInUp 0.4s ease-out 0.15s both;
}
/* 增强阴影效果 */
.banner-box {
box-shadow: 0 12rpx 40rpx rgba(0,0,0,0.08);
}
.activity-item {
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.06);
}
/* 热门标签增强 */
.activity-tag-hot {
background: linear-gradient(135deg, rgba(255,77,79,0.9), rgba(255,107,53,0.9));
color: #fff;
text-shadow: 0 1rpx 2rpx rgba(0,0,0,0.2);
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,5 @@
<template>
<view class="page">
<view v-if="showNotice" class="notice-mask" @touchmove.stop.prevent @tap.stop>
<view class="notice-dialog" @tap.stop>
<view class="notice-title">温馨提示</view>
<view class="notice-content">由于商品价格实时浮动当前暂不支持自助兑换如需兑换商品请联系客服核对最新价格</view>
<view class="notice-actions">
<view class="notice-check" @tap.stop="toggleHideForever">
<view class="check-box" :class="{ on: hideForever }">
<text v-if="hideForever" class="iconfont icon-check"></text>
</view>
<text class="check-text">不再提示</text>
</view>
<button class="notice-btn" hover-class="btn-hover" @tap.stop="onDismissNotice">我知道了</button>
</view>
</view>
</view>
<!-- 顶部固定区域 -->
<view class="header-section">
<view class="search-box" style="margin-top: 20rpx;">
@ -85,9 +69,6 @@ const loading = ref(false)
const keyword = ref('')
const minPrice = ref('')
const maxPrice = ref('')
const showNotice = ref(false)
const hideForever = ref(false)
const skipReloadOnce = ref(false)
function apiGet(url, data = {}) {
const token = uni.getStorageSync('token')
@ -219,30 +200,32 @@ onShow(async () => {
return
}
// Notice logic
try {
const sess = String(uni.getStorageSync('app_session_id') || '')
const hiddenSess = String(uni.getStorageSync('shop_notice_hidden_session_id') || '')
const hiddenThisSession = !!(sess && hiddenSess && hiddenSess === sess)
showNotice.value = !hiddenThisSession
hideForever.value = hiddenThisSession
} catch (_) { showNotice.value = true }
loading.value = true
await loadProducts()
loading.value = false
})
function toggleHideForever() { hideForever.value = !hideForever.value }
function onDismissNotice() {
if (hideForever.value) {
try {
const sess = String(uni.getStorageSync('app_session_id') || '')
if (sess) uni.setStorageSync('shop_notice_hidden_session_id', sess)
} catch (_) {}
//
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
onShareAppMessage(() => {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '奇盒潮玩商城 - 好物等你来兑',
path: `/pages/index/index?invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
showNotice.value = false
}
})
onShareTimeline(() => {
const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || ''
return {
title: '奇盒潮玩商城 - 好物等你来兑',
query: `invite_code=${inviteCode}`,
imageUrl: '/static/logo.png'
}
})
</script>
<style scoped>
@ -487,75 +470,6 @@ function onDismissNotice() {
font-size: 28rpx;
}
/* 弹窗样式 */
.notice-mask {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.6);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.notice-dialog {
width: 560rpx;
background: #FFF;
border-radius: 24rpx;
padding: 40rpx 32rpx;
text-align: center;
}
.notice-title {
font-size: 34rpx;
font-weight: 700;
margin-bottom: 24rpx;
color: #333;
}
.notice-content {
font-size: 28rpx;
color: #555;
line-height: 1.6;
margin-bottom: 40rpx;
text-align: left;
}
.notice-actions {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.notice-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(90deg, #FF9F43, #FF6B35);
color: #fff;
border-radius: 40rpx;
font-size: 30rpx;
font-weight: 600;
}
.notice-check {
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
opacity: 0.8;
}
.check-box {
width: 32rpx;
height: 32rpx;
border: 2rpx solid #CCC;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.check-box.on {
background: #FF6B35;
border-color: #FF6B35;
}
.icon-check {
font-size: 20rpx;
color: #FFF;
}
.check-text {
font-size: 26rpx;
color: #888;