修改展示时长bug
This commit is contained in:
parent
94b9271184
commit
eaad2642a8
@ -591,11 +591,11 @@ func (r *socialRepositoryImpl) GetMyLikedAssets(userID, starID int64, page, page
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 计数查询(使用 DISTINCT 因为一个资产可能在多个展位展出)
|
// 计数查询(使用 DISTINCT 因为一个资产可能在多个展位展出)
|
||||||
// 显示:展品存在且未领取(is_processed=false),无论是否过期
|
// 显示:展品未下架(deleted_at IS NULL),无论是否过期
|
||||||
// 不显示:已领取的(is_processed=true)或从未展出过的
|
// 不显示:已领取下架的(deleted_at IS NOT NULL)或从未展出过的
|
||||||
countQuery := r.db.Model(&models.AssetLike{}).
|
countQuery := r.db.Model(&models.AssetLike{}).
|
||||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||||
Joins("JOIN exhibitions e ON e.asset_id = a.id AND e.deleted_at IS NULL AND e.is_processed = false").
|
Joins("JOIN exhibitions e ON e.asset_id = a.id AND e.deleted_at IS NULL").
|
||||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true)
|
Where("a.deleted_at IS NULL AND a.is_active = ?", true)
|
||||||
|
|
||||||
@ -603,14 +603,14 @@ func (r *socialRepositoryImpl) GetMyLikedAssets(userID, starID int64, page, page
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据查询:只过滤已下架的,不过滤过期(已过期但未领取的仍显示)
|
// 数据查询:只过滤已下架的,不过滤过期(用户领取收益后才下架)
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
err := r.db.Model(&models.AssetLike{}).
|
err := r.db.Model(&models.AssetLike{}).
|
||||||
Select(`asset_likes.asset_id, a.name, a.cover_url, a.like_count,
|
Select(`asset_likes.asset_id, a.name, a.cover_url, a.like_count,
|
||||||
asset_likes.created_at as liked_at,
|
asset_likes.created_at as liked_at,
|
||||||
(a.tags @> '["craft:lenticular"]') as is_lenticular`).
|
(a.tags @> '["craft:lenticular"]') as is_lenticular`).
|
||||||
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
Joins("JOIN assets a ON a.id = asset_likes.asset_id").
|
||||||
Joins("JOIN exhibitions e ON e.asset_id = a.id AND e.deleted_at IS NULL AND e.is_processed = false").
|
Joins("JOIN exhibitions e ON e.asset_id = a.id AND e.deleted_at IS NULL").
|
||||||
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
Where("asset_likes.user_id = ? AND asset_likes.star_id = ?", userID, starID).
|
||||||
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
Where("a.deleted_at IS NULL AND a.is_active = ?", true).
|
||||||
Group("asset_likes.asset_id, a.name, a.cover_url, a.like_count, asset_likes.created_at, is_lenticular").
|
Group("asset_likes.asset_id, a.name, a.cover_url, a.like_count, asset_likes.created_at, is_lenticular").
|
||||||
|
|||||||
@ -163,9 +163,6 @@ func (s *revenueService) ClaimExhibitionRevenue(ctx context.Context, userID, sta
|
|||||||
// 增加用户累计上架时长(触发升级检查)
|
// 增加用户累计上架时长(触发升级检查)
|
||||||
// 计算上架时长(毫秒转小时)
|
// 计算上架时长(毫秒转小时)
|
||||||
exhibitionHours := (record.CycleEndTime - record.CycleStartTime) / 3600000
|
exhibitionHours := (record.CycleEndTime - record.CycleStartTime) / 3600000
|
||||||
if exhibitionHours < 1 {
|
|
||||||
exhibitionHours = 1 // 最少1小时
|
|
||||||
}
|
|
||||||
if s.userRPCClient != nil {
|
if s.userRPCClient != nil {
|
||||||
newLevel, levelDelta, crystalReward, err := s.userRPCClient.AddExhibitionHours(ctx, userID, starID, exhibitionHours,
|
newLevel, levelDelta, crystalReward, err := s.userRPCClient.AddExhibitionHours(ctx, userID, starID, exhibitionHours,
|
||||||
fmt.Sprintf("%d", record.ID))
|
fmt.Sprintf("%d", record.ID))
|
||||||
@ -341,9 +338,6 @@ func (s *revenueService) OnExhibitionCompleted(ctx context.Context, req *pb.OnEx
|
|||||||
startTime := req.StartTime
|
startTime := req.StartTime
|
||||||
expireAt := req.ExpireAt
|
expireAt := req.ExpireAt
|
||||||
actualHours := (expireAt - startTime) / 3600000
|
actualHours := (expireAt - startTime) / 3600000
|
||||||
if actualHours < 1 {
|
|
||||||
actualHours = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceID 用于去重,避免重复累计
|
// sourceID 用于去重,避免重复累计
|
||||||
sourceID := fmt.Sprintf("exhibition_%d", req.ExhibitionId)
|
sourceID := fmt.Sprintf("exhibition_%d", req.ExhibitionId)
|
||||||
|
|||||||
@ -133,7 +133,17 @@
|
|||||||
<view class="liked-item" :class="index === 0 ? 'liked-item-first' : ''">
|
<view class="liked-item" :class="index === 0 ? 'liked-item-first' : ''">
|
||||||
<!-- 作品封面 -->
|
<!-- 作品封面 -->
|
||||||
<view class="liked-cover-wrap" :class="index === 0 ? 'liked-cover-wrap-first' : ''">
|
<view class="liked-cover-wrap" :class="index === 0 ? 'liked-cover-wrap-first' : ''">
|
||||||
<image class="liked-cover" :src="item.cover_url || '/static/nft/placeholder.png'"
|
<LenticularCard
|
||||||
|
v-if="item.is_lenticular"
|
||||||
|
class="liked-lenticular"
|
||||||
|
:layers="getLikedLenticularLayers(item.id)"
|
||||||
|
:transforms="getLikedLenticularTransforms(item.id)"
|
||||||
|
:gyro-source="gyroSourceLabel"
|
||||||
|
:skip-built-in-touch="false"
|
||||||
|
:shimmer-mid-opacity="0.16"
|
||||||
|
@simulate="(x, y) => onLikedLenticularSimulate(item.id, x, y)"
|
||||||
|
/>
|
||||||
|
<image v-else class="liked-cover" :src="item.cover_url || '/static/nft/placeholder.png'"
|
||||||
mode="aspectFill"></image>
|
mode="aspectFill"></image>
|
||||||
<image class="liked-cover-frame" src="/static/square/cangpinkuang1.png"
|
<image class="liked-cover-frame" src="/static/square/cangpinkuang1.png"
|
||||||
mode="aspectFill"></image>
|
mode="aspectFill"></image>
|
||||||
@ -518,6 +528,10 @@ const lenticularLayersByAsset = ref({});
|
|||||||
const activeLenticularId = ref(null);
|
const activeLenticularId = ref(null);
|
||||||
const gyroSourceLabel = ref('device');
|
const gyroSourceLabel = ref('device');
|
||||||
|
|
||||||
|
// 点赞作品光栅卡数据
|
||||||
|
const likedLenticularLayersByAsset = ref({});
|
||||||
|
const likedLenticularTransformsMap = ref({});
|
||||||
|
|
||||||
// 创建单一引擎供模拟倾斜使用
|
// 创建单一引擎供模拟倾斜使用
|
||||||
const lenticularPhysics = ref(null);
|
const lenticularPhysics = ref(null);
|
||||||
const lenticularEngine = ref(null);
|
const lenticularEngine = ref(null);
|
||||||
@ -534,6 +548,86 @@ function getLenticularTransforms(assetId) {
|
|||||||
return lenticularTransformsMap.value[assetId] || {};
|
return lenticularTransformsMap.value[assetId] || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 点赞作品光栅卡相关函数
|
||||||
|
function getLikedLenticularLayers(assetId) {
|
||||||
|
return likedLenticularLayersByAsset.value[assetId] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLikedLenticularTransforms(assetId) {
|
||||||
|
return likedLenticularTransformsMap.value[assetId] || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLikedLenticularSimulate(assetId, x, y) {
|
||||||
|
simulateLikedLenticularTilt(assetId, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
function simulateLikedLenticularTilt(assetId, x, y) {
|
||||||
|
if (!lenticularEngine.value) return;
|
||||||
|
const layers = likedLenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) return;
|
||||||
|
|
||||||
|
lenticularEngine.value.setLayers(layers);
|
||||||
|
const renderState = lenticularEngine.value.feedSimulatedTilt(x, y ? y : 0);
|
||||||
|
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
const rs = renderState.layerOffsets.get(l.id);
|
||||||
|
const op = renderState.layerOpacities.get(l.id);
|
||||||
|
transforms[l.id] = {
|
||||||
|
x: rs ? rs.x : 0,
|
||||||
|
y: rs ? rs.y : 0,
|
||||||
|
opacity: op != null ? op : l.opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
likedLenticularTransformsMap.value = { ...likedLenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadLikedLenticularLayersForAsset(assetId) {
|
||||||
|
const item = likedWorks.value.find(w => w.id === assetId);
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const materialsRes = await getAssetMaterialsApi(assetId);
|
||||||
|
if (materialsRes.code === 200 && materialsRes.data) {
|
||||||
|
const materialsList = Array.isArray(materialsRes.data) ? materialsRes.data : materialsRes.data.materials || [];
|
||||||
|
let subjectUrl = item.cover_url;
|
||||||
|
let bgUrl = '';
|
||||||
|
for (const mat of materialsList) {
|
||||||
|
if (mat.material_type === 'main' && mat.material_url_signed) {
|
||||||
|
subjectUrl = mat.material_url_signed;
|
||||||
|
}
|
||||||
|
if (mat.material_type === 'bg' && mat.material_url_signed) {
|
||||||
|
bgUrl = mat.material_url_signed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bgUrl) {
|
||||||
|
const { buildLenticularLayersTwo } = await import('@/utils/castloveMintForm.js');
|
||||||
|
likedLenticularLayersByAsset.value[assetId] = buildLenticularLayersTwo(bgUrl, subjectUrl);
|
||||||
|
} else {
|
||||||
|
likedLenticularLayersByAsset.value[assetId] = buildLenticularLayers(subjectUrl);
|
||||||
|
}
|
||||||
|
initLikedTransformsForAsset(assetId);
|
||||||
|
} else {
|
||||||
|
likedLenticularLayersByAsset.value[assetId] = buildLenticularLayers(item.cover_url);
|
||||||
|
initLikedTransformsForAsset(assetId);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[myWorks] 获取点赞作品素材列表失败:', e);
|
||||||
|
likedLenticularLayersByAsset.value[assetId] = buildLenticularLayers(item.cover_url);
|
||||||
|
initLikedTransformsForAsset(assetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initLikedTransformsForAsset(assetId) {
|
||||||
|
const layers = likedLenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) return;
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
transforms[l.id] = { x: 0, y: 0, opacity: l.opacity || 1 };
|
||||||
|
}
|
||||||
|
likedLenticularTransformsMap.value = { ...likedLenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
|
|
||||||
async function loadLenticularLayersForAsset(assetId) {
|
async function loadLenticularLayersForAsset(assetId) {
|
||||||
// 需要获取 bg + subject 素材构建 layers
|
// 需要获取 bg + subject 素材构建 layers
|
||||||
// 目前使用 buildLenticularLayers(coverUrl) 作为占位
|
// 目前使用 buildLenticularLayers(coverUrl) 作为占位
|
||||||
@ -650,6 +744,24 @@ function startLenticularRenderLoop() {
|
|||||||
}
|
}
|
||||||
lenticularTransformsMap.value = { ...lenticularTransformsMap.value, [assetId]: transforms };
|
lenticularTransformsMap.value = { ...lenticularTransformsMap.value, [assetId]: transforms };
|
||||||
}
|
}
|
||||||
|
// 遍历点赞作品的光栅卡
|
||||||
|
for (const assetId of Object.keys(likedLenticularLayersByAsset.value)) {
|
||||||
|
const layers = likedLenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) continue;
|
||||||
|
lenticularEngine.value.setLayers(layers);
|
||||||
|
const renderState = lenticularEngine.value.feedSimulatedTilt(0, 0);
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
const rs = renderState.layerOffsets.get(l.id);
|
||||||
|
const op = renderState.layerOpacities.get(l.id);
|
||||||
|
transforms[l.id] = {
|
||||||
|
x: rs ? rs.x : 0,
|
||||||
|
y: rs ? rs.y : 0,
|
||||||
|
opacity: op != null ? op : l.opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
likedLenticularTransformsMap.value = { ...likedLenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
lenticularRafId = requestAnimationFrame(tick);
|
lenticularRafId = requestAnimationFrame(tick);
|
||||||
};
|
};
|
||||||
lenticularRafId = requestAnimationFrame(tick);
|
lenticularRafId = requestAnimationFrame(tick);
|
||||||
@ -667,6 +779,9 @@ const switchLikedTab = async (tab) => {
|
|||||||
if (likedTab.value === tab) return;
|
if (likedTab.value === tab) return;
|
||||||
likedTab.value = tab;
|
likedTab.value = tab;
|
||||||
likedWorks.value = [];
|
likedWorks.value = [];
|
||||||
|
// 清理点赞作品光栅卡数据
|
||||||
|
likedLenticularLayersByAsset.value = {};
|
||||||
|
likedLenticularTransformsMap.value = {};
|
||||||
await loadLikedAssets();
|
await loadLikedAssets();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -726,11 +841,19 @@ const loadLikedAssets = async () => {
|
|||||||
earnings: item.earnings,
|
earnings: item.earnings,
|
||||||
liked_at: item.liked_at,
|
liked_at: item.liked_at,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
is_lenticular: item.is_lenticular ?? false,
|
||||||
// 暂时用排名模拟状态文字
|
// 暂时用排名模拟状态文字
|
||||||
status_text: index < 3 ? '排名进榜' : '潜力待挖',
|
status_text: index < 3 ? '排名进榜' : '潜力待挖',
|
||||||
score: item.like_count,
|
score: item.like_count,
|
||||||
reward: Math.floor(item.earnings || 0),
|
reward: Math.floor(item.earnings || 0),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// 为每个光栅卡加载层级数据
|
||||||
|
for (const item of likedWorks.value) {
|
||||||
|
if (item.is_lenticular) {
|
||||||
|
loadLikedLenticularLayersForAsset(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('加载点赞作品失败:', err);
|
console.error('加载点赞作品失败:', err);
|
||||||
@ -1318,6 +1441,17 @@ onShow(() => {
|
|||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.liked-lenticular {
|
||||||
|
width: 90%;
|
||||||
|
height: 90%;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
transform: rotate(-22deg);
|
||||||
|
transform-origin: center center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.liked-cover-frame {
|
.liked-cover-frame {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user